From b7dd49c1d5832ac7d82edba27316884ab53e614c Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 10 Jul 2026 17:06:21 +0200 Subject: Report if the base type of a record is not a record --- boot/semantic.cc | 279 +++++++++++-------------------------------------------- 1 file changed, 53 insertions(+), 226 deletions(-) (limited to 'boot/semantic.cc') 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(definition->identifier.name, definition->position()); + add_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, std::vector& 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 alias_path; + auto unresolved_type = this->bag.lookup(declaration->identifier.name)->is_type()->symbol.get(); + + if (!check_unresolved_symbol(unresolved_type, alias_path)) { - type->accept(this); + add_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 alias_path; - auto unresolved_type = this->bag.lookup(definition->identifier.name)->is_type()->symbol.get(); - - if (!check_unresolved_symbol(unresolved_type, alias_path)) + if (expression->base.has_value()) { - add_error(alias_path, definition->position()); + type base_type = inner_aliased_type(this->bag.lookup(expression->base.value())->is_type()->symbol); + if (base_type.get() == nullptr) + { + add_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(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(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(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(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 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(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(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(variable_type)); this->bag.enter("parameters", std::make_shared(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 *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(type_identifier) }).second) { - add_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(declaration->identifier.name, declaration->position()); } } } -- cgit v1.2.3