From eb1d068beeaaa420b558595751295eec35ad0c3c Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sat, 12 Sep 2026 00:18:11 +0200 Subject: Support variadic extern procedures --- boot/type_check.cc | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'boot/type_check.cc') diff --git a/boot/type_check.cc b/boot/type_check.cc index 8847693..5cdd2a2 100644 --- a/boot/type_check.cc +++ b/boot/type_check.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see #include "elna/boot/evaluator.h" #include "elna/boot/name_analysis.h" +#include #include #include @@ -286,6 +287,9 @@ namespace elna::boot case not_addressable: return "Expression of type '" + this->actual.to_string() + "' is not addressable"; + case variadic_argument: + return "Type '" + this->actual.to_string() + + "' cannot be passed as a variadic argument"; default: __builtin_unreachable(); } @@ -1337,6 +1341,34 @@ namespace elna::boot procedure.parameters, bindings); } + type type_analysis_visitor::promote_variadic_argument(const expression& argument) + { + const type resolved = resolve_underlying_type(argument.type_decoration); + + if (resolved.get() != nullptr || resolved.get() != nullptr) + { + add_error(argument.position(), argument.type_decoration, + type_requirement_error::kind::variadic_argument); + return type(); + } + if (is_primitive_type(resolved, "Single")) + { + return this->bag.lookup("Double")->is_type()->symbol; + } + if (is_discrete_type(resolved)) + { + const std::optional properties = get_type_properties(resolved, this->target); + + if (properties.has_value() && properties->size < this->target.c_int_properties.size) + { + const std::size_t bit_size = this->target.c_int_properties.size * CHAR_BIT; + + return this->bag.lookup("Int" + std::to_string(bit_size))->is_type()->symbol; + } + } + return argument.type_decoration; + } + void type_analysis_visitor::visit(procedure_call *call) { const named_expression *reference = call->callable().is_named(); @@ -1388,7 +1420,17 @@ namespace elna::boot ++argument_iterator; ++type_iterator; } - if (call->arguments.size() != procedure->parameters.size()) + while (procedure->variadic && argument_iterator != std::cend(call->arguments)) + { + if (inferred == nullptr) + { + (*argument_iterator)->accept(this); + } + call->variadic_types.push_back(promote_variadic_argument(**argument_iterator)); + ++argument_iterator; + } + if (call->arguments.size() < procedure->parameters.size() + || (!procedure->variadic && call->arguments.size() > procedure->parameters.size())) { if (auto *procedure_name = call->callable().is_named()) { -- cgit v1.2.3