From 7d0d0eb69589ab8e0c8b036a3b642593a372b041 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sun, 23 Aug 2026 20:01:55 +0200 Subject: Determine array type by the first element --- boot/ast.cc | 11 ++--------- boot/name_analysis.cc | 5 +++-- boot/parser.yy | 16 +++++++++------- boot/type_check.cc | 7 ------- include/elna/boot/ast.h | 6 +----- source/main.elna | 2 -- testsuite/compilable/compile_time_array_length.elna | 2 +- testsuite/fail_compilation/assign_element_of_const.elna | 2 +- testsuite/fail_compilation/compile_time_array_ptr.elna | 2 +- testsuite/fail_compilation/constant_enum_to_int.elna | 2 +- testsuite/runnable/array_constructor.elna | 6 +++--- testsuite/runnable/compile_time_array_access.elna | 2 +- testsuite/runnable/for_each_array.elna | 6 +++--- testsuite/runnable/for_each_slice.elna | 6 +++--- testsuite/runnable/for_with.elna | 6 +++--- testsuite/runnable/repeat_loop.elna | 4 ++-- testsuite/runnable/slice_array.elna | 2 +- testsuite/runnable/slice_cast.elna | 2 +- testsuite/runnable/slice_equality.elna | 2 +- testsuite/runnable/slice_pointer.elna | 2 +- testsuite/runnable/slice_slice.elna | 2 +- 21 files changed, 39 insertions(+), 56 deletions(-) diff --git a/boot/ast.cc b/boot/ast.cc index 1f2b884..d4f015b 100644 --- a/boot/ast.cc +++ b/boot/ast.cc @@ -461,7 +461,6 @@ namespace elna::boot void walking_visitor::visit(array_constructor_expression *expression) { - expression->array_type().accept(this); for (auto *element : expression->elements) { element->accept(this); @@ -844,8 +843,8 @@ namespace elna::boot } array_constructor_expression::array_constructor_expression(const source_position position, - array_type_expression *element_type, std::vector&& elements) - : node(position), m_element_type(element_type), elements(std::move(elements)) + std::vector&& elements) + : node(position), elements(std::move(elements)) { } @@ -859,14 +858,8 @@ namespace elna::boot return this; } - array_type_expression& array_constructor_expression::array_type() const - { - return *this->m_element_type; - } - array_constructor_expression::~array_constructor_expression() { - delete this->m_element_type; for (const expression *element : elements) { delete element; diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc index d4b8643..30d3cda 100644 --- a/boot/name_analysis.cc +++ b/boot/name_analysis.cc @@ -470,12 +470,13 @@ namespace elna::boot void name_analysis_visitor::visit(array_constructor_expression *expression) { - expression->array_type().accept(this); - expression->type_decoration = this->current_type; for (auto *element : expression->elements) { element->accept(this); } + const type element_type = expression->elements.front()->type_decoration; + expression->type_decoration = type(std::make_shared(element_type, + expression->elements.size())); this->current_type = type(); } diff --git a/boot/parser.yy b/boot/parser.yy index 0c32610..669115b 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -135,7 +135,7 @@ along with GCC; see the file COPYING3. If not see %type > type_expressions; %type expression operand simple_expression procedure_return unary_expression; %type binary_expression; -%type > expressions actual_parameter_list; +%type > optional_expressions required_expressions actual_parameter_list; %type designator_expression; %type > call_expression; %type statement; @@ -343,9 +343,9 @@ simple_expression: { $$ = new boot::record_constructor_expression(boot::make_position(@$), std::move(*$1), $3); } - | array_type_expression "{" expressions "}" + | "[" required_expressions "]" { - $$ = new boot::array_constructor_expression(boot::make_position(@$), $1.release(), $3); + $$ = new boot::array_constructor_expression(boot::make_position(@$), $2); } operand: unary_expression { $$ = $1; } @@ -453,14 +453,16 @@ unary_expression: { $$ = new boot::unary_expression(boot::make_position(@$), $2, boot::unary_operator::plus); } -expressions: - expression "," expressions +optional_expressions: + required_expressions { $$ = $1; } + | %empty { $$ = std::vector(); } +required_expressions: + expression "," required_expressions { $$ = $3; $$.emplace($$.cbegin(), $1); } | expression { $$.push_back($1); } - | %empty { $$ = std::vector(); } type_expressions: type_expression "," type_expressions { @@ -659,7 +661,7 @@ type_part: %empty {} | "type" type_declarations { $$ = $2; } actual_parameter_list: - "(" expressions ")" { $$ = $2; } + "(" optional_expressions ")" { $$ = $2; } %% void yy::parser::error(const location_type& loc, const std::string& message) diff --git a/boot/type_check.cc b/boot/type_check.cc index e810e30..ad27337 100644 --- a/boot/type_check.cc +++ b/boot/type_check.cc @@ -984,13 +984,6 @@ namespace elna::boot type_mismatch_error::expected_type{ type(std::make_shared(type(), 0)) }); return; } - if (expression->elements.size() > array->size) - { - add_error(expression->position(), - argument_count_error::kind::array, expression->type_decoration.to_string(), - array->size, expression->elements.size()); - return; - } for (auto *element : expression->elements) { if (!is_assignable_from(array->base, element->type_decoration)) diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 94488ff..c6a0828 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -487,18 +487,14 @@ namespace elna::boot class array_constructor_expression : public expression { - array_type_expression *m_element_type; - public: const std::vector elements; array_constructor_expression(const source_position position, - array_type_expression *element_type, std::vector&& elements); + std::vector&& elements); void accept(parser_visitor *visitor) override; array_constructor_expression *is_array_constructor() override; - array_type_expression& array_type() const; - ~array_constructor_expression() override; }; diff --git a/source/main.elna b/source/main.elna index d539d0d..13d9c61 100644 --- a/source/main.elna +++ b/source/main.elna @@ -34,8 +34,6 @@ var stderr: ^FILE stdin: ^FILE - t: Word := [3]Int{ 1, 2, 3 }.length - (* Standard procedures. *) diff --git a/testsuite/compilable/compile_time_array_length.elna b/testsuite/compilable/compile_time_array_length.elna index 12e706f..e38919e 100644 --- a/testsuite/compilable/compile_time_array_length.elna +++ b/testsuite/compilable/compile_time_array_length.elna @@ -1,5 +1,5 @@ var - source: const [3]Int := [3]Int{ 1, 2, 3 } + source: const [3]Int := [1, 2, 3] target: Word := source.length end. diff --git a/testsuite/fail_compilation/assign_element_of_const.elna b/testsuite/fail_compilation/assign_element_of_const.elna index a5b5cda..8235448 100644 --- a/testsuite/fail_compilation/assign_element_of_const.elna +++ b/testsuite/fail_compilation/assign_element_of_const.elna @@ -1,6 +1,6 @@ proc f() var - a: const [2]Int := [2]Int{ 1, 3 } + a: const [2]Int := [1, 3] begin a[1] := 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/compile_time_array_ptr.elna b/testsuite/fail_compilation/compile_time_array_ptr.elna index dd626a6..bd630ac 100644 --- a/testsuite/fail_compilation/compile_time_array_ptr.elna +++ b/testsuite/fail_compilation/compile_time_array_ptr.elna @@ -1,5 +1,5 @@ var - source: [3]Int := [3]Int{ 1, 2, 3} + source: [3]Int := [1, 2, 3] target: ^Int := source.ptr (* @Error Variable initializers must be constant expressions *) end. diff --git a/testsuite/fail_compilation/constant_enum_to_int.elna b/testsuite/fail_compilation/constant_enum_to_int.elna index f97bd3f..4be6131 100644 --- a/testsuite/fail_compilation/constant_enum_to_int.elna +++ b/testsuite/fail_compilation/constant_enum_to_int.elna @@ -2,7 +2,7 @@ type Enumeration = (one, two, three) var - x: [3]Int := [3]Int{ 1, 2, 3 } + x: [3]Int := [1, 2, 3] y: []Int begin diff --git a/testsuite/runnable/array_constructor.elna b/testsuite/runnable/array_constructor.elna index feefbe7..0e7b08b 100644 --- a/testsuite/runnable/array_constructor.elna +++ b/testsuite/runnable/array_constructor.elna @@ -1,11 +1,11 @@ var - a: [3]Int := [3]Int{1, 2, 3} - b: [2]Int := [2]Int{4} + a: [3]Int := [1, 2, 3] + b: [2]Int := [4, 0] begin assert(a[1] = 1 & a[2] = 2 & a[3] = 3); assert(b[1] = 4 & b[2] = 0); - a := [3]Int{5, 6, 7}; + a := [5, 6, 7]; assert(a[1] = 5 & a[2] = 6 & a[3] = 7) end. diff --git a/testsuite/runnable/compile_time_array_access.elna b/testsuite/runnable/compile_time_array_access.elna index 566f3be..4d59215 100644 --- a/testsuite/runnable/compile_time_array_access.elna +++ b/testsuite/runnable/compile_time_array_access.elna @@ -1,5 +1,5 @@ var - array: const [3]Int := [3]Int{ 1, 2, 3 } + array: const [3]Int := [1, 2, 3] i: const Int := array[2] begin diff --git a/testsuite/runnable/for_each_array.elna b/testsuite/runnable/for_each_array.elna index bf5733d..c6cba41 100644 --- a/testsuite/runnable/for_each_array.elna +++ b/testsuite/runnable/for_each_array.elna @@ -1,6 +1,6 @@ var - actual: [4]Word := [4]Word{} - input: [4]Word := [4]Word{ 2u, 4u, 6u, 8u } + actual: [4]Word := [0u, 0u, 0u, 0u] + input: [4]Word := [2u, 4u, 6u, 8u] i: Word := 1u begin @@ -8,5 +8,5 @@ begin actual[i] := element^ * 2u; i := i + 1u end; - assert(actual = [4]Word{ 4u, 8u, 12u, 16u }) + assert(actual = [4u, 8u, 12u, 16u]) end. diff --git a/testsuite/runnable/for_each_slice.elna b/testsuite/runnable/for_each_slice.elna index efdf961..5356bc8 100644 --- a/testsuite/runnable/for_each_slice.elna +++ b/testsuite/runnable/for_each_slice.elna @@ -1,6 +1,6 @@ var - actual: [4]Word := [4]Word{} - input: [4]Word := [4]Word{ 2u, 4u, 6u, 8u } + actual: [4]Word := [0u, 0u, 0u, 0u] + input: [4]Word := [2u, 4u, 6u, 8u] slice: []Word i: Word := 1u @@ -11,5 +11,5 @@ begin actual[i] := element^ * 2u; i := i + 1u end; - assert(actual = [4]Word{ 4u, 8u, 12u, 16u }) + assert(actual = [4u, 8u, 12u, 16u]) end. diff --git a/testsuite/runnable/for_with.elna b/testsuite/runnable/for_with.elna index cfec5c0..22ccb13 100644 --- a/testsuite/runnable/for_with.elna +++ b/testsuite/runnable/for_with.elna @@ -1,9 +1,9 @@ var - actual: [3]Word := [3]Word{} + actual: [3]Word := [0u, 0u, 0u] begin - for element of [3]Word{ 1u, 2u, 3u } with i do + for element of [1u, 2u, 3u] with i do actual[i] := i * element^ end; - assert(actual = [3]Word{ 1u, 4u, 9u }) + assert(actual = [1u, 4u, 9u]) end. diff --git a/testsuite/runnable/repeat_loop.elna b/testsuite/runnable/repeat_loop.elna index 5faaeab..71554f0 100644 --- a/testsuite/runnable/repeat_loop.elna +++ b/testsuite/runnable/repeat_loop.elna @@ -1,5 +1,5 @@ var - actual: [4]Word := [4]Word{} + actual: [4]Word := [0u, 0u, 0u, 0u] i: Word := 0u begin @@ -7,5 +7,5 @@ begin i := i + 1u; actual[i] := i until i = 4u; - assert(actual = [4]Word{ 1u, 2u, 3u, 4u }) + assert(actual = [1u, 2u, 3u, 4u]) end. diff --git a/testsuite/runnable/slice_array.elna b/testsuite/runnable/slice_array.elna index af0a270..8baaff3 100644 --- a/testsuite/runnable/slice_array.elna +++ b/testsuite/runnable/slice_array.elna @@ -1,5 +1,5 @@ var - array: [3]Int := [3]Int{ 2, 4, 6 } + array: [3]Int := [2, 4, 6] slice: []Int begin diff --git a/testsuite/runnable/slice_cast.elna b/testsuite/runnable/slice_cast.elna index 7c43959..ca093db 100644 --- a/testsuite/runnable/slice_cast.elna +++ b/testsuite/runnable/slice_cast.elna @@ -1,5 +1,5 @@ var - ints: [4]Int32 := [4]Int32{ 1i32, 2i32, 3i32, 4i32 } + ints: [4]Int32 := [1i32, 2i32, 3i32, 4i32] begin assert(cast(ints[1u to 4u]: []Int8).length = #size(Int32) * ints.length) diff --git a/testsuite/runnable/slice_equality.elna b/testsuite/runnable/slice_equality.elna index 712ae7a..e34981a 100644 --- a/testsuite/runnable/slice_equality.elna +++ b/testsuite/runnable/slice_equality.elna @@ -1,5 +1,5 @@ var - lhs_payload, rhs_payload: [3]Int := [3]Int{ 2, 4, 6 } + lhs_payload, rhs_payload: [3]Int := [2, 4, 6] lhs, rhs: []Int begin diff --git a/testsuite/runnable/slice_pointer.elna b/testsuite/runnable/slice_pointer.elna index d053f51..1ab367e 100644 --- a/testsuite/runnable/slice_pointer.elna +++ b/testsuite/runnable/slice_pointer.elna @@ -1,5 +1,5 @@ var - array: [3]Int := [3]Int{ 2, 4, 6 } + array: [3]Int := [2, 4, 6] slice: []Int begin diff --git a/testsuite/runnable/slice_slice.elna b/testsuite/runnable/slice_slice.elna index cce45ee..f5e0eba 100644 --- a/testsuite/runnable/slice_slice.elna +++ b/testsuite/runnable/slice_slice.elna @@ -1,5 +1,5 @@ var - array: [5]Int := [5]Int{ 2, 4, 6, 8, 10 } + array: [5]Int := [2, 4, 6, 8, 10] slice1, slice2: []Int begin -- cgit v1.2.3