diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/elna/boot/name_analysis.h | 107 | ||||
| -rw-r--r-- | include/elna/boot/symbol.h | 11 |
2 files changed, 83 insertions, 35 deletions
diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h index a2e9437..cd3c4f7 100644 --- a/include/elna/boot/name_analysis.h +++ b/include/elna/boot/name_analysis.h @@ -66,8 +66,7 @@ namespace elna::boot }; /** - * \c const qualifier used incorrectly — wrong position or - * duplicate. + * \c const qualifier used incorrectly — wrong position or duplicate. */ class const_qualifier_error final : public diagnostic { @@ -126,62 +125,78 @@ namespace elna::boot type base_type; }; + /** + * Makes every type name of the module referencable before any underlying + * type is resolved. + * + * Enters an unresolved alias placeholder for each type declaration, so + * declarations within the type section can reference each other regardless + * of order. + */ + class forward_declaration_visitor final : public empty_visitor, public diagnostic_container + { + public: + forward_table unresolved; + + void visit(unit *unit) override; + void visit(type_declaration *declaration) override; + }; + /** - * Performs name analysis. + * Shared name resolution machinery for the declaration and the body passes. + * + * Resolves type expressions into semantic types, decorates expressions with + * their type and evaluates constant expressions. */ - class name_analysis_visitor final : public walking_visitor, public diagnostic_container + class resolving_visitor : public parser_visitor, public diagnostic_container { + protected: type current_type; - symbol_bag bag; + symbol_bag& bag; evaluator constant_evaluator; - /// Path of the module being analyzed, recorded in the symbol infos. std::filesystem::path module_file; + resolving_visitor(symbol_bag& bag, const target_info& target, + const std::filesystem::path& module_path); + std::pair<procedure_type, std::vector<std::string>> build_procedure( procedure_type_expression& expression); ordered_map<type> build_composite_type(const std::vector<field_declaration>& fields, ordered_map<field_origin>& field_names, const type& aggregate); - std::shared_ptr<variable_info> register_variable(const std::string& name, - const bool is_extern, const source_position position); - - /** - * File of \p original for a redefinition note. - * - * \param original Symbol the error redefines. - * \return Module of the original declaration; empty when it is in the - * module being analyzed, so the note renders under the - * error's own file. - */ - std::filesystem::path redefinition_file(const std::shared_ptr<info>& original) const; - type lookup_primitive_type(const std::string& name); - type lookup_field(const type& composite_type, const std::string& field_name); + std::filesystem::path redefinition_file(const std::shared_ptr<info>& original) const; + std::shared_ptr<variable_info> register_variable(const std::string& name, + const type& variable_type, const source_position position, const bool is_extern = false); 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); public: - name_analysis_visitor(symbol_bag bag, const target_info& target, - std::filesystem::path module_file); + void visit(variable_declaration *declaration) override; void visit(array_type_expression *expression) override; void visit(slice_type_expression *expression) override; void visit(pointer_type_expression *expression) override; void visit(constant_type_expression *expression) override; - void visit(type_declaration *declaration) override; void visit(record_type_expression *expression) override; - void visit(record_constructor_expression *expression) override; - void visit(array_constructor_expression *expression) override; - void visit(slicing_expression *expression) override; void visit(procedure_type_expression *expression) override; void visit(enumeration_type_expression *expression) override; void visit(extern_type_expression *) override; - void visit(variable_declaration *declaration) override; - void visit(procedure_declaration *declaration) override; + void visit(assign_statement *statement) override; + void visit(if_statement *statement) override; + void visit(import_declaration *) override; + void visit(while_statement *statement) override; + void visit(repeat_statement *statement) override; + void visit(defer_statement *statement) override; + void visit(empty_statement *) override; + void visit(case_statement *statement) override; void visit(procedure_call *call) override; - void visit(unit *unit) override; void visit(cast_expression *expression) override; + void visit(record_constructor_expression *expression) override; + void visit(array_constructor_expression *expression) override; + void visit(slicing_expression *expression) override; void visit(traits_expression *trait) override; void visit(binary_expression *expression) override; void visit(unary_expression *expression) override; @@ -190,8 +205,6 @@ namespace elna::boot void visit(field_access_expression *expression) override; void visit(dereference_expression *expression) override; - void visit(for_statement *statement) override; - void visit(literal<integer_literal> *literal) override; void visit(literal<float_literal> *literal) override; void visit(literal<bool> *literal) override; @@ -201,16 +214,42 @@ namespace elna::boot }; /** - * Collects global declarations without resolving any symbols. + * Resolves declarations: fills type underlyings, registers global variables + * with their evaluated constant values and registers procedure headings + * together with their parameter scopes. */ - class declaration_visitor final : public empty_visitor, public diagnostic_container + class declaration_visitor final : public resolving_visitor { + using resolving_visitor::visit; + public: - forward_table unresolved; + declaration_visitor(symbol_bag& bag, const target_info& target, + const std::filesystem::path& module_path); void visit(unit *unit) override; void visit(type_declaration *declaration) override; void visit(procedure_declaration *declaration) override; + + [[noreturn]] void visit(for_statement *) override; + }; + + /** + * Analyzes procedure bodies and the module entry point against the complete + * symbol table. + */ + class name_analysis_visitor final : public resolving_visitor + { + using resolving_visitor::visit; + + public: + name_analysis_visitor(symbol_bag& bag, const target_info& target, + const std::filesystem::path& module_path); + + void visit(unit *unit) override; + [[noreturn]] void visit(type_declaration *) override; void visit(variable_declaration *declaration) override; + void visit(procedure_declaration *declaration) override; + + void visit(for_statement *statement) override; }; } diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h index 5f0de28..2c47fcc 100644 --- a/include/elna/boot/symbol.h +++ b/include/elna/boot/symbol.h @@ -492,7 +492,7 @@ namespace elna::boot * returns it if so. * * \param symbol_name Type name to look up. - * \return Forward declaration or `nullptr` if the symbol is not declared. + * \return Forward declaration or \c nullptr if the symbol is not declared. */ std::shared_ptr<alias_type> declared(const std::string& symbol_name); @@ -507,6 +507,15 @@ namespace elna::boot std::shared_ptr<alias_type> resolve(const std::string& symbol_name, type& resolution); /** + * Forward declares a type registering its stub. + * + * \param symbol_name Type name. + * \param forward_declaration Type alias to store. + * \return Whether the forward declaration took place. + */ + bool forward_declare(const std::string& symbol_name, std::shared_ptr<alias_type> forward_declaration); + + /** * Add imported symbols to the scope. * * \param symbols Exported symbol table of another module. |
