diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/elna/boot/ast.h | 86 | ||||
| -rw-r--r-- | include/elna/boot/name_analysis.h | 10 | ||||
| -rw-r--r-- | include/elna/boot/type_check.h | 1 | ||||
| -rw-r--r-- | include/elna/boot/validation.h | 2 | ||||
| -rw-r--r-- | include/elna/gcc/elna-generic.h | 5 |
5 files changed, 68 insertions, 36 deletions
diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 4eea412..52461e6 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -111,6 +111,7 @@ namespace elna::boot template<typename T> concept literal_type = requires { literal_type_id<T>::value; }; + class statement; class variable_declaration; class procedure_declaration; class type_declaration; @@ -153,6 +154,27 @@ namespace elna::boot class empty_statement; /** + * Variable declarations and the statements they are visible in. + */ + struct block + { + std::vector<variable_declaration *> variables; + std::vector<statement *> statements; + /// Scope containing the variables, entered by the name analysis. + std::shared_ptr<symbol_table> symbols; + + block() = default; + block(std::vector<variable_declaration *>&& variables, std::vector<statement *>&& statements); + block(const block&) = delete; + block(block&& that) noexcept = default; + + block& operator=(const block&) = delete; + block& operator=(block&& that) noexcept = default; + + ~block(); + }; + + /** * Interface for AST visitors. */ struct parser_visitor @@ -304,6 +326,8 @@ namespace elna::boot 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); }; /** @@ -659,21 +683,14 @@ namespace elna::boot procedure_type_expression *is_procedure() override; }; - struct procedure_body + struct procedure_body : block { - const std::vector<variable_declaration *> variables; - const std::vector<statement *> statements; - expression *const return_expression{ nullptr }; + expression *return_expression{ nullptr }; - procedure_body(std::vector<variable_declaration *>&& variables, - std::vector<statement *>&& entry_point, - expression *return_expression = nullptr); - procedure_body(const procedure_body&) = delete; - procedure_body(procedure_body&& that) noexcept; + procedure_body(block&& body, expression *return_expression = nullptr); + procedure_body(procedure_body&& that) noexcept = default; - procedure_body& operator=(const procedure_body&) = delete; - - virtual ~procedure_body(); + virtual ~procedure_body() = default; }; void traverse_body(parser_visitor *visitor, const procedure_body& body); @@ -687,7 +704,7 @@ namespace elna::boot public: const identifier_definition identifier; - const std::optional<procedure_body> body; + std::optional<procedure_body> body; /** * Type parameters bound by this declaration. Empty for a plain @@ -771,9 +788,9 @@ namespace elna::boot expression *m_prerequisite; public: - const std::vector<statement *> statements; + block body; - conditional_statements(expression *prerequisite, std::vector<statement *>&& statements); + conditional_statements(expression *prerequisite, block&& body); expression& prerequisite(); @@ -783,7 +800,7 @@ namespace elna::boot struct switch_case { std::vector<expression *> labels; - std::vector<statement *> statements; + block body; }; class case_statement : public statement @@ -791,13 +808,15 @@ namespace elna::boot expression *m_condition; public: - const std::vector<switch_case> cases; - const std::vector<statement *> *alternative; + std::vector<switch_case> cases; + block *alternative; case_statement(const source_position position, expression *condition, - std::vector<switch_case>&& cases, std::vector<statement *> *alternative = nullptr); + std::vector<switch_case>&& cases, block *alternative = nullptr); void accept(parser_visitor *visitor) override; expression& condition(); + + ~case_statement() override; }; class designator_expression : public expression @@ -965,11 +984,11 @@ namespace elna::boot public: const std::vector<conditional_statements *> branches; - const std::vector<statement *> *alternative; + block *alternative; if_statement(const source_position position, conditional_statements *branch, std::vector<conditional_statements *>&& branches, - std::vector<statement *> *alternative = nullptr); + block *alternative = nullptr); void accept(parser_visitor *visitor) override; conditional_statements& branch(); @@ -1016,9 +1035,9 @@ namespace elna::boot expression *m_condition; public: - const std::vector<statement *> body; + block body; - repeat_statement(const source_position position, std::vector<statement *>&& body, + repeat_statement(const source_position position, block&& body, expression *condition); ~repeat_statement() override; @@ -1037,11 +1056,11 @@ namespace elna::boot public: const identifier control_variable; identifier *const counter; - const std::vector<statement *> body; - std::shared_ptr<symbol_table> symbols; + /// The control variable and the counter live in the body's scope. + block body; for_statement(const source_position position, identifier&& control_variable, - expression *range, std::vector<statement *>&& body, identifier *const counter); + expression *range, block&& body, identifier *const counter); ~for_statement() override; void accept(parser_visitor *visitor) override; @@ -1057,7 +1076,7 @@ namespace elna::boot public: const std::vector<import_declaration *> imports; const std::vector<declaration *> declarations; - const std::optional<procedure_body> entry_point; + std::optional<procedure_body> entry_point; const std::vector<identifier> parameters; const std::optional<source_position> entry_position; @@ -1104,12 +1123,10 @@ namespace elna::boot class defer_statement : public statement { public: - const std::vector<statement *> statements; + block body; - defer_statement(const source_position position, std::vector<statement *>&& statements); + defer_statement(const source_position position, block&& body); void accept(parser_visitor *visitor) override; - - ~defer_statement() override; }; /** @@ -1119,13 +1136,10 @@ namespace elna::boot { public: const identifier name; - const std::vector<statement *> statements; + block body; - block_statement(const source_position position, identifier&& name, - std::vector<statement *>&& statements); + block_statement(const source_position position, identifier&& name, block&& body); void accept(parser_visitor *visitor) override; - - ~block_statement() override; }; /** diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h index 67cd713..004aeae 100644 --- a/include/elna/boot/name_analysis.h +++ b/include/elna/boot/name_analysis.h @@ -298,6 +298,16 @@ 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. + */ + void visit_block(block& body); public: void visit(array_type_expression *expression) override; diff --git a/include/elna/boot/type_check.h b/include/elna/boot/type_check.h index 582b887..94f8961 100644 --- a/include/elna/boot/type_check.h +++ b/include/elna/boot/type_check.h @@ -300,6 +300,7 @@ namespace elna::boot protected: void visit_entry_point(unit *unit) override; + void traverse_block(block& body) override; public: explicit type_analysis_visitor(symbol_bag bag, const target_info& target); diff --git a/include/elna/boot/validation.h b/include/elna/boot/validation.h index 87e0b18..d3a22d1 100644 --- a/include/elna/boot/validation.h +++ b/include/elna/boot/validation.h @@ -49,6 +49,8 @@ namespace elna::boot evaluator constant_evaluator; void visit_statements(const std::vector<statement *>& statements); + /// Visits the statements of a block in its own scope. + void visit_block(const block& body); public: validation_visitor(symbol_bag& bag, const target_info& target); diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index b05a8f9..54f320e 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -67,6 +67,11 @@ namespace elna::gcc void build_volatile_store_builtin(location_t call_location, boot::procedure_call *call); void visit_statements(const std::vector<boot::statement *>& statements); + /* + * Declares the variables of a block and generates its statements. The + * caller opens the binding level the variables are declared in. + */ + void visit_block(boot::block& body); void assert_constant(); tree declare_local_variable(const boot::identifier& name, const boot::variable_info& info, tree initial_value); |
