summaryrefslogtreecommitdiff
path: root/frontend/semantic.cc
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-02-02 12:10:40 +0100
committerEugen Wissner <belka@caraus.de>2026-02-04 18:17:47 +0100
commit8e89d33c214e3dad03a86057c2c45a0dc7608ad7 (patch)
tree6d6b52362c6e04a8466a3f393093157f49162588 /frontend/semantic.cc
parent39197fe88ab23bf452e00569ef36b556b787a421 (diff)
downloadelna-8e89d33c214e3dad03a86057c2c45a0dc7608ad7.tar.gz
Split up the rakefile
Diffstat (limited to 'frontend/semantic.cc')
-rw-r--r--frontend/semantic.cc644
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);
- }
- }
-}