diff options
Diffstat (limited to 'frontend/semantic.cc')
| -rw-r--r-- | frontend/semantic.cc | 644 |
1 files changed, 0 insertions, 644 deletions
diff --git a/frontend/semantic.cc b/frontend/semantic.cc deleted file mode 100644 index 36c75b8..0000000 --- a/frontend/semantic.cc +++ /dev/null @@ -1,644 +0,0 @@ -/* Name analysis. - Copyright (C) 2025 Free Software Foundation, Inc. - -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. - -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -#include "elna/frontend/semantic.h" - -#include <algorithm> -#include <set> - -namespace elna::frontend -{ - undeclared_error::undeclared_error(const std::string& identifier, const char *path, const struct position position) - : error(path, position), identifier(identifier) - { - } - - std::string undeclared_error::what() const - { - return "Type '" + identifier + "' not declared"; - } - - already_declared_error::already_declared_error(const std::string& identifier, - const char *path, const struct position position) - : error(path, position), identifier(identifier) - { - } - - std::string already_declared_error::what() const - { - return "Symbol '" + identifier + "' has been already declared"; - } - - field_duplication_error::field_duplication_error(const std::string& field_name, - const char *path, const struct position position) - : error(path, position), field_name(field_name) - { - } - - std::string field_duplication_error::what() const - { - return "Repeated field name '" + field_name + "'"; - } - - cyclic_declaration_error::cyclic_declaration_error(const std::vector<std::string>& cycle, - const char *path, const struct position position) - : error(path, position), cycle(cycle) - { - } - - std::string cyclic_declaration_error::what() const - { - auto segment = std::cbegin(this->cycle); - std::string message = "Type declaration forms a cycle: " + *segment; - - ++segment; - for (; segment != std::cend(this->cycle); ++segment) - { - message += " -> " + *segment; - } - return message; - } - - return_error::return_error(const std::string& identifier, const char *path, const struct position position) - : error(path, position), identifier(identifier) - { - } - - std::string return_error::what() const - { - return "Procedure '" + identifier + "' is expected to return, but does not have a return statement"; - } - - variable_initializer_error::variable_initializer_error(const char *path, const struct position position) - : error(path, position) - { - } - - std::string variable_initializer_error::what() const - { - return "Only one variable can be initialized"; - } - - type_analysis_visitor::type_analysis_visitor(const char *path, symbol_bag bag) - : error_container(path), bag(bag) - { - } - - void type_analysis_visitor::visit(program *program) - { - visit(static_cast<unit *>(program)); - } - - void type_analysis_visitor::visit(procedure_declaration *definition) - { - if (definition->body.has_value() && definition->heading().return_type.proper_type != nullptr) - { - for (statement *const statement : definition->body.value().body()) - { - statement->accept(this); - } - if (!this->returns) - { - add_error<return_error>(definition->identifier.name, this->input_file, definition->position()); - } - } - } - - void type_analysis_visitor::visit(assign_statement *) - { - } - - void type_analysis_visitor::visit(if_statement *) - { - } - - void type_analysis_visitor::visit(while_statement *) - { - } - - void type_analysis_visitor::visit(return_statement *) - { - this->returns = true; - } - - void type_analysis_visitor::visit(defer_statement *) - { - } - - void type_analysis_visitor::visit(case_statement *) - { - } - - void type_analysis_visitor::visit(procedure_call *) - { - } - - bool type_analysis_visitor::check_unresolved_symbol(std::shared_ptr<alias_type> alias, - std::vector<std::string>& alias_path) - { - if (std::find(std::cbegin(alias_path), std::cend(alias_path), alias->name) != std::cend(alias_path)) - { - return false; - } - alias_path.push_back(alias->name); - - if (auto another_alias = alias->reference.get<alias_type>()) - { - return check_unresolved_symbol(another_alias, alias_path); - } - return true; - } - - void type_analysis_visitor::visit(unit *unit) - { - for (type_declaration *const type : unit->types) - { - type->accept(this); - } - for (procedure_declaration *const procedure : unit->procedures) - { - this->returns = false; - procedure->accept(this); - } - } - - void type_analysis_visitor::visit(type_declaration *definition) - { - std::vector<std::string> alias_path; - auto unresolved_type = this->bag.lookup(definition->identifier.name)->is_type()->symbol.get<alias_type>(); - - if (!check_unresolved_symbol(unresolved_type, alias_path)) - { - add_error<cyclic_declaration_error>(alias_path, this->input_file, definition->position()); - } - } - - name_analysis_visitor::name_analysis_visitor(const char *path, symbol_bag bag) - : error_container(path), bag(bag) - { - } - - procedure_type name_analysis_visitor::build_procedure(procedure_type_expression& type_expression) - { - procedure_type::return_t result_return; - - if (type_expression.return_type.no_return) - { - result_return = procedure_type::return_t(std::monostate{}); - } - else if (type_expression.return_type.proper_type != nullptr) - { - type_expression.return_type.proper_type->accept(this); - result_return = procedure_type::return_t(this->current_type); - } - else - { - result_return = procedure_type::return_t(); - } - procedure_type result_type = procedure_type(result_return); - - for (struct type_expression *parameter : type_expression.parameters) - { - parameter->accept(this); - result_type.parameters.push_back(this->current_type); - } - return result_type; - } - - void name_analysis_visitor::visit(program *program) - { - visit(static_cast<unit *>(program)); - - for (statement *const statement : program->body) - { - statement->accept(this); - } - } - - void name_analysis_visitor::visit(type_declaration *definition) - { - definition->body().accept(this); - auto resolved = this->bag.resolve(definition->identifier.name, this->current_type); - auto info = std::make_shared<type_info>(type(resolved)); - - info->exported = definition->identifier.exported; - this->bag.enter(definition->identifier.name, info); - } - - void name_analysis_visitor::visit(named_type_expression *type_expression) - { - auto unresolved_alias = this->bag.declared(type_expression->name); - - if (unresolved_alias != nullptr) - { - this->current_type = type(unresolved_alias); - } - else if (auto from_symbol_table = this->bag.lookup(type_expression->name)) - { - this->current_type = from_symbol_table->is_type()->symbol; - } - else - { - add_error<undeclared_error>(type_expression->name, this->input_file, type_expression->position()); - this->current_type = type(); - } - } - - void name_analysis_visitor::visit(pointer_type_expression *type_expression) - { - type_expression->base().accept(this); - this->current_type = type(std::make_shared<pointer_type>(this->current_type)); - } - - void name_analysis_visitor::visit(array_type_expression *type_expression) - { - type_expression->base().accept(this); - this->current_type = type(std::make_shared<array_type>(this->current_type, type_expression->size)); - } - - std::vector<type_field> name_analysis_visitor::build_composite_type(const std::vector<field_declaration>& fields) - { - std::vector<type_field> result; - std::set<std::string> field_names; - - for (auto& field : fields) - { - if (field_names.find(field.first) != field_names.cend()) - { - add_error<field_duplication_error>(field.first, this->input_file, field.second->position()); - } - else - { - field_names.insert(field.first); - field.second->accept(this); - result.push_back(std::make_pair(field.first, this->current_type)); - } - } - return result; - } - - void name_analysis_visitor::visit(record_type_expression *type_expression) - { - auto result_type = std::make_shared<record_type>(); - - result_type->fields = build_composite_type(type_expression->fields); - - this->current_type = type(result_type); - } - - void name_analysis_visitor::visit(union_type_expression *type_expression) - { - auto result_type = std::make_shared<union_type>(); - - result_type->fields = build_composite_type(type_expression->fields); - - this->current_type = type(result_type); - } - - void name_analysis_visitor::visit(procedure_type_expression *type_expression) - { - std::shared_ptr<procedure_type> result_type = - std::make_shared<procedure_type>(std::move(build_procedure(*type_expression))); - - this->current_type = type(result_type); - } - - void name_analysis_visitor::visit(enumeration_type_expression *type_expression) - { - std::shared_ptr<enumeration_type> result_type = std::make_shared<enumeration_type>(type_expression->members); - - this->current_type = type(result_type); - } - - void name_analysis_visitor::visit(variable_declaration *declaration) - { - declaration->variable_type().accept(this); - - for (const auto& variable_identifier : declaration->identifiers) - { - auto variable_symbol = std::make_shared<variable_info>(this->current_type, declaration->is_extern); - - variable_symbol->exported = variable_identifier.exported; - if (!this->bag.enter(variable_identifier.name, variable_symbol)) - { - add_error<already_declared_error>(variable_identifier.name, this->input_file, - declaration->position()); - } - } - } - - void name_analysis_visitor::visit(constant_declaration *definition) - { - definition->body().accept(this); - auto constant_symbol = std::make_shared<constant_info>(this->current_literal); - - constant_symbol->exported = definition->identifier.exported; - this->bag.enter(definition->identifier.name, constant_symbol); - } - - void name_analysis_visitor::visit(procedure_declaration *definition) - { - std::shared_ptr<procedure_info> info; - auto heading = build_procedure(definition->heading()); - - if (definition->body.has_value()) - { - info = std::make_shared<procedure_info>(heading, definition->parameter_names, this->bag.enter()); - - for (constant_declaration *const constant : definition->body.value().constants()) - { - constant->accept(this); - } - for (variable_declaration *const variable : definition->body.value().variables()) - { - variable->accept(this); - } - for (statement *const statement : definition->body.value().body()) - { - statement->accept(this); - } - this->bag.leave(); - } - else - { - info = std::make_shared<procedure_info>(heading, definition->parameter_names); - } - info->exported = definition->identifier.exported; - this->bag.enter(definition->identifier.name, info); - } - - void name_analysis_visitor::visit(assign_statement *statement) - { - statement->lvalue().accept(this); - statement->rvalue().accept(this); - } - - void name_analysis_visitor::visit(if_statement *statement) - { - statement->body().prerequisite().accept(this); - for (struct statement *const statement : statement->body().statements) - { - statement->accept(this); - } - for (const auto branch : statement->branches) - { - branch->prerequisite().accept(this); - - for (struct statement *const statement : branch->statements) - { - statement->accept(this); - } - } - if (statement->alternative != nullptr) - { - for (struct statement *const statement : *statement->alternative) - { - statement->accept(this); - } - } - } - - void name_analysis_visitor::visit(import_declaration *) - { - } - - void name_analysis_visitor::visit(while_statement *statement) - { - statement->body().prerequisite().accept(this); - for (struct statement *const statement : statement->body().statements) - { - statement->accept(this); - } - for (const auto branch : statement->branches) - { - branch->prerequisite().accept(this); - - for (struct statement *const statement : branch->statements) - { - statement->accept(this); - } - } - } - - void name_analysis_visitor::visit(return_statement *statement) - { - statement->return_expression().accept(this); - } - - void name_analysis_visitor::visit(defer_statement *statement) - { - for (struct statement *const statement : statement->statements) - { - statement->accept(this); - } - } - - void name_analysis_visitor::visit(case_statement *statement) - { - statement->condition().accept(this); - for (const switch_case& case_block : statement->cases) - { - for (expression *const case_label : case_block.labels) - { - case_label->accept(this); - } - for (struct statement *const statement : case_block.statements) - { - statement->accept(this); - } - } - if (statement->alternative != nullptr) - { - for (struct statement *const statement : *statement->alternative) - { - statement->accept(this); - } - } - } - - void name_analysis_visitor::visit(procedure_call *call) - { - call->callable().accept(this); - for (expression *const argument: call->arguments) - { - argument->accept(this); - } - } - - void name_analysis_visitor::visit(unit *unit) - { - for (type_declaration *const type : unit->types) - { - type->accept(this); - } - for (variable_declaration *const variable : unit->variables) - { - variable->accept(this); - } - for (procedure_declaration *const procedure : unit->procedures) - { - procedure->accept(this); - } - } - - void name_analysis_visitor::visit(traits_expression *trait) - { - if (!trait->parameters.empty()) - { - trait->parameters.front()->accept(this); - trait->types.push_back(this->current_type); - } - } - - void name_analysis_visitor::visit(cast_expression *expression) - { - expression->value().accept(this); - expression->target().accept(this); - expression->expression_type = this->current_type; - } - - void name_analysis_visitor::visit(binary_expression *expression) - { - expression->lhs().accept(this); - expression->rhs().accept(this); - } - - void name_analysis_visitor::visit(unary_expression *expression) - { - expression->operand().accept(this); - } - - void name_analysis_visitor::visit(variable_expression *) - { - } - - void name_analysis_visitor::visit(array_access_expression *expression) - { - expression->base().accept(this); - expression->index().accept(this); - } - - void name_analysis_visitor::visit(field_access_expression *expression) - { - expression->base().accept(this); - } - - void name_analysis_visitor::visit(dereference_expression *expression) - { - expression->base().accept(this); - } - - void name_analysis_visitor::visit(literal<std::int32_t> *literal) - { - this->current_literal = literal->value; - } - - void name_analysis_visitor::visit(literal<std::uint32_t> *literal) - { - this->current_literal = literal->value; - } - - void name_analysis_visitor::visit(literal<double> *literal) - { - this->current_literal = literal->value; - } - - void name_analysis_visitor::visit(literal<bool> *literal) - { - this->current_literal = literal->value; - } - - void name_analysis_visitor::visit(literal<unsigned char> *literal) - { - this->current_literal = literal->value; - } - - void name_analysis_visitor::visit(literal<std::nullptr_t> *literal) - { - this->current_literal = literal->value; - } - - void name_analysis_visitor::visit(literal<std::string> *literal) - { - this->current_literal = literal->value; - } - - declaration_visitor::declaration_visitor(const char *path) - : error_container(path) - { - } - - void declaration_visitor::visit(program *program) - { - visit(static_cast<unit *>(program)); - } - - void declaration_visitor::visit(import_declaration *) - { - } - - void declaration_visitor::visit(unit *unit) - { - for (import_declaration *const _import : unit->imports) - { - _import->accept(this); - } - for (type_declaration *const type : unit->types) - { - type->accept(this); - } - for (variable_declaration *const variable : unit->variables) - { - variable->accept(this); - } - for (procedure_declaration *const procedure : unit->procedures) - { - procedure->accept(this); - } - } - - void declaration_visitor::visit(type_declaration *definition) - { - const std::string& type_identifier = definition->identifier.name; - - if (!this->unresolved.insert({ type_identifier, std::make_shared<alias_type>(type_identifier) }).second) - { - add_error<already_declared_error>(definition->identifier.name, this->input_file, - definition->position()); - } - } - - void declaration_visitor::visit(variable_declaration *declaration) - { - if (declaration->has_initializer() && declaration->identifiers.size() > 1) - { - add_error<variable_initializer_error>(this->input_file, declaration->position()); - } - } - - void declaration_visitor::visit(procedure_declaration *definition) - { - if (!definition->body.has_value()) - { - return; - } - for (variable_declaration *const variable : definition->body.value().variables()) - { - variable->accept(this); - } - } -} |
