From b575036fe804f14b78da74897a74b010cc94f730 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 16 Sep 2026 11:49:35 +0200 Subject: Implement named blocks --- boot/name_analysis.cc | 73 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 6 deletions(-) (limited to 'boot/name_analysis.cc') diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc index 8820684..9ba030c 100644 --- a/boot/name_analysis.cc +++ b/boot/name_analysis.cc @@ -48,8 +48,14 @@ namespace elna::boot return "Trait '#" + this->name + "' not declared"; case undeclared_symbol: return "Symbol '" + this->name + "' not declared"; + case undeclared_label: + return "Label '" + this->name + "' not declared"; case not_a_type: return "'" + this->name + "' is not a type"; + case not_a_label: + return "'" + this->name + "' is not a label"; + case break_leaves_defer: + return "'break' cannot leave a defer statement"; default: __builtin_unreachable(); } @@ -781,9 +787,64 @@ namespace elna::boot void resolving_visitor::visit(defer_statement *statement) { - for (auto *block_statement : statement->statements) + ++this->defer_depth; + for (auto *body_statement : statement->statements) { - block_statement->accept(this); + body_statement->accept(this); + } + --this->defer_depth; + } + + void resolving_visitor::visit(block_statement *statement) + { + const std::string& label_name = statement->name.name(); + + this->bag.enter(); + + auto label_symbol = std::make_shared(this->defer_depth); + label_symbol->position.emplace(statement->name.position()); + label_symbol->file = this->module_file; + + if (!this->bag.enter(label_name, label_symbol)) + { + auto original = this->bag.lookup(label_name); + symbol_declaration_error::redefinition original_definition{ + .original = original->position, + .file = this->redefinition_file(original) + }; + add_error(statement->name.position(), + label_name, original_definition); + } + for (auto *body_statement : statement->statements) + { + body_statement->accept(this); + } + this->bag.leave(); + } + + void resolving_visitor::visit(break_statement *statement) + { + const std::string& label_name = statement->label.name(); + const source_position position = statement->label.position(); + const std::shared_ptr symbol = this->bag.lookup(label_name); + + if (symbol == nullptr) + { + add_error(position, label_name, + symbol_declaration_error::kind::undeclared_label); + return; + } + auto label_symbol = symbol->is_label(); + + if (label_symbol == nullptr) + { + add_error(position, label_name, + symbol_declaration_error::kind::not_a_label); + } + else if (label_symbol->defer_depth != this->defer_depth) + { + add_error(position, label_name, + symbol_declaration_error::kind::break_leaves_defer); } } @@ -800,16 +861,16 @@ namespace elna::boot { case_label->accept(this); } - for (auto *block_statement : case_block.statements) + for (auto *body_statement : case_block.statements) { - block_statement->accept(this); + body_statement->accept(this); } } if (statement->alternative != nullptr) { - for (auto *block_statement : *statement->alternative) + for (auto *body_statement : *statement->alternative) { - block_statement->accept(this); + body_statement->accept(this); } } } -- cgit v1.2.3