diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/elna/boot/name_analysis.h | 153 | ||||
| -rw-r--r-- | include/elna/boot/type_check.h (renamed from include/elna/boot/semantic.h) | 165 | ||||
| -rw-r--r-- | include/elna/gcc/elna-generic.h | 1 |
3 files changed, 186 insertions, 133 deletions
diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h new file mode 100644 index 0000000..4498d0c --- /dev/null +++ b/include/elna/boot/name_analysis.h @@ -0,0 +1,153 @@ +/* Name analysis. + Copyright (C) 2025 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#pragma once + +#include <string> +#include <memory> +#include <map> + +#include "elna/boot/ast.h" +#include "elna/boot/result.h" +#include "elna/boot/symbol.h" +#include "elna/boot/type_check.h" + +namespace elna::boot +{ + /** + * Error declaring a symbol. + */ + class declaration_error : public error + { + public: + enum class kind + { + undeclared, + local_export + }; + + private: + std::string identifier; + kind error_kind; + + public: + + declaration_error(const kind error_kind, + const boot::identifier& identifier); + + std::string what() const override; + }; + + /** + * Attempted to redefine a name that is already in use in the + * current scope. + */ + class redefinition_error : public error + { + std::string identifier; + std::optional<source_position> original; + + public: + redefinition_error(const boot::identifier& identifier, + std::optional<source_position> original); + + std::string what() const override; + + std::optional<std::pair<std::string, source_position>> note() const override; + }; + + /** + * Origin of a field in a composite type. + */ + struct field_origin + { + std::optional<source_position> declaration; + type base_type; + }; + + /** + * Performs name analysis. + */ + class name_analysis_visitor final : public walking_visitor, public error_container + { + type current_type; + + symbol_bag bag; + + std::pair<procedure_type, std::vector<std::string>> build_procedure( + procedure_type_expression& expression); + std::vector<type_field> build_composite_type(const std::vector<field_declaration>& fields, + std::map<std::string, field_origin>& known_names, + type aggregate); + std::shared_ptr<variable_info> register_variable(const std::string& name, + const bool is_extern, const source_position position); + + type lookup_primitive_type(const std::string& name); + type lookup_field(const type& composite_type, const std::string& field_name); + + public: + name_analysis_visitor(symbol_bag bag); + + void visit(array_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(procedure_type_expression *expression) override; + void visit(enumeration_type_expression *expression) override; + + void visit(variable_declaration *declaration) override; + void visit(procedure_declaration *declaration) override; + + void visit(procedure_call *call) override; + void visit(unit *unit) override; + void visit(cast_expression *expression) override; + void visit(traits_expression *trait) override; + void visit(binary_expression *expression) override; + void visit(unary_expression *expression) override; + void visit(named_expression *expression) override; + void visit(array_access_expression *expression) override; + void visit(field_access_expression *expression) override; + void visit(dereference_expression *expression) override; + void visit(literal<std::int32_t> *literal) override; + void visit(literal<std::uint32_t> *literal) override; + void visit(literal<double> *literal) override; + void visit(literal<bool> *literal) override; + void visit(literal<unsigned char> *literal) override; + void visit(literal<std::nullptr_t> *literal) override; + void visit(literal<std::string> *literal) override; + }; + + /** + * Collects global declarations without resolving any symbols. + */ + class declaration_visitor final : public empty_visitor, public error_container + { + public: + forward_table unresolved; + + explicit declaration_visitor(); + + void visit(import_declaration *) override; + void visit(unit *unit) override; + void visit(type_declaration *declaration) override; + void visit(procedure_declaration *declaration) override; + void visit(variable_declaration *declaration) override; + }; +} diff --git a/include/elna/boot/semantic.h b/include/elna/boot/type_check.h index 3d2de10..b250f48 100644 --- a/include/elna/boot/semantic.h +++ b/include/elna/boot/type_check.h @@ -1,4 +1,4 @@ -/* Name analysis. +/* Type analysis. Copyright (C) 2025 Free Software Foundation, Inc. GCC is free software; you can redistribute it and/or modify @@ -19,7 +19,7 @@ along with GCC; see the file COPYING3. If not see #include <string> #include <memory> -#include <map> +#include <vector> #include "elna/boot/ast.h" #include "elna/boot/result.h" @@ -28,48 +28,6 @@ along with GCC; see the file COPYING3. If not see namespace elna::boot { /** - * Error declaring a symbol. - */ - class declaration_error : public error - { - public: - enum class kind - { - undeclared, - local_export - }; - - private: - std::string identifier; - kind error_kind; - - public: - - declaration_error(const kind error_kind, - const boot::identifier& identifier); - - std::string what() const override; - }; - - /** - * Attempted to redefine a name that is already in use in the - * current scope. - */ - class redefinition_error : public error - { - std::string identifier; - std::optional<source_position> original; - - public: - redefinition_error(const boot::identifier& identifier, - std::optional<source_position> original); - - std::string what() const override; - - std::optional<std::pair<std::string, source_position>> note() const override; - }; - - /** * Expected type does not match the actual type of an expression. */ class type_mismatch_error : public error @@ -205,7 +163,37 @@ namespace elna::boot }; /** - * Checks types. + * Chain of responsibility for type compatibility checks. + * + * Populate \c ctx with pre-resolved types, then call \c run(). + * Each handler inspects the context and returns a verdict — + * the first non-\c pass verdict wins. + */ + struct assign_check + { + enum class verdict { pass, accept, reject }; + + struct context + { + type aliased_assignee; + type aliased_assignment; + type resolved_assignee; + type resolved_assignment; + }; + context ctx; + + verdict guard_const_laundering(); + verdict check_exact_match(); + verdict check_pointer_hatch(); + verdict check_pointer_conversion(); + + bool run(); + }; + + /** + * Checks types: assignment compatibility, const-correctness, + * procedure argument counts, record field validity, + * and type declaration well-formedness. */ class type_analysis_visitor final : public walking_visitor, public error_container { @@ -217,12 +205,6 @@ namespace elna::boot * of type assignee. */ static bool is_assignable_from(const type& assignee, const type& assignment); - /* - * Checks whether derived has base in its parent chain. - * base should not be null, derived can be null. - */ - static bool is_base_of(const std::shared_ptr<record_type>& base, - const std::shared_ptr<record_type>& derived); static bool check_unresolved_symbol(std::shared_ptr<alias_type> alias, std::vector<std::string>& path); @@ -240,85 +222,4 @@ namespace elna::boot void visit(record_constructor_expression *expression) override; void visit(array_constructor_expression *expression) override; }; - - /** - * Origin of a field in a composite type. - */ - struct field_origin - { - std::optional<source_position> declaration; - type base_type; - }; - - /** - * Performs name analysis. - */ - class name_analysis_visitor final : public walking_visitor, public error_container - { - type current_type; - - symbol_bag bag; - - std::pair<procedure_type, std::vector<std::string>> build_procedure( - procedure_type_expression& expression); - std::vector<type_field> build_composite_type(const std::vector<field_declaration>& fields, - std::map<std::string, field_origin>& known_names, - type aggregate); - std::shared_ptr<variable_info> register_variable(const std::string& name, - const bool is_extern, const source_position position); - - type lookup_primitive_type(const std::string& name); - type lookup_field(const type& composite_type, const std::string& field_name); - - public: - name_analysis_visitor(symbol_bag bag); - - void visit(array_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(procedure_type_expression *expression) override; - void visit(enumeration_type_expression *expression) override; - - void visit(variable_declaration *declaration) override; - void visit(procedure_declaration *declaration) override; - - void visit(procedure_call *call) override; - void visit(unit *unit) override; - void visit(cast_expression *expression) override; - void visit(traits_expression *trait) override; - void visit(binary_expression *expression) override; - void visit(unary_expression *expression) override; - void visit(named_expression *expression) override; - void visit(array_access_expression *expression) override; - void visit(field_access_expression *expression) override; - void visit(dereference_expression *expression) override; - void visit(literal<std::int32_t> *literal) override; - void visit(literal<std::uint32_t> *literal) override; - void visit(literal<double> *literal) override; - void visit(literal<bool> *literal) override; - void visit(literal<unsigned char> *literal) override; - void visit(literal<std::nullptr_t> *literal) override; - void visit(literal<std::string> *literal) override; - }; - - /** - * Collects global declarations without resolving any symbols. - */ - class declaration_visitor final : public empty_visitor, public error_container - { - public: - forward_table unresolved; - - explicit declaration_visitor(); - - void visit(import_declaration *) override; - void visit(unit *unit) override; - void visit(type_declaration *declaration) override; - void visit(procedure_declaration *declaration) override; - void visit(variable_declaration *declaration) override; - }; } diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index a1689be..dd5c9ef 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -20,7 +20,6 @@ along with GCC; see the file COPYING3. If not see #include <string> #include "elna/boot/ast.h" #include "elna/boot/symbol.h" -#include "elna/boot/semantic.h" #include "elna/gcc/elna-tree.h" #include "config.h" |
