diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-07-17 10:18:58 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-07-17 10:18:58 +0200 |
| commit | a0e1740227535adc3151c02eb102c4f96b4f9731 (patch) | |
| tree | 0e29cd3719370eca8c74fb67480f3bfc1a207106 /include | |
| parent | d0a666507a6f11b65170c257fd483613f462f3f2 (diff) | |
| download | elna-a0e1740227535adc3151c02eb102c4f96b4f9731.tar.gz | |
Implement type constness
Diffstat (limited to 'include')
| -rw-r--r-- | include/elna/boot/ast.h | 47 | ||||
| -rw-r--r-- | include/elna/boot/semantic.h | 42 | ||||
| -rw-r--r-- | include/elna/boot/symbol.h | 72 | ||||
| -rw-r--r-- | include/elna/gcc/elna-generic.h | 1 |
4 files changed, 99 insertions, 63 deletions
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::vector<identifier>, std::shared_ptr<type_expression>>; class record_type_expression : public type_expression @@ -430,23 +445,6 @@ namespace elna::boot }; /** - * 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. */ class procedure_type_expression : public type_expression @@ -467,15 +465,13 @@ namespace elna::boot struct procedure_body { - const std::vector<constant_declaration *> constants; const std::vector<variable_declaration *> variables; const std::vector<statement *> entry_point; expression *const return_expression{ nullptr }; - procedure_body(std::vector<constant_declaration *>&& constants, - std::vector<variable_declaration *>&& variables, + procedure_body(std::vector<variable_declaration *>&& variables, std::vector<statement *>&& 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<import_declaration *>&& imports, - std::vector<constant_declaration *>&& constants, std::vector<type_declaration *>&& types, std::vector<variable_declaration *>&& variables, std::vector<procedure_declaration *>&& 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 @@ -85,6 +85,19 @@ namespace elna::boot }; /** + * 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. */ class field_not_found_error : public error @@ -199,8 +212,20 @@ namespace elna::boot symbol_bag bag; std::shared_ptr<procedure_info> current_procedure; - bool check_unresolved_symbol(std::shared_ptr<alias_type> 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<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); + 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_type> primitive; std::shared_ptr<record_type> record; std::shared_ptr<pointer_type> pointer; + std::shared_ptr<constant_type> constant; std::shared_ptr<array_type> array; std::shared_ptr<procedure_type> procedure; std::shared_ptr<enumeration_type> enumeration; @@ -70,6 +73,7 @@ namespace elna::boot explicit type(std::shared_ptr<primitive_type> primitive); explicit type(std::shared_ptr<record_type> record); explicit type(std::shared_ptr<pointer_type> pointer); + explicit type(std::shared_ptr<constant_type> constant); explicit type(std::shared_ptr<array_type> array); explicit type(std::shared_ptr<procedure_type> procedure); explicit type(std::shared_ptr<enumeration_type> 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<info> @@ -169,7 +179,6 @@ namespace elna::boot virtual std::shared_ptr<type_info> is_type(); virtual std::shared_ptr<procedure_info> is_procedure(); - virtual std::shared_ptr<constant_info> is_constant(); virtual std::shared_ptr<variable_info> is_variable(); }; @@ -332,18 +341,6 @@ namespace elna::boot bool is_extern() const; }; - class constant_info : public info - { - public: - using variant = typename - std::variant<std::int32_t, std::uint32_t, double, bool, unsigned char, std::nullptr_t, std::string>; - - const variant symbol; - - explicit constant_info(const variant& symbol); - std::shared_ptr<constant_info> 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_type> 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_type> 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<std::string> *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; |
