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/ast.cc | 426 ++++++++++++++++++++++++++++++++++++++++++++----------- boot/parser.yy | 25 ++-- boot/semantic.cc | 279 +++++++----------------------------- boot/symbol.cc | 17 +++ 4 files changed, 423 insertions(+), 324 deletions(-) (limited to 'boot') diff --git a/boot/ast.cc b/boot/ast.cc index b6ce4b3..4270a3b 100644 --- a/boot/ast.cc +++ b/boot/ast.cc @@ -24,11 +24,6 @@ namespace elna::boot __builtin_unreachable(); } - void empty_visitor::visit(type_expression *) - { - not_implemented(); - } - void empty_visitor::visit(array_type_expression *) { not_implemented(); @@ -204,6 +199,300 @@ namespace elna::boot not_implemented(); } + void walking_visitor::visit(import_declaration *) + { + } + + void walking_visitor::visit(procedure_declaration *declaration) + { + for (const field_declaration& parameter : declaration->heading().parameters) + { + parameter.second->accept(this); + } + if (declaration->heading().return_type.proper_type != nullptr) + { + declaration->heading().return_type.proper_type->accept(this); + } + if (declaration->body.has_value()) + { + for (constant_declaration *const constant : declaration->body.value().constants()) + { + constant->accept(this); + } + for (variable_declaration *const variable : declaration->body.value().variables()) + { + variable->accept(this); + } + for (statement *const statement : declaration->body.value().statements()) + { + statement->accept(this); + } + } + } + + void walking_visitor::visit(assign_statement *statement) + { + statement->lvalue().accept(this); + statement->rvalue().accept(this); + } + + void walking_visitor::visit(if_statement *statement) + { + statement->branch().prerequisite().accept(this); + for (struct statement *const branch_statement : statement->branch().statements) + { + branch_statement->accept(this); + } + for (conditional_statements *const branch : statement->branches) + { + branch->prerequisite().accept(this); + + for (struct statement *const branch_statement : branch->statements) + { + branch_statement->accept(this); + } + } + if (statement->alternative != nullptr) + { + for (struct statement *const branch_statement : *statement->alternative) + { + branch_statement->accept(this); + } + } + } + + void walking_visitor::visit(while_statement *statement) + { + statement->branch().prerequisite().accept(this); + for (struct statement *const branch_statement : statement->branch().statements) + { + branch_statement->accept(this); + } + for (conditional_statements *const branch : statement->branches) + { + branch->prerequisite().accept(this); + + for (struct statement *const branch_statement : branch->statements) + { + branch_statement->accept(this); + } + } + } + + void walking_visitor::visit(return_statement *statement) + { + statement->return_expression().accept(this); + } + + void walking_visitor::visit(defer_statement *statement) + { + for (struct statement *const block_statement : statement->statements) + { + block_statement->accept(this); + } + } + + void walking_visitor::visit(empty_statement *) + { + } + + void walking_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 block_statement : case_block.statements) + { + block_statement->accept(this); + } + } + if (statement->alternative != nullptr) + { + for (struct statement *const block_statement : *statement->alternative) + { + block_statement->accept(this); + } + } + } + + void walking_visitor::visit(procedure_call *call) + { + call->callable().accept(this); + for (expression *const argument : call->arguments) + { + argument->accept(this); + } + } + + void walking_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 (constant_declaration *const constant : unit->constants) + { + constant->accept(this); + } + for (procedure_declaration *const procedure : unit->procedures) + { + procedure->accept(this); + } + if (unit->entry_point.has_value()) + { + for (statement *const entry_statement : unit->entry_point.value()) + { + entry_statement->accept(this); + } + } + } + + void walking_visitor::visit(type_declaration *declaration) + { + declaration->underlying_type().accept(this); + } + + void walking_visitor::visit(variable_declaration *declaration) + { + declaration->variable_type().accept(this); + if (declaration->initializer != nullptr) + { + declaration->initializer->accept(this); + } + } + + void walking_visitor::visit(constant_declaration *declaration) + { + declaration->initializer().accept(this); + } + + void walking_visitor::visit(array_type_expression *expression) + { + expression->base().accept(this); + } + + void walking_visitor::visit(pointer_type_expression *expression) + { + expression->base().accept(this); + } + + void walking_visitor::visit(record_type_expression *expression) + { + for (const field_declaration& field : expression->fields) + { + field.second->accept(this); + } + } + + void walking_visitor::visit(union_type_expression *expression) + { + for (const field_declaration& field : expression->fields) + { + field.second->accept(this); + } + } + + void walking_visitor::visit(procedure_type_expression *expression) + { + for (const field_declaration& field : expression->parameters) + { + field.second->accept(this); + } + if (expression->return_type.proper_type != nullptr) + { + expression->return_type.proper_type->accept(this); + } + } + + void walking_visitor::visit(enumeration_type_expression *) + { + } + + void walking_visitor::visit(cast_expression *expression) + { + expression->value().accept(this); + expression->target().accept(this); + } + + void walking_visitor::visit(traits_expression *trait) + { + if (!trait->parameters.empty()) + { + trait->parameters.front()->accept(this); + } + } + + void walking_visitor::visit(binary_expression *expression) + { + expression->lhs().accept(this); + expression->rhs().accept(this); + } + + void walking_visitor::visit(unary_expression *expression) + { + expression->operand().accept(this); + } + + void walking_visitor::visit(named_expression *) + { + } + + void walking_visitor::visit(array_access_expression *expression) + { + expression->base().accept(this); + expression->index().accept(this); + } + + void walking_visitor::visit(field_access_expression *expression) + { + expression->base().accept(this); + } + + void walking_visitor::visit(dereference_expression *expression) + { + expression->base().accept(this); + } + + void walking_visitor::visit(literal *) + { + } + + void walking_visitor::visit(literal *) + { + } + + void walking_visitor::visit(literal *) + { + } + + void walking_visitor::visit(literal *) + { + } + + void walking_visitor::visit(literal *) + { + } + + void walking_visitor::visit(literal *) + { + } + + void walking_visitor::visit(literal *) + { + } + node::node(const struct position position) : source_position(position) { @@ -288,43 +577,6 @@ namespace elna::boot return nullptr; } - void type_expression::accept(parser_visitor *visitor) - { - if (named_expression *node = is_named()) - { - return visitor->visit(node); - } - else if (array_type_expression *node = is_array()) - { - return visitor->visit(node); - } - else if (pointer_type_expression *node = is_pointer()) - { - return visitor->visit(node); - } - else if (record_type_expression *node = is_record()) - { - return visitor->visit(node); - } - else if (union_type_expression *node = is_union()) - { - return visitor->visit(node); - } - else if (procedure_type_expression *node = is_procedure()) - { - return visitor->visit(node); - } - else if (enumeration_type_expression *node = is_enumeration()) - { - return visitor->visit(node); - } - __builtin_unreachable(); - } - - type_expression::~type_expression() - { - } - array_type_expression::array_type_expression(const struct position position, type_expression *base, const std::uint32_t size) : node(position), m_base(base), size(size) @@ -417,8 +669,8 @@ namespace elna::boot variable_declaration::variable_declaration(const struct position position, std::vector&& identifier, std::shared_ptr variable_type, - expression *body) - : node(position), m_variable_type(variable_type), identifiers(std::move(identifier)), body(body) + expression *initializer) + : node(position), m_variable_type(variable_type), identifiers(std::move(identifier)), initializer(initializer) { } @@ -436,7 +688,7 @@ namespace elna::boot bool variable_declaration::has_initializer() const { - return this->is_extern || this->body != nullptr; + return this->is_extern || this->initializer != nullptr; } type_expression& variable_declaration::variable_type() @@ -450,8 +702,8 @@ namespace elna::boot } constant_declaration::constant_declaration(const struct position position, identifier_definition identifier, - expression *body) - : declaration(position, identifier), m_body(body) + expression *initializer) + : declaration(position, identifier), m_initializer(initializer) { } @@ -460,14 +712,14 @@ namespace elna::boot visitor->visit(this); } - expression& constant_declaration::body() + expression& constant_declaration::initializer() { - return *m_body; + return *m_initializer; } constant_declaration::~constant_declaration() { - delete m_body; + delete m_initializer; } procedure_type_expression::procedure_type_expression(const struct position position, @@ -511,8 +763,9 @@ namespace elna::boot } procedure_declaration::procedure_declaration(const struct position position, identifier_definition identifier, - procedure_type_expression *heading, block&& body) - : declaration(position, identifier), m_heading(heading), body(std::make_optional(std::move(body))) + procedure_type_expression *heading, procedure_body&& body) + : declaration(position, identifier), m_heading(heading), + body(std::make_optional(std::move(body))) { } @@ -538,14 +791,14 @@ namespace elna::boot } type_declaration::type_declaration(const struct position position, identifier_definition identifier, - type_expression *body) - : declaration(position, identifier), m_body(body) + type_expression *underlying_type) + : declaration(position, identifier), m_underlying_type(underlying_type) { } type_declaration::~type_declaration() { - delete m_body; + delete m_underlying_type; } void type_declaration::accept(parser_visitor *visitor) @@ -553,55 +806,56 @@ namespace elna::boot visitor->visit(this); } - type_expression& type_declaration::body() + type_expression& type_declaration::underlying_type() { - return *m_body; + return *m_underlying_type; } - block::block(std::vector&& constants, std::vector&& variables, - std::vector&& body) - : m_variables(std::move(variables)), m_constants(std::move(constants)), m_body(std::move(body)) + procedure_body::procedure_body(std::vector&& constants, + std::vector&& variables, std::vector&& statements) + : m_variables(std::move(variables)), m_constants(std::move(constants)), m_statements(std::move(statements)) { } - block::block(std::vector&& constants, std::vector&& variables) - : m_variables(std::move(variables)), m_constants(std::move(constants)) + procedure_body::procedure_body(std::vector&& constants, + std::vector&& variables) + : procedure_body(std::move(constants), std::move(variables), std::vector{}) { } - block::block(block&& that) + procedure_body::procedure_body(procedure_body&& that) : m_variables(std::move(that.m_variables)), m_constants(std::move(that.m_constants)), - m_body(std::move(that.m_body)) + m_statements(std::move(that.m_statements)) { } - block& block::operator=(block&& that) + procedure_body& procedure_body::operator=(procedure_body&& that) { std::swap(m_variables, that.m_variables); std::swap(m_constants, that.m_constants); - std::swap(m_body, that.m_body); + std::swap(m_statements, that.m_statements); return *this; } - const std::vector& block::variables() + const std::vector& procedure_body::variables() { return m_variables; } - const std::vector& block::constants() + const std::vector& procedure_body::constants() { return m_constants; } - const std::vector& block::body() + const std::vector& procedure_body::statements() { - return m_body; + return m_statements; } - block::~block() + procedure_body::~procedure_body() { - for (statement *body_statement : this->body()) + for (statement *body_statement : this->statements()) { delete body_statement; } @@ -620,8 +874,8 @@ namespace elna::boot { } - unit::unit(const struct position position, std::vector&& body) - : node(position), body(std::make_optional>(std::move(body))) + unit::unit(const struct position position, std::vector&& entry_point) + : node(position), entry_point(std::make_optional>(std::move(entry_point))) { } @@ -1073,10 +1327,10 @@ namespace elna::boot delete m_rvalue; } - if_statement::if_statement(const struct position position, conditional_statements *body, + if_statement::if_statement(const struct position position, conditional_statements *branch, std::vector&& branches, std::vector *alternative) - : node(position), m_body(body), branches(std::move(branches)), alternative(alternative) + : node(position), m_branch(branch), branches(std::move(branches)), alternative(alternative) { } @@ -1085,15 +1339,15 @@ namespace elna::boot visitor->visit(this); } - conditional_statements& if_statement::body() + conditional_statements& if_statement::branch() { - return *m_body; + return *m_branch; } if_statement::~if_statement() { - delete m_body; - for (const auto branch : branches) + delete m_branch; + for (conditional_statements *const branch : branches) { delete branch; } @@ -1110,9 +1364,9 @@ namespace elna::boot visitor->visit(this); } - while_statement::while_statement(const struct position position, conditional_statements *body, + while_statement::while_statement(const struct position position, conditional_statements *branch, std::vector&& branches) - : node(position), m_body(body), branches(std::move(branches)) + : node(position), m_branch(branch), branches(std::move(branches)) { } @@ -1121,15 +1375,15 @@ namespace elna::boot visitor->visit(this); } - conditional_statements& while_statement::body() + conditional_statements& while_statement::branch() { - return *m_body; + return *m_branch; } while_statement::~while_statement() { - delete m_body; - for (const auto branch : branches) + delete m_branch; + for (conditional_statements *const branch : branches) { delete branch; } diff --git a/boot/parser.yy b/boot/parser.yy index 42840ff..6ada702 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -148,7 +148,7 @@ along with GCC; see the file COPYING3. If not see %type > procedure_part; %type type_declaration; %type > type_declarations type_part; -%type > block; +%type > procedure_body; %type field_declaration; %type > optional_fields required_fields; %type > elsif_then_statements elsif_do_statements; @@ -162,32 +162,33 @@ along with GCC; see the file COPYING3. If not see program: import_part constant_part type_part variable_part procedure_part statement_part "end" "." { + boot::unit *tree; if ($6) { - boot::unit *tree = new boot::unit(boot::make_position(@1)); - tree->body = std::make_optional>(std::move(*$6.release())); - - driver.tree.reset(tree); + tree = new boot::unit(boot::make_position(@1), + std::move(*$6.release())); } else { - driver.tree.reset(new boot::unit(boot::make_position(@1))); + tree = new boot::unit(boot::make_position(@1)); } + driver.tree.reset(tree); + std::swap(driver.tree->imports, $1); std::swap(driver.tree->constants, $2); std::swap(driver.tree->types , $3); std::swap(driver.tree->variables, $4); std::swap(driver.tree->procedures, $5); } -block: constant_part variable_part statement_part "end" +procedure_body: constant_part variable_part statement_part "end" { if ($3) { - $$ = std::make_unique(std::move($1), std::move($2), std::move(*$3.release())); + $$ = std::make_unique(std::move($1), std::move($2), std::move(*$3.release())); } else { - $$ = std::make_unique(std::move($1), std::move($2)); + $$ = std::make_unique(std::move($1), std::move($2)); } } statement_part: @@ -221,7 +222,7 @@ procedure_heading: "(" optional_fields ")" return_declaration $$ = new boot::procedure_type_expression(boot::make_position(@1), std::move($2), std::move($4)); } procedure_declaration: - "proc" identifier_definition procedure_heading block + "proc" identifier_definition procedure_heading procedure_body { $$ = new boot::procedure_declaration(boot::make_position(@1), std::move($2), $3, std::move(*$4)); @@ -251,7 +252,7 @@ elsif_do_statements: std::swap($5, $$); $$.emplace($$.begin(), branch); } - | {} + | /* no branches */ {} else_statements: "else" statements { $$ = new std::vector(std::move($2)); } | { $$ = nullptr; } @@ -262,7 +263,7 @@ elsif_then_statements: std::swap($5, $$); $$.emplace($$.begin(), branch); } - | {} + | /* no branches */ {} return_statement: "return" expression { $$ = new boot::return_statement(boot::make_position(@1), $2); } literal: 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()); } } } diff --git a/boot/symbol.cc b/boot/symbol.cc index d01eb8e..512cf04 100644 --- a/boot/symbol.cc +++ b/boot/symbol.cc @@ -429,4 +429,21 @@ namespace elna::boot { this->imports.push_front(bag.symbols); } + + type inner_aliased_type(std::shared_ptr alias) + { + return inner_aliased_type(alias->reference); + } + + type inner_aliased_type(type alias) + { + if (auto aliased = alias.get()) + { + return inner_aliased_type(aliased); + } + else + { + return alias; + } + } } -- cgit v1.2.3