From be534f5e511a1d3836254b827cdaa2b8c309f5c4 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sun, 24 Aug 2025 14:18:22 -0400 Subject: Constructors and functions with underscore arguments should be allowed to be called, but only if the underscore arguments are not provided but are implicit from the default values. Same for constructing structs with private fields. --- src/environment.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) (limited to 'src/environment.c') diff --git a/src/environment.c b/src/environment.c index 848e1269..f7956054 100644 --- a/src/environment.c +++ b/src/environment.c @@ -718,28 +718,18 @@ PUREFUNC binding_t *get_constructor(env_t *env, type_t *t, arg_ast_t *args, bool if (!type_env) return NULL; List_t constructors = type_env->namespace->constructors; // Prioritize exact matches: + call_opts_t options = {.promotion = false, .underscores = allow_underscores}; for (int64_t i = constructors.length - 1; i >= 0; i--) { - binding_t *b = constructors.data + i * constructors.stride; - DeclareMatch(fn, b->type, FunctionType); - if (!allow_underscores) { - for (arg_t *arg = fn->args; arg; arg = arg->next) - if (arg->name[0] == '_') goto next_constructor; - } - if (type_eq(fn->ret, t) && is_valid_call(env, fn->args, args, false)) return b; - next_constructor: - continue; + binding_t *constructor = constructors.data + i * constructors.stride; + DeclareMatch(fn, constructor->type, FunctionType); + if (type_eq(fn->ret, t) && is_valid_call(env, fn->args, args, options)) return constructor; } // Fall back to promotion: + options.promotion = true; for (int64_t i = constructors.length - 1; i >= 0; i--) { - binding_t *b = constructors.data + i * constructors.stride; - DeclareMatch(fn, b->type, FunctionType); - if (!allow_underscores) { - for (arg_t *arg = fn->args; arg; arg = arg->next) - if (arg->name[0] == '_') goto next_constructor2; - } - if (type_eq(fn->ret, t) && is_valid_call(env, fn->args, args, true)) return b; - next_constructor2: - continue; + binding_t *constructor = constructors.data + i * constructors.stride; + DeclareMatch(fn, constructor->type, FunctionType); + if (type_eq(fn->ret, t) && is_valid_call(env, fn->args, args, options)) return constructor; } return NULL; } @@ -752,7 +742,7 @@ PUREFUNC binding_t *get_metamethod_binding(env_t *env, ast_e tag, ast_t *lhs, as DeclareMatch(fn, b->type, FunctionType); if (!type_eq(fn->ret, ret)) return NULL; arg_ast_t *args = new (arg_ast_t, .value = lhs, .next = new (arg_ast_t, .value = rhs)); - return is_valid_call(env, fn->args, args, true) ? b : NULL; + return is_valid_call(env, fn->args, args, (call_opts_t){.promotion = true}) ? b : NULL; } void set_binding(env_t *env, const char *name, type_t *type, Text_t code) { -- cgit v1.2.3