diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-07-13 23:59:36 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-07-13 23:59:36 +0200 |
| commit | 8ceb48a4e60b8ff89f28372da4f66cd152e2e0fe (patch) | |
| tree | b5e5522c47de3a7f62cd51a3258bfec7e99c062e /boot/semantic.cc | |
| parent | 500c0676b3f6cd5a2297987d5b0dc7ccf34a28d9 (diff) | |
| download | elna-8ceb48a4e60b8ff89f28372da4f66cd152e2e0fe.tar.gz | |
Change record constructor syntax
Diffstat (limited to 'boot/semantic.cc')
| -rw-r--r-- | boot/semantic.cc | 80 |
1 files changed, 42 insertions, 38 deletions
diff --git a/boot/semantic.cc b/boot/semantic.cc index 97c316a..f46dce9 100644 --- a/boot/semantic.cc +++ b/boot/semantic.cc @@ -288,37 +288,6 @@ namespace elna::boot walking_visitor::visit(expression); } - std::size_t type_analysis_visitor::match_record_fields( - const std::shared_ptr<record_type>& record, - std::vector<expression *>::const_iterator& argument_it, - const std::vector<expression *>::const_iterator& argument_end) - { - std::size_t expected = 0; - - if (!record->base.empty()) - { - if (auto base = inner_aliased_type(record->base).get<record_type>()) - { - expected += match_record_fields(base, argument_it, argument_end); - } - } - for (auto& field : record->fields) - { - ++expected; - if (argument_it != argument_end) - { - (*argument_it)->accept(this); - if (!is_assignable_from(field.second, (*argument_it)->type_decoration)) - { - add_error<type_expectation_error>(type_expectation_error::kind::argument, - (*argument_it)->position()); - } - ++argument_it; - } - } - return expected; - } - void type_analysis_visitor::visit(procedure_call *call) { call->callable().accept(this); @@ -346,16 +315,30 @@ namespace elna::boot call->arguments.size(), call->position()); } } - else if (auto callable_record = inner_aliased_type(call->type_decoration).get<record_type>()) - { - auto argument_it = std::cbegin(call->arguments); - auto argument_end = std::cend(call->arguments); + } - std::size_t expected = match_record_fields(callable_record, argument_it, argument_end); + void type_analysis_visitor::visit(record_constructor_expression *expression) + { + auto record = inner_aliased_type(expression->type_decoration).get<record_type>(); - if (call->arguments.size() != expected) + if (record == nullptr) + { + add_error<type_expectation_error>(type_expectation_error::kind::result, expression->position()); + return; + } + for (const field_initializer& initializer : expression->field_initializers) + { + for (const type_field& field : record->fields) { - add_error<argument_count_error>(expected, call->arguments.size(), call->position()); + if (field.first == initializer.name) + { + if (!is_assignable_from(field.second, initializer.value->type_decoration)) + { + add_error<type_expectation_error>(type_expectation_error::kind::argument, + initializer.value->position()); + } + break; + } } } } @@ -584,6 +567,27 @@ namespace elna::boot this->current_type = type(result_type); } + void name_analysis_visitor::visit(record_constructor_expression *expression) + { + if (auto type_symbol = this->bag.lookup(expression->type_name)) + { + if (auto type_info = type_symbol->is_type()) + { + expression->type_decoration = type_info->symbol; + } + } + for (const field_initializer& initializer : expression->field_initializers) + { + initializer.value->accept(this); + if (!expression->type_decoration.empty() + && lookup_field(expression->type_decoration, initializer.name).empty()) + { + add_error<declaration_error>(declaration_error::kind::undeclared, + initializer.name, expression->position()); + } + } + } + void name_analysis_visitor::visit(procedure_type_expression *expression) { std::shared_ptr<procedure_type> result_type = |
