aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-10-08 01:29:37 +0200
committerEugen Wissner <belka@caraus.de>2026-10-08 01:29:37 +0200
commitd4b7f5e52a33f2d15aafca7f1b040f3f2821fd0c (patch)
treec4d2f2ea44bbcb26108e86270a4454cd04f7873a
parent12e304fd56f054ba7296ab538eecd4280a67832a (diff)
downloadelna-d4b7f5e52a33f2d15aafca7f1b040f3f2821fd0c.tar.gz
Move record constructor type into the braces
-rw-r--r--boot/ast.cc28
-rw-r--r--boot/name_analysis.cc17
-rw-r--r--boot/parser.yy18
-rw-r--r--gcc/gcc/elna-generic.cc15
-rw-r--r--include/elna/boot/ast.h16
-rw-r--r--testsuite/fail_compilation/assign_const_member.elna4
-rw-r--r--testsuite/fail_compilation/assign_member_of_const.elna2
-rw-r--r--testsuite/fail_compilation/record_base_constructor_type_mismatch.elna2
-rw-r--r--testsuite/runnable/aggregate_argument.elna2
-rw-r--r--testsuite/runnable/aggregate_equality.elna2
-rw-r--r--testsuite/runnable/case_record.elna6
-rw-r--r--testsuite/runnable/generic_constructor.elna2
-rw-r--r--testsuite/runnable/record_base_constructor.elna2
-rw-r--r--testsuite/runnable/record_construction.elna2
-rw-r--r--testsuite/runnable/return_aggregate.elna4
-rw-r--r--testsuite/runnable/two_fields_same_type.elna2
16 files changed, 43 insertions, 81 deletions
diff --git a/boot/ast.cc b/boot/ast.cc
index dc643fe..d698cd4 100644
--- a/boot/ast.cc
+++ b/boot/ast.cc
@@ -423,6 +423,7 @@ namespace elna::boot
void walking_visitor::visit(record_constructor_expression *expression)
{
+ expression->record_type().accept(this);
for (const field_initializer& initializer : expression->field_initializers)
{
initializer.value().accept(this);
@@ -844,36 +845,29 @@ namespace elna::boot
}
record_constructor_expression::record_constructor_expression(const source_position position,
- identifier&& type_name,
- std::vector<field_initializer>&& field_initializers)
- : node(position), type_name(std::move(type_name)), field_initializers(std::move(field_initializers))
+ type_expression *record_type, std::vector<field_initializer>&& field_initializers)
+ : node(position), m_record_type(record_type), field_initializers(std::move(field_initializers))
{
}
- record_constructor_expression::record_constructor_expression(const source_position position,
- identifier&& type_name, std::vector<type_expression *>&& arguments,
- std::vector<field_initializer>&& field_initializers)
- : node(position), type_name(std::move(type_name)),
- field_initializers(std::move(field_initializers)), arguments(std::move(arguments))
+ void record_constructor_expression::accept(parser_visitor *visitor)
{
+ visitor->visit(this);
}
- record_constructor_expression::~record_constructor_expression()
+ record_constructor_expression *record_constructor_expression::is_record_constructor()
{
- for (const type_expression *argument : this->arguments)
- {
- delete argument;
- }
+ return this;
}
- void record_constructor_expression::accept(parser_visitor *visitor)
+ type_expression& record_constructor_expression::record_type()
{
- visitor->visit(this);
+ return *this->m_record_type;
}
- record_constructor_expression *record_constructor_expression::is_record_constructor()
+ record_constructor_expression::~record_constructor_expression()
{
- return this;
+ delete this->m_record_type;
}
array_constructor_expression::array_constructor_expression(const source_position position,
diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc
index ff5f6bc..5ad2a75 100644
--- a/boot/name_analysis.cc
+++ b/boot/name_analysis.cc
@@ -918,21 +918,8 @@ namespace elna::boot
void resolving_visitor::visit(record_constructor_expression *expression)
{
- if (const auto type_symbol = this->bag.lookup(expression->type_name.name()))
- {
- if (const auto type_info = type_symbol->is_type())
- {
- expression->type_decoration = expression->arguments.empty()
- ? type_info->symbol
- : type(std::make_shared<instantiated_type>(type_info->symbol,
- resolve_arguments(expression->arguments)));
- }
- }
- else
- {
- add_error<symbol_declaration_error>(expression->type_name.position(),
- expression->type_name.name(), symbol_declaration_error::kind::undeclared_type);
- }
+ expression->type_decoration = resolve_type(expression->record_type());
+
for (const field_initializer& initializer : expression->field_initializers)
{
initializer.value().accept(this);
diff --git a/boot/parser.yy b/boot/parser.yy
index e8c3590..f416d57 100644
--- a/boot/parser.yy
+++ b/boot/parser.yy
@@ -424,14 +424,9 @@ simple_expression:
}
| call_expression { $$ = $1; }
| "(" expression ")" { $$ = $2; }
- | name_reference "{" field_initializers "}"
+ | "{" type_expression field_initializers "}"
{
- boot::named_expression *reference = $1;
-
- $$ = new boot::record_constructor_expression(boot::make_position(@$),
- boot::identifier(reference->name, reference->position()),
- std::move(reference->arguments), $3);
- delete reference;
+ $$ = new boot::record_constructor_expression(boot::make_position(@$), $2, $3);
}
| "[" required_expressions "]"
{
@@ -644,12 +639,13 @@ field_declarations:
field_initializer:
identifier ":" expression { $$ = std::make_unique<boot::field_initializer>(std::move(*$1), $3); }
field_initializers:
- field_initializer "," field_initializers
+ ";" field_initializer { $$.push_back(std::move(*$2)); }
+ | field_initializers "," field_initializer
{
- $$ = $3;
- $$.emplace($$.cbegin(), std::move(*$1));
+ $$ = $1;
+ $$.push_back(std::move(*$3));
}
- | field_initializer { $$.push_back(std::move(*$1)); }
+ | %empty {}
array_type_expression:
"[" expression "]" type_expression
{ $$ = new boot::array_type_expression(boot::make_position(@$), $4, $2); }
diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc
index 77ff61f..bb93270 100644
--- a/gcc/gcc/elna-generic.cc
+++ b/gcc/gcc/elna-generic.cc
@@ -248,14 +248,9 @@ namespace elna::gcc
void generic_visitor::visit(boot::record_constructor_expression *expression)
{
- tree type_decl = this->symbols->lookup(expression->type_name.name());
+ tree record_type = get_inner_alias(expression->type_decoration, this->symbols);
+ gcc_assert(TREE_CODE(record_type) == RECORD_TYPE);
- if (type_decl == NULL_TREE)
- {
- this->current_expression = error_mark_node;
- return;
- }
- tree record_type = TREE_TYPE(type_decl);
vec<constructor_elt, va_gc> *tree_arguments = nullptr;
for (const boot::field_initializer& initializer : expression->field_initializers)
@@ -271,12 +266,8 @@ namespace elna::gcc
void generic_visitor::visit(boot::array_constructor_expression *expression)
{
tree array_type = get_inner_alias(expression->type_decoration, this->symbols);
+ gcc_assert(TREE_CODE(array_type) == ARRAY_TYPE);
- 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;
diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h
index c3b43bb..35cfc8d 100644
--- a/include/elna/boot/ast.h
+++ b/include/elna/boot/ast.h
@@ -559,24 +559,18 @@ namespace elna::boot
class record_constructor_expression : public expression
{
+ type_expression *m_record_type;
+
public:
- const identifier type_name;
const std::vector<field_initializer> field_initializers;
- /**
- * Type arguments naming the instantiation being constructed. Empty
- * when no argument list was written.
- */
- const std::vector<type_expression *> arguments;
record_constructor_expression(const source_position position,
- identifier&& type_name,
- std::vector<field_initializer>&& field_initializers);
- record_constructor_expression(const source_position position,
- identifier&& type_name, std::vector<type_expression *>&& arguments,
- std::vector<field_initializer>&& field_initializers);
+ type_expression *record_type, std::vector<field_initializer>&& field_initializers);
~record_constructor_expression() override;
void accept(parser_visitor *visitor) override;
record_constructor_expression *is_record_constructor() override;
+
+ type_expression& record_type();
};
class array_constructor_expression : public expression
diff --git a/testsuite/fail_compilation/assign_const_member.elna b/testsuite/fail_compilation/assign_const_member.elna
index a603729..13e9e40 100644
--- a/testsuite/fail_compilation/assign_const_member.elna
+++ b/testsuite/fail_compilation/assign_const_member.elna
@@ -7,8 +7,8 @@ type
proc f()
var
- r1: R := R{ x: 5 }
- r2: R := R{ x: 5 }
+ r1: R := { R; x: 5 }
+ r2: R := { R; x: 5 }
begin
r1 := r2 (* @Error Cannot assign to a value of type 'R', because it is constant or contains constant members *)
return
diff --git a/testsuite/fail_compilation/assign_member_of_const.elna b/testsuite/fail_compilation/assign_member_of_const.elna
index efdf67b..44fb566 100644
--- a/testsuite/fail_compilation/assign_member_of_const.elna
+++ b/testsuite/fail_compilation/assign_member_of_const.elna
@@ -7,7 +7,7 @@ type
proc f()
var
- r: const R := R{ x: 5 }
+ r: const R := { R; x: 5 }
begin
r.x := 6 (* @Error Cannot assign to a value of type 'const Int', because it is constant or contains constant members *)
return
diff --git a/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna b/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna
index d7a8419..27a652c 100644
--- a/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna
+++ b/testsuite/fail_compilation/record_base_constructor_type_mismatch.elna
@@ -11,5 +11,5 @@ var
c: Child
begin
- c := Child{a: "wrong", b: 9} (* @Error Expected type 'Int', but got '\[\]const Word8' *)
+ c := { Child; a: "wrong", b: 9 } (* @Error Expected type 'Int', but got '\[\]const Word8' *)
end.
diff --git a/testsuite/runnable/aggregate_argument.elna b/testsuite/runnable/aggregate_argument.elna
index 7ae4947..edd9529 100644
--- a/testsuite/runnable/aggregate_argument.elna
+++ b/testsuite/runnable/aggregate_argument.elna
@@ -9,5 +9,5 @@ proc f(r: R) -> Bool
return r.a = 1 & r.b = 2
begin
- assert(f(R{a: 1, b: 2}))
+ assert(f({ R; a: 1, b: 2 }))
end.
diff --git a/testsuite/runnable/aggregate_equality.elna b/testsuite/runnable/aggregate_equality.elna
index c9601f9..b3e0646 100644
--- a/testsuite/runnable/aggregate_equality.elna
+++ b/testsuite/runnable/aggregate_equality.elna
@@ -6,7 +6,7 @@ type
end
proc f() -> Bool
-return R{a: 1, b: 2} = R{a: 1, b: 2}
+return { R; a: 1, b: 2 } = { R; a: 1, b: 2 }
begin
assert(f())
diff --git a/testsuite/runnable/case_record.elna b/testsuite/runnable/case_record.elna
index db8a6ff..13d6add 100644
--- a/testsuite/runnable/case_record.elna
+++ b/testsuite/runnable/case_record.elna
@@ -6,12 +6,12 @@ type
end
var
- r: R := R{a: 1, b: 2}
+ r: R := { R; a: 1, b: 2 }
begin
case r of
- R{a: 0, b: 0}: assert(false)
- | R{a: 1, b: 2}: assert(true)
+ { R; a: 0, b: 0 }: assert(false) |
+ { R; a: 1, b: 2 }: assert(true)
else
assert(false)
end
diff --git a/testsuite/runnable/generic_constructor.elna b/testsuite/runnable/generic_constructor.elna
index b21cd4a..a67b4f3 100644
--- a/testsuite/runnable/generic_constructor.elna
+++ b/testsuite/runnable/generic_constructor.elna
@@ -14,7 +14,7 @@ var
f: File
begin
- s := Stack#[File]{ top: 1u, items: @f };
+ s := { Stack#[File]; top: 1u, items: @f };
assert(s.top = 1u);
assert(s.items = @f)
end.
diff --git a/testsuite/runnable/record_base_constructor.elna b/testsuite/runnable/record_base_constructor.elna
index 80b6802..58e81ca 100644
--- a/testsuite/runnable/record_base_constructor.elna
+++ b/testsuite/runnable/record_base_constructor.elna
@@ -11,7 +11,7 @@ type
end
var
- g: Grandchild := Grandchild{a: 3, b: 5, c: 7}
+ g: Grandchild := { Grandchild; a: 3, b: 5, c: 7 }
begin
assert(g.a = 3);
diff --git a/testsuite/runnable/record_construction.elna b/testsuite/runnable/record_construction.elna
index 5a3a254..64770de 100644
--- a/testsuite/runnable/record_construction.elna
+++ b/testsuite/runnable/record_construction.elna
@@ -5,7 +5,7 @@ type
end
var
- r: R := R{x: 1, y: 2}
+ r: R := { R; x: 1, y: 2 }
begin
assert(r.x = 1 & r.y = 2)
diff --git a/testsuite/runnable/return_aggregate.elna b/testsuite/runnable/return_aggregate.elna
index 6959b60..c39823d 100644
--- a/testsuite/runnable/return_aggregate.elna
+++ b/testsuite/runnable/return_aggregate.elna
@@ -6,8 +6,8 @@ type
end
proc f() -> R
-return R{ a: 1, b: 2 }
+return { R; a: 1, b: 2 }
begin
- assert(f() = R{ a: 1, b: 2 })
+ assert(f() = { R; a: 1, b: 2 })
end.
diff --git a/testsuite/runnable/two_fields_same_type.elna b/testsuite/runnable/two_fields_same_type.elna
index 2b905b6..8f1d4cf 100644
--- a/testsuite/runnable/two_fields_same_type.elna
+++ b/testsuite/runnable/two_fields_same_type.elna
@@ -6,7 +6,7 @@ type
proc f() -> Int
var
- r: R := R{x: 3, y: 2}
+ r: R := { R; x: 3, y: 2 }
return r.x + r.y
begin