diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-10-03 20:51:22 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-10-03 20:51:22 +0200 |
| commit | e4ce7f658741a7428597da4872435a1b0bae944c (patch) | |
| tree | 50f65abf6fa4468db7bc93a6ae61d623a2dd8566 /boot | |
| parent | 5d808dd4c4003968bbdf180e1e1193231db5d43b (diff) | |
| download | elna-e4ce7f658741a7428597da4872435a1b0bae944c.tar.gz | |
Rework generics for parameters to be plain types
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/symbol.cc | 1 | ||||
| -rw-r--r-- | boot/type_check.cc | 102 |
2 files changed, 70 insertions, 33 deletions
diff --git a/boot/symbol.cc b/boot/symbol.cc index e247bdb..4828070 100644 --- a/boot/symbol.cc +++ b/boot/symbol.cc @@ -809,7 +809,6 @@ namespace elna::boot { return checked.get<pointer_type>() != nullptr || checked.get<procedure_type>() != nullptr - || checked.get<parameter_type>() != nullptr || is_primitive_type(checked, "Pointer"); } diff --git a/boot/type_check.cc b/boot/type_check.cc index 42e7227..82c910f 100644 --- a/boot/type_check.cc +++ b/boot/type_check.cc @@ -137,11 +137,6 @@ namespace elna::boot return "Type parameter '" + payload.parameter + "' of '" + this->generic_name + "' is not used"; } - else if constexpr (std::is_same_v<T, argument_not_pointer>) - { - return "Type '" + payload.actual.to_string() + "' cannot be a type argument of '" - + this->generic_name + "', it is not a pointer type"; - } else if constexpr (std::is_same_v<T, argument_not_scalar>) { return "Type '" + payload.actual.to_string() + "' cannot be a type argument of '" @@ -379,7 +374,10 @@ namespace elna::boot */ static std::optional<type> find_opaque_type(const type& checked) { - if (resolve_underlying_type(checked).get<extern_type>() != nullptr) + const type underlying = resolve_underlying_type(checked); + + if (underlying.get<extern_type>() != nullptr + || underlying.get<parameter_type>() != nullptr) { return checked; } @@ -935,27 +933,59 @@ namespace elna::boot const std::shared_ptr<alias_type> unresolved_type = this->bag.lookup(declaration->identifier.name())->is_type()->symbol.get<alias_type>(); - if (const auto generic = unresolved_type->referent.get<generic_type>()) + type referent = unresolved_type->referent; + if (const auto generic = referent.get<generic_type>()) { check_parameters_used(declaration->position(), declaration->identifier.name(), generic->parameters, generic->referent); - return; + referent = generic->referent; } - const type referent = resolve_aliases(unresolved_type->referent); + referent = resolve_aliases(referent); if (const auto record = referent.get<record_type>()) { - for (const auto& [field_name, field] : record->fields) + const record_type_expression *record_expression = declaration->underlying_type().is_record(); + + if (record_expression != nullptr) { - if (const auto opaque = find_opaque_type(field.field_type)) + for (const field_declaration& field : record_expression->fields) { - add_error<type_requirement_error>(declaration->position(), - opaque.value(), type_requirement_error::kind::opaque_field); + if (field.first.empty()) + { + continue; + } + const auto field_entry = record->fields.find(field.first.front().name()); + + if (field_entry == record->fields.end()) + { + continue; + } + if (const auto opaque = find_opaque_type(field_entry->second.field_type)) + { + add_error<type_requirement_error>(field.second->position(), + opaque.value(), type_requirement_error::kind::opaque_field); + } + else if (has_zero_size(field_entry->second.field_type, this->target)) + { + add_error<type_requirement_error>(field.second->position(), + field_entry->second.field_type, type_requirement_error::kind::zero_sized); + } } - else if (has_zero_size(field.field_type, this->target)) + } + else + { + for (const auto& [field_name, field] : record->fields) { - add_error<type_requirement_error>(declaration->position(), - field.field_type, type_requirement_error::kind::zero_sized); + if (const auto opaque = find_opaque_type(field.field_type)) + { + add_error<type_requirement_error>(declaration->position(), + opaque.value(), type_requirement_error::kind::opaque_field); + } + else if (has_zero_size(field.field_type, this->target)) + { + add_error<type_requirement_error>(declaration->position(), + field.field_type, type_requirement_error::kind::zero_sized); + } } } } @@ -1137,10 +1167,17 @@ namespace elna::boot } else if (const auto left_pointer = left.get<pointer_type>()) { - const std::shared_ptr<pointer_type> right_pointer = right.get<pointer_type>(); + if (is_primitive_type(right, "Pointer")) + { + return true; + } + else + { + const std::shared_ptr<pointer_type> right_pointer = right.get<pointer_type>(); - return right_pointer != nullptr - && bind_arguments(parameters, bindings, left_pointer->base, right_pointer->base); + return right_pointer != nullptr + && bind_arguments(parameters, bindings, left_pointer->base, right_pointer->base); + } } else if (const auto left_slice = left.get<slice_type>()) { @@ -1227,7 +1264,7 @@ namespace elna::boot { return argument_rule::mutable_scalar; } - return argument_rule::pointer; + return argument_rule::opaque; } void type_analysis_visitor::check_arguments(const named_expression& reference, @@ -1241,18 +1278,13 @@ namespace elna::boot } const type underlying = resolve_underlying_type(argument); - if (rule != argument_rule::scalar + if (rule == argument_rule::mutable_scalar && resolve_aliases(argument).get<constant_type>() != nullptr) { add_error<generic_error>(reference.position(), reference.name, generic_error::constant_argument{ argument }); } - else if (rule == argument_rule::pointer && !is_any_pointer_type(underlying)) - { - add_error<generic_error>(reference.position(), reference.name, - generic_error::argument_not_pointer{ argument }); - } - else if (rule != argument_rule::pointer && !is_scalar_type(underlying)) + else if (rule != argument_rule::opaque && !is_scalar_type(underlying)) { add_error<generic_error>(reference.position(), reference.name, generic_error::argument_not_scalar{ argument }); @@ -1308,7 +1340,7 @@ namespace elna::boot } else { - check_arguments(*expression, expression->argument_types, argument_rule::pointer); + check_arguments(*expression, expression->argument_types, argument_rule::opaque); } } else if (std::shared_ptr<generic_type> const generic = unwrap_generic(denoted)) @@ -1619,12 +1651,18 @@ namespace elna::boot const type resolved_base = resolve_underlying_type(expression->base().type_decoration); - if (resolved_base.get<parameter_type>() != nullptr) + if (const auto pointer = resolved_base.get<pointer_type>()) { - add_error<type_requirement_error>(expression->position(), expression->base().type_decoration, - type_requirement_error::kind::dereference_of_parameter); + if (const auto opaque = find_opaque_type(pointer->base)) + { + if (opaque->get<parameter_type>() != nullptr) + { + add_error<type_requirement_error>(expression->position(), *opaque, + type_requirement_error::kind::dereference_of_parameter); + } + } } - else if (resolved_base.get<pointer_type>() == nullptr) + else { add_error<type_requirement_error>(expression->position(), expression->base().type_decoration, type_requirement_error::kind::dereference_of_non_pointer); |
