aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-07-14 01:45:58 +0200
committerEugen Wissner <belka@caraus.de>2026-07-14 01:45:58 +0200
commit51e2f98e33ae10fc3052335cc6847bc93d0784fa (patch)
tree7588effe2778d38d19adbf83cf23b5429df93691
parent8ceb48a4e60b8ff89f28372da4f66cd152e2e0fe (diff)
downloadelna-51e2f98e33ae10fc3052335cc6847bc93d0784fa.tar.gz
Add static array initializer
-rw-r--r--boot/ast.cc35
-rw-r--r--boot/parser.yy4
-rw-r--r--boot/semantic.cc45
-rw-r--r--gcc/gcc/elna-generic.cc22
-rw-r--r--include/elna/boot/ast.h19
-rw-r--r--include/elna/boot/semantic.h2
-rw-r--r--include/elna/gcc/elna-generic.h1
-rw-r--r--testsuite/runnable/array_constructor.elna12
-rw-r--r--testsuite/runnable/record_construction.elna (renamed from testsuite/compilable/record_construction.elna)0
9 files changed, 138 insertions, 2 deletions
diff --git a/boot/ast.cc b/boot/ast.cc
index 36215c1..4af906f 100644
--- a/boot/ast.cc
+++ b/boot/ast.cc
@@ -119,6 +119,11 @@ namespace elna::boot
__builtin_unreachable();
}
+ void empty_visitor::visit(array_constructor_expression *)
+ {
+ __builtin_unreachable();
+ }
+
void empty_visitor::visit(traits_expression *)
{
__builtin_unreachable();
@@ -416,6 +421,15 @@ namespace elna::boot
}
}
+ void walking_visitor::visit(array_constructor_expression *expression)
+ {
+ expression->m_element_type->accept(this);
+ for (auto element : expression->elements)
+ {
+ element->accept(this);
+ }
+ }
+
void walking_visitor::visit(traits_expression *trait)
{
if (!trait->parameters.empty())
@@ -656,6 +670,27 @@ namespace elna::boot
}
}
+ array_constructor_expression::array_constructor_expression(const struct position position,
+ std::uint32_t size, type_expression *element_type,
+ std::vector<expression *>&& elements)
+ : node(position), size(size), m_element_type(element_type), elements(std::move(elements))
+ {
+ }
+
+ void array_constructor_expression::accept(parser_visitor *visitor)
+ {
+ visitor->visit(this);
+ }
+
+ array_constructor_expression::~array_constructor_expression()
+ {
+ delete m_element_type;
+ for (expression *const element : elements)
+ {
+ delete element;
+ }
+ }
+
variable_declaration::variable_declaration(const struct position position,
std::vector<identifier_definition>&& identifier, std::shared_ptr<type_expression> variable_type,
expression *initializer)
diff --git a/boot/parser.yy b/boot/parser.yy
index ae2e5a8..4ef2de4 100644
--- a/boot/parser.yy
+++ b/boot/parser.yy
@@ -265,6 +265,10 @@ simple_expression:
{
$$ = new boot::record_constructor_expression(boot::make_position(@1), std::move($1), std::move($3));
}
+ | "[" INTEGER "]" type_expression "{" expressions "}"
+ {
+ $$ = new boot::array_constructor_expression(boot::make_position(@1), $2, $4, std::move($6));
+ }
operand:
unary_expression { $$ = $1; }
| simple_expression { $$ = $1; }
diff --git a/boot/semantic.cc b/boot/semantic.cc
index f46dce9..f42b094 100644
--- a/boot/semantic.cc
+++ b/boot/semantic.cc
@@ -343,6 +343,31 @@ namespace elna::boot
}
}
+ void type_analysis_visitor::visit(array_constructor_expression *expression)
+ {
+ auto array = inner_aliased_type(expression->type_decoration).get<array_type>();
+
+ if (array == nullptr)
+ {
+ add_error<type_expectation_error>(type_expectation_error::kind::result, expression->position());
+ return;
+ }
+ if (expression->elements.size() > array->size)
+ {
+ add_error<argument_count_error>(array->size, expression->elements.size(),
+ expression->position());
+ return;
+ }
+ for (auto element : expression->elements)
+ {
+ if (!is_assignable_from(array->base, element->type_decoration))
+ {
+ add_error<type_expectation_error>(type_expectation_error::kind::argument,
+ element->position());
+ }
+ }
+ }
+
name_analysis_visitor::name_analysis_visitor(symbol_bag bag)
: error_container(), bag(bag)
{
@@ -588,6 +613,17 @@ namespace elna::boot
}
}
+ void name_analysis_visitor::visit(array_constructor_expression *expression)
+ {
+ expression->m_element_type->accept(this);
+ auto element_type = this->current_type;
+ for (auto element : expression->elements)
+ {
+ element->accept(this);
+ }
+ expression->type_decoration = type(std::make_shared<array_type>(element_type, expression->size));
+ }
+
void name_analysis_visitor::visit(procedure_type_expression *expression)
{
std::shared_ptr<procedure_type> result_type =
@@ -617,8 +653,13 @@ namespace elna::boot
void name_analysis_visitor::visit(variable_declaration *declaration)
{
- walking_visitor::visit(declaration);
-
+ declaration->variable_type().accept(this);
+ auto variable_type = this->current_type;
+ if (declaration->initializer != nullptr)
+ {
+ declaration->initializer->accept(this);
+ this->current_type = variable_type;
+ }
for (const identifier_definition& variable_identifier : declaration->identifiers)
{
auto variable_symbol = register_variable(variable_identifier.name, declaration->is_extern,
diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc
index 5749bbc..928ca8d 100644
--- a/gcc/gcc/elna-generic.cc
+++ b/gcc/gcc/elna-generic.cc
@@ -202,6 +202,28 @@ namespace elna::gcc
this->current_expression = build_constructor(record_type, tree_arguments);
}
+ void generic_visitor::visit(boot::array_constructor_expression *expression)
+ {
+ tree array_type = get_inner_alias(expression->type_decoration, this->symbols);
+
+ if (TREE_CODE(array_type) != ARRAY_TYPE)
+ {
+ this->current_expression = error_mark_node;
+ return;
+ }
+ tree domain = TYPE_DOMAIN(array_type);
+ tree index = TYPE_MIN_VALUE(domain);
+ vec<constructor_elt, va_gc> *tree_arguments = nullptr;
+
+ for (boot::expression *const element : expression->elements)
+ {
+ element->accept(this);
+ CONSTRUCTOR_APPEND_ELT(tree_arguments, index, this->current_expression);
+ index = int_const_binop(PLUS_EXPR, index, size_one_node);
+ }
+ this->current_expression = build_constructor(array_type, tree_arguments);
+ }
+
void generic_visitor::visit(boot::unit *unit)
{
for (boot::import_declaration *const declaration : unit->imports)
diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h
index 67e9fbe..fbe65a4 100644
--- a/include/elna/boot/ast.h
+++ b/include/elna/boot/ast.h
@@ -61,6 +61,7 @@ namespace elna::boot
class procedure_call;
class cast_expression;
class record_constructor_expression;
+ class array_constructor_expression;
struct field_initializer;
class assign_statement;
class if_statement;
@@ -100,6 +101,7 @@ namespace elna::boot
virtual void visit(procedure_call *) = 0;
virtual void visit(cast_expression *) = 0;
virtual void visit(record_constructor_expression *) = 0;
+ virtual void visit(array_constructor_expression *) = 0;
virtual void visit(traits_expression *) = 0;
virtual void visit(assign_statement *) = 0;
virtual void visit(if_statement *) = 0;
@@ -156,6 +158,7 @@ namespace elna::boot
[[noreturn]] virtual void visit(unit *) override;
[[noreturn]] virtual void visit(cast_expression *) override;
[[noreturn]] virtual void visit(record_constructor_expression *) override;
+ [[noreturn]] virtual void visit(array_constructor_expression *) override;
[[noreturn]] virtual void visit(traits_expression *) override;
[[noreturn]] virtual void visit(binary_expression *) override;
[[noreturn]] virtual void visit(unary_expression *) override;
@@ -199,6 +202,7 @@ namespace elna::boot
virtual void visit(unit *unit) override;
virtual void visit(cast_expression *expression) override;
virtual void visit(record_constructor_expression *expression) override;
+ virtual void visit(array_constructor_expression *expression) override;
virtual void visit(traits_expression *trait) override;
virtual void visit(binary_expression *expression) override;
virtual void visit(unary_expression *expression) override;
@@ -350,6 +354,21 @@ namespace elna::boot
virtual ~record_constructor_expression() override;
};
+ class array_constructor_expression : public expression
+ {
+ public:
+ const std::uint32_t size;
+ type_expression *const m_element_type;
+ const std::vector<expression *> elements;
+
+ array_constructor_expression(const struct position position,
+ std::uint32_t size, type_expression *element_type,
+ std::vector<expression *>&& elements);
+ void accept(parser_visitor *visitor) override;
+
+ virtual ~array_constructor_expression() override;
+ };
+
/**
* Enumeration type.
*/
diff --git a/include/elna/boot/semantic.h b/include/elna/boot/semantic.h
index 5ef4bc8..4041f33 100644
--- a/include/elna/boot/semantic.h
+++ b/include/elna/boot/semantic.h
@@ -162,6 +162,7 @@ namespace elna::boot
void visit(procedure_call *call) override;
void visit(case_statement *statement) override;
void visit(record_constructor_expression *expression) override;
+ void visit(array_constructor_expression *expression) override;
};
/**
@@ -193,6 +194,7 @@ namespace elna::boot
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;
diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h
index f30f9d6..23e1738 100644
--- a/include/elna/gcc/elna-generic.h
+++ b/include/elna/gcc/elna-generic.h
@@ -84,6 +84,7 @@ namespace elna::gcc
void visit(boot::dereference_expression *expression) override;
void visit(boot::unit *unit) override;
void visit(boot::record_constructor_expression *expression) override;
+ void visit(boot::array_constructor_expression *expression) override;
void visit(boot::assign_statement *statement) override;
void visit(boot::if_statement *statement) override;
void visit(boot::import_declaration *) override;
diff --git a/testsuite/runnable/array_constructor.elna b/testsuite/runnable/array_constructor.elna
new file mode 100644
index 0000000..2ce3578
--- /dev/null
+++ b/testsuite/runnable/array_constructor.elna
@@ -0,0 +1,12 @@
+var
+ a: [3]Int := [3]Int{1, 2, 3}
+ b: [2]Int := [2]Int{4}
+
+begin
+ assert(a[1] = 1 & a[2] = 2 & a[3] = 3);
+ assert(b[1] = 4 & b[2] = 0);
+
+ a := [3]Int{5, 6, 7};
+ assert(a[1] = 5 & a[2] = 6 & a[3] = 7)
+return 0
+end.
diff --git a/testsuite/compilable/record_construction.elna b/testsuite/runnable/record_construction.elna
index 00e60db..00e60db 100644
--- a/testsuite/compilable/record_construction.elna
+++ b/testsuite/runnable/record_construction.elna