aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-09-11 09:11:47 +0200
committerEugen Wissner <belka@caraus.de>2026-09-11 09:11:47 +0200
commitbd2b80d6ac582b9f0bcd96c86d4b79bfdb64eca1 (patch)
treea835a5cfe5a9cf48720b9255261e065fd7978849 /include
parentb27872d5c5bfecae74195771f5c1f4e73385b6d6 (diff)
downloadelna-bd2b80d6ac582b9f0bcd96c86d4b79bfdb64eca1.tar.gz
Implement aligned attribute
Diffstat (limited to 'include')
-rw-r--r--include/elna/boot/ast.h55
-rw-r--r--include/elna/boot/materialization.h13
-rw-r--r--include/elna/boot/name_analysis.h40
-rw-r--r--include/elna/boot/result.h23
-rw-r--r--include/elna/boot/symbol.h21
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.
*