diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-09-14 21:11:03 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-09-14 21:11:03 +0200 |
| commit | 52c8ca2c06da93c8d14e80a256e8996c1fa1e885 (patch) | |
| tree | 3579cffe682bb2d2270e5d892f26ae3c197880e6 /boot/type_check.cc | |
| parent | 49e6a0518eb6b7b09938b562ef270028337508bf (diff) | |
| download | elna-52c8ca2c06da93c8d14e80a256e8996c1fa1e885.tar.gz | |
Implement volatile operations
Diffstat (limited to 'boot/type_check.cc')
| -rw-r--r-- | boot/type_check.cc | 55 |
1 files changed, 48 insertions, 7 deletions
diff --git a/boot/type_check.cc b/boot/type_check.cc index eee5b42..2b82bec 100644 --- a/boot/type_check.cc +++ b/boot/type_check.cc @@ -142,6 +142,11 @@ namespace elna::boot 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 '" + + this->generic_name + "', it is not a scalar type"; + } else if constexpr (std::is_same_v<T, constant_argument>) { return "Constant type '" + payload.actual.to_string() @@ -1217,23 +1222,50 @@ namespace elna::boot return true; } + /* + * The volatile builtins take the pointee as their type argument, so the + * rule applies to what is loaded or stored rather than to a pointer. + */ + static argument_rule builtin_argument_rule(const std::string& name) + { + if (name == "volatile_load") + { + return argument_rule::scalar; + } + if (name == "volatile_store") + { + return argument_rule::mutable_scalar; + } + return argument_rule::pointer; + } + void type_analysis_visitor::check_arguments(const named_expression& reference, - const std::vector<type>& arguments) + const std::vector<type>& arguments, const argument_rule rule) { for (const type& argument : arguments) { - const type resolved = resolve_aliases(argument); + if (argument.empty()) + { + continue; + } + const type underlying = resolve_underlying_type(argument); - if (resolved.get<constant_type>() != nullptr) + if (rule != argument_rule::scalar + && resolve_aliases(argument).get<constant_type>() != nullptr) { add_error<generic_error>(reference.position(), reference.name, generic_error::constant_argument{ argument }); } - else if (!argument.empty() && !is_any_pointer_type(resolve_underlying_type(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)) + { + add_error<generic_error>(reference.position(), reference.name, + generic_error::argument_not_scalar{ argument }); + } } } @@ -1261,7 +1293,8 @@ namespace elna::boot } else if (!expression->arguments.empty()) { - check_arguments(*expression, expression->argument_types); + check_arguments(*expression, expression->argument_types, + builtin_argument_rule(expression->name)); } return; } @@ -1284,7 +1317,7 @@ namespace elna::boot } else { - check_arguments(*expression, expression->argument_types); + check_arguments(*expression, expression->argument_types, argument_rule::pointer); } } else if (std::shared_ptr<generic_type> const generic = unwrap_generic(denoted)) @@ -1335,7 +1368,7 @@ namespace elna::boot return type(); } } - check_arguments(reference, bindings); + check_arguments(reference, bindings, builtin_argument_rule(reference.name)); return substitute(type(std::make_shared<procedure_type>(procedure.symbol)), procedure.parameters, bindings); @@ -1396,6 +1429,14 @@ namespace elna::boot } inferred = procedure; callable_type = infer_call(*call, *reference, *procedure); + + // Name analysis decorated the call with the declared return + // type, which still mentions the parameters inference has + // just bound. + if (auto substituted = callable_type.get<procedure_type>()) + { + call->type_decoration = substituted->return_type.proper_type; + } } } if (auto procedure = callable_type.get<procedure_type>()) |
