diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-09-11 09:11:47 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-09-11 09:11:47 +0200 |
| commit | bd2b80d6ac582b9f0bcd96c86d4b79bfdb64eca1 (patch) | |
| tree | a835a5cfe5a9cf48720b9255261e065fd7978849 /include | |
| parent | b27872d5c5bfecae74195771f5c1f4e73385b6d6 (diff) | |
| download | elna-bd2b80d6ac582b9f0bcd96c86d4b79bfdb64eca1.tar.gz | |
Implement aligned attribute
Diffstat (limited to 'include')
| -rw-r--r-- | include/elna/boot/ast.h | 55 | ||||
| -rw-r--r-- | include/elna/boot/materialization.h | 13 | ||||
| -rw-r--r-- | include/elna/boot/name_analysis.h | 40 | ||||
| -rw-r--r-- | include/elna/boot/result.h | 23 | ||||
| -rw-r--r-- | include/elna/boot/symbol.h | 21 |
5 files changed, 121 insertions, 31 deletions
diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index f697b44..76fb94e 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -342,6 +342,57 @@ namespace elna::boot }; /** + * Attribute applied to a declaration. + */ + struct attribute + { + attribute(identifier&& name, std::vector<expression *> arguments); + attribute(const attribute&) = delete; + attribute(attribute&& that) noexcept; + ~attribute(); + + attribute& operator=(const attribute& that) = delete; + attribute& operator=(attribute&& that) noexcept; + + const identifier& name() const; + const std::vector<expression *>& arguments() const; + + private: + identifier m_name; + std::vector<expression *> m_arguments; + }; + + /** + * A declared name together with some attributes. + */ + struct identifier_definition + { + identifier_definition(const std::string& name, const source_position& position, + const bool exported, std::vector<attribute>&& attributes = std::vector<attribute>{}); + + const std::string& name() const; + const identifier& id() const; + bool exported() const; + /** + * \return Attributes written in front of the identifier. + */ + std::vector<attribute> attributes; + + private: + identifier m_identifier; + bool m_exported{ false }; + }; + + /** + * Extracts identifiers (name and position) from identifier definitions and + * returns them in an allocated vector. + * + * \param identifiers Identifier definitions. + * \return Extracted identifiers. + */ + std::vector<identifier> extract_identifiers(const std::vector<identifier_definition>& identifiers); + + /** * Symbol definition. */ class declaration : public node @@ -438,7 +489,7 @@ namespace elna::boot void accept(parser_visitor *visitor) override; }; - using field_declaration = std::pair<std::vector<identifier>, std::shared_ptr<type_expression>>; + using field_declaration = std::pair<std::vector<identifier_definition>, std::shared_ptr<type_expression>>; class record_type_expression : public type_expression { @@ -450,6 +501,8 @@ namespace elna::boot * absent. */ std::vector<type_expression *> base_arguments; + /// Attributes written in front of the \c record keyword. + std::vector<attribute> attributes; record_type_expression(const source_position position, std::vector<field_declaration>&& fields); diff --git a/include/elna/boot/materialization.h b/include/elna/boot/materialization.h index f3c720e..ef1b70b 100644 --- a/include/elna/boot/materialization.h +++ b/include/elna/boot/materialization.h @@ -27,7 +27,9 @@ namespace elna::boot enum class kind { integer_overflow, - real_overflow + real_overflow, + local_export, + field_export }; materialization_error(const source_position position, kind error_kind); @@ -41,11 +43,20 @@ namespace elna::boot class materialization_visitor final : public walking_visitor, public diagnostic_container { const target_info& target; + bool in_global_scope{ true }; public: explicit materialization_visitor(const target_info& target); + void visit(procedure_declaration *declaration) override; + void visit(variable_declaration *declaration) override; + + void visit(record_type_expression *expression) override; + void visit(literal<integer_literal> *literal) override; void visit(literal<float_literal> *literal) override; + + protected: + void visit_entry_point(unit *unit) override; }; } diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h index 46a3e2d..f2f2813 100644 --- a/include/elna/boot/name_analysis.h +++ b/include/elna/boot/name_analysis.h @@ -43,8 +43,7 @@ namespace elna::boot undeclared_type, undeclared_trait, undeclared_symbol, - not_a_type, - local_export + not_a_type }; struct redefinition { @@ -68,6 +67,31 @@ namespace elna::boot }; /** + * Error applying an attribute. + */ + class attribute_error final : public diagnostic + { + public: + enum class kind + { + unknown, + duplicate, + unsupported, + argument_count, + not_constant, + invalid_alignment + }; + + attribute_error(const source_position position, const std::string& name, kind attribute_kind); + + std::string what() const override; + + private: + std::string name; + kind m_kind; + }; + + /** * Cyclic type declaration. */ class cyclic_declaration_error final : public diagnostic @@ -179,8 +203,15 @@ namespace elna::boot const procedure_type_expression::return_t& return_type); 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); + ordered_map<field_info> build_composite_type(const std::vector<field_declaration>& fields, + ordered_map<field_origin>& field_names, const type& aggregate, + bool supported = true); + /* + * Reads the alignment out of the attributes written in front of a + * declaration, reporting the ones that do not belong there. + */ + std::optional<std::size_t> evaluate_alignment(const std::vector<attribute>& attributes, + bool supported); /* * Resolves a type expression, reporting names that denote something * other than a type. @@ -294,7 +325,6 @@ namespace elna::boot 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/result.h b/include/elna/boot/result.h index d37484a..6defcb8 100644 --- a/include/elna/boot/result.h +++ b/include/elna/boot/result.h @@ -202,20 +202,6 @@ namespace elna::boot source_position m_position; }; - struct identifier_definition - { - identifier_definition(const std::string& name, const source_position& position, - const bool exported); - - const std::string& name() const; - const identifier& id() const; - bool exported() const; - - private: - identifier m_identifier; - bool m_exported{ false }; - }; - /** * Creates an error note pointing to a previous declaration. * @@ -243,15 +229,6 @@ namespace elna::boot }; /** - * Extracts identifiers (name and position) from identifier definitions and - * returns them in an allocated vector. - * - * \param identifiers Identifier definitions. - * \return Extracted identifiers. - */ - std::vector<identifier> extract_identifiers(const std::vector<identifier_definition>& identifiers); - - /** * Joins an array of string-convertable objects (with a .t_string() method) * into a delimiter separated list. * diff --git a/include/elna/boot/symbol.h b/include/elna/boot/symbol.h index 8646f48..e9c9a0c 100644 --- a/include/elna/boot/symbol.h +++ b/include/elna/boot/symbol.h @@ -172,10 +172,25 @@ namespace elna::boot primitive_type(const std::string& identifier, const type_properties& properties); }; + /** + * A record field: its type and whatever its attributes decided about it. + */ + struct field_info + { + type field_type; + /// Alignment written with \c #aligned, empty when the field takes its + /// type's own alignment. + std::optional<std::size_t> alignment; + + field_info(type field_type = type(), std::optional<std::size_t> alignment = std::nullopt); + }; + struct record_type { - ordered_map<type> fields; + ordered_map<field_info> fields; const type base; + /// Alignment written with \c #aligned on the record itself. + std::optional<std::size_t> alignment; explicit record_type(type base = type()); }; @@ -465,6 +480,10 @@ namespace elna::boot /// Evaluated constant value, set by the constant folder. std::optional<constant_value> value; + /// Alignment written with \c #aligned, empty when the variable takes + /// its type's own alignment. + std::optional<std::size_t> alignment; + /** * Constructs a variable symbol information. * |
