diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-10-07 10:15:16 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-10-07 10:15:16 +0200 |
| commit | f547dae96d770cc7bc27d3790d0d87bb8e37963d (patch) | |
| tree | 052abb2d81cabc5a3c5bde7d623ef2af9dcd45e9 /boot/type_check.cc | |
| parent | f9dfefc52fc792099b622ae47dafa32d2512e51e (diff) | |
| download | elna-f547dae96d770cc7bc27d3790d0d87bb8e37963d.tar.gz | |
Make procedure pointers compatible with normal pointers
Diffstat (limited to 'boot/type_check.cc')
| -rw-r--r-- | boot/type_check.cc | 57 |
1 files changed, 23 insertions, 34 deletions
diff --git a/boot/type_check.cc b/boot/type_check.cc index 82c910f..d8a9170 100644 --- a/boot/type_check.cc +++ b/boot/type_check.cc @@ -233,6 +233,10 @@ namespace elna::boot std::string type_requirement_error::what() const { + const bool is_procedure = resolve_underlying_type(this->actual).get<procedure_type>() != nullptr; + const std::string opaque_subject = (is_procedure ? "Procedure type '" : "Opaque type '") + + this->actual.to_string(); + switch (this->m_kind) { using enum kind; @@ -255,26 +259,19 @@ namespace elna::boot return "Type '" + this->actual.to_string() + "' cannot be dereferenced, it is not a pointer"; case opaque_variable: - return "Opaque type '" + this->actual.to_string() - + "' cannot be used to declare a variable"; + return opaque_subject + "' cannot be used to declare a variable"; case opaque_parameter: - return "Opaque type '" + this->actual.to_string() - + "' cannot be used as a procedure parameter"; + return opaque_subject + "' cannot be used as a procedure parameter"; case opaque_return: - return "Opaque type '" + this->actual.to_string() - + "' cannot be used as a return type"; + return opaque_subject + "' cannot be used as a return type"; case opaque_field: - return "Opaque type '" + this->actual.to_string() - + "' cannot be used as a record field type"; + return opaque_subject + "' cannot be used as a record field type"; case opaque_element: - return "Opaque type '" + this->actual.to_string() - + "' cannot be used as an array or slice element type"; + return opaque_subject + "' cannot be used as an array or slice element type"; case opaque_cast: - return "Opaque type '" + this->actual.to_string() - + "' cannot be used as a cast target type"; + return opaque_subject + "' cannot be used as a cast target type"; case opaque_arithmetic: - return "Opaque type '" + this->actual.to_string() - + "' cannot be used as an element type in pointer arithmetic"; + return opaque_subject + "' cannot be used as an element type in pointer arithmetic"; case dereference_of_parameter: return "Type parameter '" + this->actual.to_string() + "' cannot be dereferenced, its pointee is unknown"; @@ -342,7 +339,7 @@ namespace elna::boot { const type referent = resolve_aliases(checked); - if (referent.get<constant_type>() != nullptr) + if (referent.get<constant_type>() != nullptr || referent.get<procedure_type>() != nullptr) { return true; } @@ -367,7 +364,8 @@ namespace elna::boot /* * Finds the first opaque type in a value position, following aliases, - * qualifiers, arrays, slices, records and procedures but not pointers. + * qualifiers, arrays, slices and records but not pointers. A procedure is + * opaque too: it has no size and is only reachable through a pointer. * A pointer doesn't store its base type by value, so an opaque behind it * is only reachable as a transient value. A slice does: indexing, slicing * and taking an element's address all scale by the element size. @@ -377,7 +375,8 @@ namespace elna::boot const type underlying = resolve_underlying_type(checked); if (underlying.get<extern_type>() != nullptr - || underlying.get<parameter_type>() != nullptr) + || underlying.get<parameter_type>() != nullptr + || underlying.get<procedure_type>() != nullptr) { return checked; } @@ -402,26 +401,13 @@ namespace elna::boot { return find_opaque_type(slice->base); } - else if (const auto procedure = referent.get<procedure_type>()) - { - for (const type& parameter : procedure->parameters) - { - if (const auto opaque = find_opaque_type(parameter)) - { - return opaque; - } - } - return !procedure->return_type.empty() - ? find_opaque_type(procedure->return_type) - : std::nullopt; - } return std::nullopt; } /* * Scaling an offset needs the pointee size, which neither an opaque type * nor a type parameter has. Only a pointer_type scales; the generic - * Pointer and procedure values advance byte-wise. + * Pointer advances byte-wise. */ static std::optional<type> find_arithmetic_violation(binary_operator operation, const type& lhs, const type& rhs) @@ -1403,7 +1389,9 @@ namespace elna::boot { const type resolved = resolve_underlying_type(argument.type_decoration); - if (resolved.get<array_type>() != nullptr || resolved.get<slice_type>() != nullptr) + if (resolved.get<array_type>() != nullptr + || resolved.get<slice_type>() != nullptr + || resolved.get<procedure_type>() != nullptr) { add_error<type_requirement_error>(argument.position(), argument.type_decoration, type_requirement_error::kind::variadic_argument); @@ -1435,7 +1423,7 @@ namespace elna::boot call->callable().accept(this); this->in_callable_position = false; - type callable_type = call->callable().type_decoration; + type callable_type = resolve_underlying_type(call->callable().type_decoration); std::shared_ptr<procedure_info> inferred; if (reference != nullptr && reference->arguments.empty()) @@ -1770,7 +1758,8 @@ namespace elna::boot break; case equals: case not_equals: - valid = is_equality_compatible(lhs_resolved, rhs_resolved); + valid = lhs_resolved.get<procedure_type>() == nullptr + && is_equality_compatible(lhs_resolved, rhs_resolved); break; case shift_left: case shift_right: |
