diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-07-10 17:06:21 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-07-10 17:06:21 +0200 |
| commit | b7dd49c1d5832ac7d82edba27316884ab53e614c (patch) | |
| tree | 24afc27b83974c9322088e5469d2d1894c0eb314 /boot/semantic.cc | |
| parent | 36440faa345bf842c348711325312c2b02e4cc23 (diff) | |
| download | elna-b7dd49c1d5832ac7d82edba27316884ab53e614c.tar.gz | |
Report if the base type of a record is not a record
Diffstat (limited to 'boot/semantic.cc')
| -rw-r--r-- | boot/semantic.cc | 279 |
1 files changed, 53 insertions, 226 deletions
diff --git a/boot/semantic.cc b/boot/semantic.cc index 0530448..42b7b3c 100644 --- a/boot/semantic.cc +++ b/boot/semantic.cc @@ -96,54 +96,26 @@ namespace elna::boot { } - void type_analysis_visitor::visit(procedure_declaration *definition) + void type_analysis_visitor::visit(procedure_declaration *declaration) { - if (definition->body.has_value() && definition->heading().return_type.proper_type != nullptr) + this->returns = false; + walking_visitor::visit(declaration); + + if (declaration->body.has_value()) { - for (statement *const statement : definition->body.value().body()) + if (!this->returns && declaration->heading().return_type.proper_type != nullptr) { - statement->accept(this); - } - if (!this->returns) - { - add_error<return_error>(definition->identifier.name, definition->position()); + add_error<return_error>(declaration->identifier.name, declaration->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 *) + void type_analysis_visitor::visit(return_statement *statement) { + walking_visitor::visit(statement); this->returns = true; } - void type_analysis_visitor::visit(defer_statement *) - { - } - - void type_analysis_visitor::visit(empty_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) { @@ -160,28 +132,32 @@ namespace elna::boot return true; } - void type_analysis_visitor::visit(unit *unit) + void type_analysis_visitor::visit(type_declaration *declaration) { - for (type_declaration *const type : unit->types) + std::vector<std::string> alias_path; + auto unresolved_type = this->bag.lookup(declaration->identifier.name)->is_type()->symbol.get<alias_type>(); + + if (!check_unresolved_symbol(unresolved_type, alias_path)) { - type->accept(this); + add_error<cyclic_declaration_error>(alias_path, declaration->position()); } - for (procedure_declaration *const procedure : unit->procedures) + else { - this->returns = false; - procedure->accept(this); + walking_visitor::visit(declaration); } } - void type_analysis_visitor::visit(type_declaration *definition) + void type_analysis_visitor::visit(record_type_expression *expression) { - 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)) + if (expression->base.has_value()) { - add_error<cyclic_declaration_error>(alias_path, definition->position()); + type base_type = inner_aliased_type(this->bag.lookup(expression->base.value())->is_type()->symbol); + if (base_type.get<record_type>() == nullptr) + { + add_error<base_type_error>(expression->base.value(), expression->position()); + } } + walking_visitor::visit(expression); } name_analysis_visitor::name_analysis_visitor(symbol_bag bag) @@ -222,29 +198,25 @@ namespace elna::boot return result_type; } - void name_analysis_visitor::visit(type_declaration *definition) + void name_analysis_visitor::visit(type_declaration *declaration) { - definition->body().accept(this); - auto resolved = this->bag.resolve(definition->identifier.name, this->current_type); + walking_visitor::visit(declaration); + auto resolved = this->bag.resolve(declaration->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(type_expression *) - { + info->exported = declaration->identifier.exported; + this->bag.enter(declaration->identifier.name, info); } void name_analysis_visitor::visit(pointer_type_expression *expression) { - expression->base().accept(this); + walking_visitor::visit(expression); this->current_type = type(std::make_shared<pointer_type>(this->current_type)); } void name_analysis_visitor::visit(array_type_expression *expression) { - expression->base().accept(this); + walking_visitor::visit(expression); auto result_type = std::make_shared<array_type>(this->current_type, expression->size); this->current_type = type(result_type); @@ -350,9 +322,9 @@ namespace elna::boot void name_analysis_visitor::visit(variable_declaration *declaration) { - declaration->variable_type().accept(this); + walking_visitor::visit(declaration); - for (const auto& variable_identifier : declaration->identifiers) + for (const identifier_definition& variable_identifier : declaration->identifiers) { auto variable_symbol = register_variable(variable_identifier.name, declaration->is_extern, declaration->position()); @@ -360,21 +332,21 @@ namespace elna::boot } } - void name_analysis_visitor::visit(constant_declaration *definition) + void name_analysis_visitor::visit(constant_declaration *declaration) { - definition->body().accept(this); + walking_visitor::visit(declaration); 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); + constant_symbol->exported = declaration->identifier.exported; + this->bag.enter(declaration->identifier.name, constant_symbol); } - void name_analysis_visitor::visit(procedure_declaration *definition) + void name_analysis_visitor::visit(procedure_declaration *declaration) { std::shared_ptr<procedure_info> info; - auto [heading, parameter_names] = build_procedure(definition->heading()); + auto [heading, parameter_names] = build_procedure(declaration->heading()); - if (definition->body.has_value()) + if (declaration->body.has_value()) { info = std::make_shared<procedure_info>(heading, std::move(parameter_names), this->bag.enter()); auto name_iterator = std::cbegin(info->names); @@ -383,21 +355,21 @@ namespace elna::boot while (name_iterator != std::cend(info->names) && type_iterator != std::cend(heading.parameters)) { this->current_type = *type_iterator; - auto variable_symbol = register_variable(*name_iterator, false, definition->heading().position()); + auto variable_symbol = register_variable(*name_iterator, false, declaration->heading().position()); variable_symbol->exported = false; ++name_iterator; ++type_iterator; } - for (constant_declaration *const constant : definition->body.value().constants()) + for (constant_declaration *const constant : declaration->body.value().constants()) { constant->accept(this); } - for (variable_declaration *const variable : definition->body.value().variables()) + for (variable_declaration *const variable : declaration->body.value().variables()) { variable->accept(this); } - for (statement *const statement : definition->body.value().body()) + for (statement *const statement : declaration->body.value().statements()) { statement->accept(this); } @@ -407,101 +379,8 @@ namespace elna::boot { info = std::make_shared<procedure_info>(heading, std::move(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(empty_statement *) - { - } - - 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); - } - } + info->exported = declaration->identifier.exported; + this->bag.enter(declaration->identifier.name, info); } void name_analysis_visitor::visit(procedure_call *call) @@ -536,7 +415,7 @@ namespace elna::boot { procedure->accept(this); } - if (unit->body.has_value()) + if (unit->entry_point.has_value()) { this->bag.enter(); auto variable_type = this->bag.lookup("Int")->is_type()->symbol; @@ -547,7 +426,7 @@ namespace elna::boot variable_type = type(std::make_shared<pointer_type>(variable_type)); this->bag.enter("parameters", std::make_shared<variable_info>(variable_type, false)); - for (statement *const statement : unit->body.value()) + for (statement *const statement : unit->entry_point.value()) { statement->accept(this); } @@ -566,22 +445,10 @@ namespace elna::boot void name_analysis_visitor::visit(cast_expression *expression) { - expression->value().accept(this); - expression->target().accept(this); + walking_visitor::visit(expression); 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(named_expression *expression) { if (auto unresolved_alias = this->bag.declared(expression->name)) @@ -602,22 +469,6 @@ namespace elna::boot } } - 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; @@ -672,39 +523,15 @@ namespace elna::boot { 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) + void declaration_visitor::visit(type_declaration *declaration) { - const std::string& type_identifier = definition->identifier.name; + const std::string& type_identifier = declaration->identifier.name; if (!this->unresolved.insert({ type_identifier, std::make_shared<alias_type>(type_identifier) }).second) { - add_error<already_declared_error>(definition->identifier.name, definition->position()); - } - } - - void declaration_visitor::visit(variable_declaration *) - { - } - - 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); + add_error<already_declared_error>(declaration->identifier.name, declaration->position()); } } } |
