aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-08-29 10:03:11 +0200
committerEugen Wissner <belka@caraus.de>2026-08-29 10:03:11 +0200
commit08d9c4292ebba3e320c1dbaca4fa06c83f6fc7fb (patch)
tree6ab464ecb3478eb958c75e696e90a9d04f9a1b80 /include
parent8e655a0786aec5e0215e09f2a9629c6f32e34793 (diff)
downloadelna-08d9c4292ebba3e320c1dbaca4fa06c83f6fc7fb.tar.gz
Fix procedure order resolution
Diffstat (limited to 'include')
-rw-r--r--include/elna/boot/name_analysis.h107
-rw-r--r--include/elna/boot/symbol.h11
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.