From a0e1740227535adc3151c02eb102c4f96b4f9731 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 17 Jul 2026 10:18:58 +0200 Subject: Implement type constness --- include/elna/boot/ast.h | 47 ++++++++++++--------------- include/elna/boot/semantic.h | 42 +++++++++++++++--------- include/elna/boot/symbol.h | 72 +++++++++++++++++++++++++++++------------ include/elna/gcc/elna-generic.h | 1 - 4 files changed, 99 insertions(+), 63 deletions(-) (limited to 'include') diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index b6aad70..42e7666 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -55,7 +55,6 @@ namespace elna::boot }; class variable_declaration; - class constant_declaration; class procedure_declaration; class type_declaration; class procedure_call; @@ -74,6 +73,7 @@ namespace elna::boot class type_expression; class array_type_expression; class pointer_type_expression; + class constant_type_expression; class record_type_expression; class procedure_type_expression; class enumeration_type_expression; @@ -94,7 +94,6 @@ namespace elna::boot struct parser_visitor { virtual void visit(variable_declaration *) = 0; - virtual void visit(constant_declaration *) = 0; virtual void visit(procedure_declaration *) = 0; virtual void visit(type_declaration *) = 0; virtual void visit(procedure_call *) = 0; @@ -114,6 +113,7 @@ namespace elna::boot virtual void visit(unary_expression *) = 0; virtual void visit(array_type_expression *) = 0; virtual void visit(pointer_type_expression *) = 0; + virtual void visit(constant_type_expression *) = 0; virtual void visit(record_type_expression *) = 0; virtual void visit(procedure_type_expression *) = 0; virtual void visit(enumeration_type_expression *) = 0; @@ -138,13 +138,13 @@ namespace elna::boot public: [[noreturn]] virtual void visit(array_type_expression *) override; [[noreturn]] virtual void visit(pointer_type_expression *) override; + [[noreturn]] virtual void visit(constant_type_expression *) override; [[noreturn]] virtual void visit(type_declaration *) override; [[noreturn]] virtual void visit(record_type_expression *) override; [[noreturn]] virtual void visit(procedure_type_expression *) override; [[noreturn]] virtual void visit(enumeration_type_expression *) override; [[noreturn]] virtual void visit(variable_declaration *) override; - [[noreturn]] virtual void visit(constant_declaration *) override; [[noreturn]] virtual void visit(procedure_declaration *) override; [[noreturn]] virtual void visit(assign_statement *) override; [[noreturn]] virtual void visit(if_statement *) override; @@ -182,13 +182,13 @@ namespace elna::boot public: virtual void visit(array_type_expression *) override; virtual void visit(pointer_type_expression *) override; + virtual void visit(constant_type_expression *) override; virtual void visit(type_declaration *) override; virtual void visit(record_type_expression *) override; virtual void visit(procedure_type_expression *) override; virtual void visit(enumeration_type_expression *) override; virtual void visit(variable_declaration *) override; - virtual void visit(constant_declaration *) override; virtual void visit(procedure_declaration *) override; virtual void visit(assign_statement *) override; virtual void visit(if_statement *) override; @@ -280,6 +280,7 @@ namespace elna::boot virtual named_expression *is_named(); virtual array_type_expression *is_array(); virtual pointer_type_expression *is_pointer(); + virtual constant_type_expression *is_constant(); virtual record_type_expression *is_record(); virtual procedure_type_expression *is_procedure(); virtual enumeration_type_expression *is_enumeration(); @@ -316,6 +317,20 @@ namespace elna::boot type_expression& base(); }; + class constant_type_expression : public type_expression + { + type_expression *m_base; + + public: + constant_type_expression(const source_position position, type_expression *base); + ~constant_type_expression() override; + + void accept(parser_visitor *visitor) override; + constant_type_expression *is_constant() override; + + type_expression& base(); + }; + using field_declaration = std::pair, std::shared_ptr>; class record_type_expression : public type_expression @@ -429,23 +444,6 @@ namespace elna::boot literal_expression *is_literal() override; }; - /** - * Constant definition. - */ - class constant_declaration : public declaration - { - expression *m_initializer; - - public: - constant_declaration(const source_position position, identifier_definition identifier, - expression *initializer); - void accept(parser_visitor *visitor) override; - - expression& initializer(); - - virtual ~constant_declaration() override; - }; - /** * Procedure type. */ @@ -467,15 +465,13 @@ namespace elna::boot struct procedure_body { - const std::vector constants; const std::vector variables; const std::vector entry_point; expression *const return_expression{ nullptr }; - procedure_body(std::vector&& constants, - std::vector&& variables, + procedure_body(std::vector&& variables, std::vector&& entry_point, - expression *return_expr = nullptr); + expression *return_expression = nullptr); procedure_body(const procedure_body&) = delete; procedure_body(procedure_body&& that); @@ -773,7 +769,6 @@ namespace elna::boot unit(const source_position position); unit(const source_position position, std::vector&& imports, - std::vector&& constants, std::vector&& types, std::vector&& variables, std::vector&& procedures, diff --git a/include/elna/boot/semantic.h b/include/elna/boot/semantic.h index 0f8f6c7..3d2de10 100644 --- a/include/elna/boot/semantic.h +++ b/include/elna/boot/semantic.h @@ -84,6 +84,19 @@ namespace elna::boot std::string what() const override; }; + /** + * Attempted to assign a value whose type contains constant members. + */ + class constant_assignment_error : public error + { + type assignee; + + public: + constant_assignment_error(const source_position position, type assignee); + + std::string what() const override; + }; + /** * Attempted to access a field that does not exist on the given type. */ @@ -199,8 +212,20 @@ namespace elna::boot symbol_bag bag; std::shared_ptr current_procedure; - bool check_unresolved_symbol(std::shared_ptr alias, + /* + * Whether an expression of type assignment can be assigned to a variable + * 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& base, + const std::shared_ptr& derived); + static bool check_unresolved_symbol(std::shared_ptr alias, std::vector& path); + public: explicit type_analysis_visitor(symbol_bag bag); @@ -231,7 +256,6 @@ namespace elna::boot class name_analysis_visitor final : public walking_visitor, public error_container { type current_type; - constant_info::variant current_literal; symbol_bag bag; @@ -244,7 +268,6 @@ namespace elna::boot const bool is_extern, const source_position position); type lookup_primitive_type(const std::string& name); - type type_of_constant(const constant_info::variant& value); type lookup_field(const type& composite_type, const std::string& field_name); public: @@ -252,6 +275,7 @@ namespace elna::boot 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; @@ -260,7 +284,6 @@ namespace elna::boot void visit(enumeration_type_expression *expression) override; void visit(variable_declaration *declaration) override; - void visit(constant_declaration *declaration) override; void visit(procedure_declaration *declaration) override; void visit(procedure_call *call) override; @@ -297,16 +320,5 @@ namespace elna::boot void visit(type_declaration *declaration) override; void visit(procedure_declaration *declaration) override; void visit(variable_declaration *declaration) override; - void visit(constant_declaration *declaration) override; }; - - /** - * Whether an expression of type \a assignment can be assigned to a variable - * of type \a assignee. - * - * \param assignee Assignee. - * \param assignment Assignment. - * \return Whether the assignment can be performed. - */ - bool is_assignable_from(const type& assignee, const type& assignment); } diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h index ec5a051..6884dd7 100644 --- a/include/elna/boot/symbol.h +++ b/include/elna/boot/symbol.h @@ -32,6 +32,7 @@ namespace elna::boot class primitive_type; class record_type; class pointer_type; + class constant_type; class array_type; class procedure_type; class enumeration_type; @@ -45,6 +46,7 @@ namespace elna::boot primitive, record, pointer, + constant, array, procedure, enumeration @@ -56,6 +58,7 @@ namespace elna::boot std::shared_ptr primitive; std::shared_ptr record; std::shared_ptr pointer; + std::shared_ptr constant; std::shared_ptr array; std::shared_ptr procedure; std::shared_ptr enumeration; @@ -70,6 +73,7 @@ namespace elna::boot explicit type(std::shared_ptr primitive); explicit type(std::shared_ptr record); explicit type(std::shared_ptr pointer); + explicit type(std::shared_ptr constant); explicit type(std::shared_ptr array); explicit type(std::shared_ptr procedure); explicit type(std::shared_ptr enumeration); @@ -112,6 +116,13 @@ namespace elna::boot explicit pointer_type(type base); }; + struct constant_type + { + const type unqualified; + + explicit constant_type(type unqualified); + }; + struct array_type { const type base; @@ -156,7 +167,6 @@ namespace elna::boot class type_info; class procedure_info; - class constant_info; class variable_info; class info : public std::enable_shared_from_this @@ -169,7 +179,6 @@ namespace elna::boot virtual std::shared_ptr is_type(); virtual std::shared_ptr is_procedure(); - virtual std::shared_ptr is_constant(); virtual std::shared_ptr is_variable(); }; @@ -332,18 +341,6 @@ namespace elna::boot bool is_extern() const; }; - class constant_info : public info - { - public: - using variant = typename - std::variant; - - const variant symbol; - - explicit constant_info(const variant& symbol); - std::shared_ptr is_constant() override; - }; - /** * Variable symbol information. */ @@ -467,13 +464,46 @@ namespace elna::boot }; /** - * If a type is a declared name for another type, look up recursively - * the declared type. If the given type is not an alias, then this function - * returns its argument. + * Resolves alias chains and type qualifiers until the underlying type is + * reached. If the given type is neither an alias nor qualified, it is + * returned as is. + * + * \param alias The type to resolve. + * \return The underlying, unqualified type. + */ + type resolve_underlying_type(const type& alias); + + /** + * \overload + */ + type resolve_underlying_type(std::shared_ptr alias); + + /** + * Resolves an alias chain until the underlying type or a qualified type is + * reached. + * + * \param checked The type to resolve. + * \return The first non-alias type in the chain. + */ + type resolve_aliases(const type& checked); + + /** + * Checks whether the given type is the built-in type \a name. + * + * \param checked The type to check. + * \param name The name of the primitive type to compare against. + * \return Whether the type is the primitive type with the given name. + */ + bool is_primitive_type(const type& checked, const std::string& name); + + /** + * Checks whether the given type is a pointer type. + * + * A pointer type is considered to be a variable pointer, a procedure + * pointer, or a built-in Pointer. * - * \param alias The type to lookup the innermost declaration for. - * \return Innermost type declaration. + * \param checked The type to check. + * \return Whether the type is a pointer type. */ - type inner_aliased_type(const type& alias); - type inner_aliased_type(std::shared_ptr alias); + bool is_any_pointer_type(const type& checked); } diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index e0f20f3..a1689be 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -76,7 +76,6 @@ namespace elna::gcc void visit(boot::literal *string) override; void visit(boot::binary_expression *expression) override; void visit(boot::unary_expression *expression) override; - void visit(boot::constant_declaration *declaration) override; void visit(boot::variable_declaration *declaration) override; void visit(boot::named_expression *expression) override; void visit(boot::array_access_expression *expression) override; -- cgit v1.2.3