diff options
| -rw-r--r-- | boot/ast.cc | 93 | ||||
| -rw-r--r-- | boot/materialization.cc | 20 | ||||
| -rw-r--r-- | boot/name_analysis.cc | 55 | ||||
| -rw-r--r-- | boot/type_check.cc | 25 | ||||
| -rw-r--r-- | boot/validation.cc | 27 | ||||
| -rw-r--r-- | gcc/gcc/elna-generic.cc | 15 | ||||
| -rw-r--r-- | include/elna/boot/ast.h | 33 | ||||
| -rw-r--r-- | include/elna/boot/materialization.h | 4 | ||||
| -rw-r--r-- | include/elna/boot/name_analysis.h | 6 | ||||
| -rw-r--r-- | include/elna/boot/type_check.h | 4 | ||||
| -rw-r--r-- | include/elna/boot/validation.h | 3 |
11 files changed, 112 insertions, 173 deletions
diff --git a/boot/ast.cc b/boot/ast.cc index cd2ac55..87d6313 100644 --- a/boot/ast.cc +++ b/boot/ast.cc @@ -243,7 +243,11 @@ namespace elna::boot } if (declaration->body.has_value()) { - traverse_body(this, declaration->body.value()); + traverse_block(this, declaration->body.value()); + if (declaration->body.value().return_expression != nullptr) + { + declaration->body.value().return_expression->accept(this); + } } } @@ -253,66 +257,54 @@ namespace elna::boot statement->rvalue().accept(this); } - void walking_visitor::traverse_block(block& body) - { - for (variable_declaration *const variable : body.variables) - { - variable->accept(this); - } - for (statement *const body_statement : body.statements) - { - body_statement->accept(this); - } - } - void walking_visitor::visit(if_statement *statement) { statement->branch().prerequisite().accept(this); - traverse_block(statement->branch().body); + traverse_block(this, statement->branch().body); for (conditional_statements& branch : statement->branches) { branch.prerequisite().accept(this); - traverse_block(branch.body); + traverse_block(this, branch.body); } if (statement->alternative != nullptr) { - traverse_block(*statement->alternative); + traverse_block(this, *statement->alternative); } } void walking_visitor::visit(while_statement *statement) { statement->branch().prerequisite().accept(this); - traverse_block(statement->branch().body); + traverse_block(this, statement->branch().body); for (conditional_statements& branch : statement->branches) { branch.prerequisite().accept(this); - traverse_block(branch.body); + traverse_block(this, branch.body); } } void walking_visitor::visit(repeat_statement *statement) { statement->condition().accept(this); - traverse_block(statement->body); + traverse_block(this, statement->body); } void walking_visitor::visit(for_statement *statement) { statement->range().accept(this); - traverse_block(statement->body); + traverse_block(this, statement->body); } void walking_visitor::visit(defer_statement *statement) { - traverse_block(statement->body); + traverse_block(this, statement->body); } void walking_visitor::visit(block_statement *statement) { - traverse_block(statement->body); + traverse_block(this, statement->body); } void walking_visitor::visit(break_statement *) @@ -326,50 +318,30 @@ namespace elna::boot void walking_visitor::visit(case_statement *statement) { statement->condition().accept(this); - for (switch_case& case_block : statement->cases) + for (const switch_case& case_block : statement->cases) { - for (expression *case_label : case_block.labels) - { - case_label->accept(this); - } - traverse_block(case_block.body); + visit_all(this, case_block.labels); + traverse_block(this, case_block.body); } if (statement->alternative != nullptr) { - traverse_block(*statement->alternative); + traverse_block(this, *statement->alternative); } } void walking_visitor::visit(procedure_call *call) { call->callable().accept(this); - for (expression *argument : call->arguments) - { - argument->accept(this); - } + visit_all(this, call->arguments); } void walking_visitor::visit(unit *unit) { - for (import_declaration *_import : unit->imports) - { - _import->accept(this); - } - for (declaration *const unit_declaration : unit->declarations) - { - unit_declaration->accept(this); - } + visit_all(this, unit->imports); + visit_all(this, unit->declarations); if (unit->entry_point.has_value()) { - visit_entry_point(unit); - } - } - - void walking_visitor::visit_entry_point(unit *unit) - { - for (statement *body_statement : unit->entry_point.value()) - { - body_statement->accept(this); + visit_all(this, unit->entry_point.value()); } } @@ -452,10 +424,7 @@ namespace elna::boot void walking_visitor::visit(array_constructor_expression *expression) { - for (auto *element : expression->elements) - { - element->accept(this); - } + visit_all(this, expression->elements); } void walking_visitor::visit(slicing_expression *expression) @@ -1115,20 +1084,10 @@ namespace elna::boot delete this->return_expression; } - void traverse_body(parser_visitor *visitor, const procedure_body& body) + void traverse_block(parser_visitor *visitor, const block& body) { - for (variable_declaration *variable : body.variables) - { - variable->accept(visitor); - } - for (statement *body_statement : body.statements) - { - body_statement->accept(visitor); - } - if (body.return_expression != nullptr) - { - body.return_expression->accept(visitor); - } + visit_all(visitor, body.variables); + visit_all(visitor, body.statements); } unit::unit(const source_position position, diff --git a/boot/materialization.cc b/boot/materialization.cc index 0ca81aa..6eea0d1 100644 --- a/boot/materialization.cc +++ b/boot/materialization.cc @@ -48,6 +48,19 @@ namespace elna::boot { } + void materialization_visitor::visit(unit *unit) + { + visit_all(this, unit->imports); + visit_all(this, unit->declarations); + + this->in_global_scope = false; + if (unit->entry_point.has_value()) + { + visit_all(this, unit->entry_point.value()); + } + this->in_global_scope = true; + } + void materialization_visitor::visit(procedure_declaration *declaration) { this->in_global_scope = false; @@ -144,11 +157,4 @@ namespace elna::boot materialization_error::kind::real_overflow); } } - - void materialization_visitor::visit_entry_point(unit *unit) - { - this->in_global_scope = false; - walking_visitor::visit_entry_point(unit); - this->in_global_scope = true; - } } diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc index 2ee3da1..20f08ee 100644 --- a/boot/name_analysis.cc +++ b/boot/name_analysis.cc @@ -284,10 +284,7 @@ namespace elna::boot void forward_declaration_visitor::visit(unit *unit) { - for (auto *const unit_declaration: unit->declarations) - { - unit_declaration->accept(this); - } + visit_all(this, unit->declarations); } void forward_declaration_visitor::visit(type_declaration *declaration) @@ -733,22 +730,10 @@ namespace elna::boot statement->rvalue().accept(this); } - void resolving_visitor::traverse_block(block& body) - { - for (variable_declaration *const variable : body.variables) - { - variable->accept(this); - } - for (statement *const body_statement : body.statements) - { - body_statement->accept(this); - } - } - void resolving_visitor::visit_block(block& body) { body.symbols = this->bag.enter(); - traverse_block(body); + traverse_block(this, body); this->bag.leave(); } @@ -813,7 +798,7 @@ namespace elna::boot add_error<symbol_declaration_error>(statement->name.position(), label_name, original_definition); } - traverse_block(statement->body); + traverse_block(this, statement->body); this->bag.leave(); } @@ -852,10 +837,7 @@ namespace elna::boot statement->condition().accept(this); for (switch_case& case_block : statement->cases) { - for (expression *case_label : case_block.labels) - { - case_label->accept(this); - } + visit_all(this, case_block.labels); visit_block(case_block.body); } if (statement->alternative != nullptr) @@ -871,10 +853,7 @@ namespace elna::boot { call->type_decoration = procedure->return_type.proper_type; } - for (expression *const argument : call->arguments) - { - argument->accept(this); - } + visit_all(this, call->arguments); this->current_type = type(); } @@ -918,11 +897,9 @@ namespace elna::boot void resolving_visitor::visit(array_constructor_expression *expression) { - for (auto *const element : expression->elements) - { - element->accept(this); - } + visit_all(this, expression->elements); const type element_type = expression->elements.front()->type_decoration; + expression->type_decoration = type(std::make_shared<array_type>(element_type, expression->elements.size())); this->current_type = type(); @@ -1347,10 +1324,7 @@ namespace elna::boot void declaration_visitor::visit(unit *unit) { - for (declaration *const unit_declaration : unit->declarations) - { - unit_declaration->accept(this); - } + visit_all(this, unit->declarations); if (unit->entry_point.has_value()) { const type word8_primitive = lookup_primitive_type("Word8"); @@ -1540,10 +1514,7 @@ namespace elna::boot const std::shared_ptr<procedure_info> info = this->bag.lookup("")->is_procedure(); this->bag.enter(info->scope); - for (statement *body_statement : unit->entry_point.value()) - { - body_statement->accept(this); - } + visit_all(this, unit->entry_point.value()); this->bag.leave(); } } @@ -1590,7 +1561,11 @@ namespace elna::boot declaration->body->symbols = info->scope; this->bag.enter(info->scope); - traverse_body(this, declaration->body.value()); + traverse_block(this, declaration->body.value()); + if (declaration->body.value().return_expression != nullptr) + { + declaration->body.value().return_expression->accept(this); + } this->bag.leave(); } } @@ -1612,7 +1587,7 @@ namespace elna::boot register_variable(statement->counter->name(), lookup_primitive_type("Word"), statement->counter->position()); } - traverse_block(statement->body); + traverse_block(this, statement->body); this->bag.leave(); } } diff --git a/boot/type_check.cc b/boot/type_check.cc index 71fd8ab..15a01dc 100644 --- a/boot/type_check.cc +++ b/boot/type_check.cc @@ -800,13 +800,19 @@ namespace elna::boot } } - void type_analysis_visitor::visit_entry_point(unit *unit) + void type_analysis_visitor::visit(unit *unit) { - this->current_procedure = this->bag.lookup("")->is_procedure(); - this->bag.enter(this->current_procedure->scope); - walking_visitor::visit_entry_point(unit); - this->bag.leave(); - this->current_procedure.reset(); + visit_all(this, unit->imports); + visit_all(this, unit->declarations); + + if (unit->entry_point.has_value()) + { + this->current_procedure = this->bag.lookup("")->is_procedure(); + this->bag.enter(this->current_procedure->scope); + visit_all(this, unit->entry_point.value()); + this->bag.leave(); + this->current_procedure.reset(); + } } void type_analysis_visitor::visit(variable_declaration *declaration) @@ -885,7 +891,7 @@ namespace elna::boot void type_analysis_visitor::traverse_block(block& body) { this->bag.enter(body.symbols); - walking_visitor::traverse_block(body); + boot::traverse_block(this, body); this->bag.leave(); } @@ -1409,10 +1415,7 @@ namespace elna::boot { // Inference reads the argument types, so they are decorated // before the parameter types they will be checked against exist. - for (expression *const argument : call->arguments) - { - argument->accept(this); - } + visit_all(this, call->arguments); inferred = procedure; callable_type = infer_call(*call, *reference, *procedure); diff --git a/boot/validation.cc b/boot/validation.cc index 0c9259e..4539633 100644 --- a/boot/validation.cc +++ b/boot/validation.cc @@ -41,34 +41,27 @@ namespace elna::boot { } - void validation_visitor::visit_statements(const std::vector<statement *>& statements) + void validation_visitor::visit_statements(const std::vector<statement *>& statements, + const std::shared_ptr<symbol_table>& scope) { - for (statement *const body_statement : statements) - { - body_statement->accept(this); - } + this->bag.enter(scope); + visit_all(this, statements); + this->bag.leave(); } void validation_visitor::visit_block(const block& body) { - this->bag.enter(body.symbols); - visit_statements(body.statements); - this->bag.leave(); + visit_statements(body.statements, body.symbols); } void validation_visitor::visit(unit *unit) { - for (declaration *unit_declaration : unit->declarations) - { - unit_declaration->accept(this); - } + visit_all(this, unit->declarations); if (unit->entry_point.has_value()) { const std::shared_ptr<procedure_info> entry_point = this->bag.lookup("")->is_procedure(); - this->bag.enter(entry_point->scope); - visit_statements(unit->entry_point.value()); - this->bag.leave(); + visit_statements(unit->entry_point.value(), entry_point->scope); } } @@ -87,9 +80,7 @@ namespace elna::boot const std::shared_ptr<procedure_info> procedure = this->bag.lookup(declaration->identifier.name())->is_procedure(); - this->bag.enter(procedure->scope); - visit_statements(declaration->body.value().statements); - this->bag.leave(); + visit_statements(declaration->body.value().statements, procedure->scope); } } diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc index 464124a..fcc4c64 100644 --- a/gcc/gcc/elna-generic.cc +++ b/gcc/gcc/elna-generic.cc @@ -342,10 +342,7 @@ namespace elna::gcc void generic_visitor::visit(boot::unit *unit) { - for (boot::declaration *const unit_declaration : unit->declarations) - { - unit_declaration->accept(this); - } + visit_all(this, unit->declarations); if (unit->entry_point.has_value()) { const std::shared_ptr<boot::procedure_info> entry_point = this->bag.lookup("")->is_procedure(); @@ -491,10 +488,7 @@ namespace elna::gcc { this->symbols->enter(IDENTIFIER_POINTER(DECL_NAME(argument_chain)), argument_chain); } - for (boot::variable_declaration *const variable : declaration->body.value().variables) - { - variable->accept(this); - } + visit_all(this, declaration->body.value().variables); visit_statements(declaration->body.value().statements); if (declaration->body.value().return_expression != nullptr) @@ -1165,10 +1159,7 @@ namespace elna::gcc void generic_visitor::visit_block(boot::block& body) { this->bag.enter(body.symbols); - for (boot::variable_declaration *const variable : body.variables) - { - variable->accept(this); - } + visit_all(this, body.variables); visit_statements(body.statements); this->bag.leave(); } diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 6a3b9c9..82dde80 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see #include <string> #include <vector> #include <optional> +#include <concepts> +#include <ranges> #include "elna/boot/symbol.h" #include "elna/boot/result.h" @@ -321,12 +323,6 @@ namespace elna::boot void visit(literal<std::uint32_t> *) override; void visit(literal<std::nullptr_t> *) override; void visit(literal<std::string> *) override; - - protected: - /// Passes needing the entry point's scope override this. - virtual void visit_entry_point(unit *unit); - /// Passes needing the scope of a block override this. - virtual void traverse_block(block& body); }; /** @@ -700,7 +696,30 @@ namespace elna::boot procedure_body& operator=(procedure_body&& that) noexcept; }; - void traverse_body(parser_visitor *visitor, const procedure_body& body); + /** + * Vistis all nodes in a container. + * + * \tparam R Container or range type. + * \param visitor Visitor. + * \param nodes Visited container. + */ + template<std::ranges::input_range R> + requires std::derived_from<std::remove_pointer_t<std::ranges::range_value_t<R>>, node> + void visit_all(parser_visitor *visitor, R&& nodes) + { + for (auto *const node : nodes) + { + node->accept(visitor); + } + } + + /** + * Visits the declarations and the statements of a block. + * + * \param visitor Visitor. + * \param nodes Visited block. + */ + void traverse_block(parser_visitor *visitor, const block& body); /** * Procedure definition. diff --git a/include/elna/boot/materialization.h b/include/elna/boot/materialization.h index 63d6155..b239836 100644 --- a/include/elna/boot/materialization.h +++ b/include/elna/boot/materialization.h @@ -49,6 +49,7 @@ namespace elna::boot public: explicit materialization_visitor(const target_info& target); + void visit(unit *unit) override; void visit(procedure_declaration *declaration) override; void visit(variable_declaration *declaration) override; @@ -56,8 +57,5 @@ namespace elna::boot void visit(literal<integer_literal> *literal) override; void visit(literal<float_literal> *literal) override; - - protected: - void visit_entry_point(unit *unit) override; }; } diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h index 004aeae..c726a4f 100644 --- a/include/elna/boot/name_analysis.h +++ b/include/elna/boot/name_analysis.h @@ -298,11 +298,7 @@ namespace elna::boot std::optional<type> lookup_pointer_like_field(const std::string& field_name, const type& element_type); type lookup_field(const type& composite_type, const std::string& field_name); - /* - * Visits the declarations and the statements of a block in the scope - * the caller has opened for it. - */ - void traverse_block(block& body); + /* * Opens the scope of a block, remembers it on the block for the later * passes and visits the block in it. diff --git a/include/elna/boot/type_check.h b/include/elna/boot/type_check.h index 620af74..5e4f792 100644 --- a/include/elna/boot/type_check.h +++ b/include/elna/boot/type_check.h @@ -305,12 +305,12 @@ namespace elna::boot type promote_variadic_argument(const expression& argument); protected: - void visit_entry_point(unit *unit) override; - void traverse_block(block& body) override; + void traverse_block(block& body); public: explicit type_analysis_visitor(symbol_bag bag, const target_info& target); + void visit(unit *unit) override; void visit(procedure_declaration *declaration) override; void visit(assign_statement *statement) override; void visit(variable_declaration *declaration) override; diff --git a/include/elna/boot/validation.h b/include/elna/boot/validation.h index d3a22d1..2af68e0 100644 --- a/include/elna/boot/validation.h +++ b/include/elna/boot/validation.h @@ -48,7 +48,8 @@ namespace elna::boot symbol_bag& bag; evaluator constant_evaluator; - void visit_statements(const std::vector<statement *>& statements); + void visit_statements(const std::vector<statement *>& statements, + const std::shared_ptr<symbol_table>& scope); /// Visits the statements of a block in its own scope. void visit_block(const block& body); |
