diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-08-24 14:18:22 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-08-24 14:18:22 -0400 |
| commit | be534f5e511a1d3836254b827cdaa2b8c309f5c4 (patch) | |
| tree | 478fc9ede3a1c61220d3b02a2524fb32d53e7300 /src/environment.c | |
| parent | 788922fa2437c5b680b57d8adaaac9012fd5aba4 (diff) | |
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.
Diffstat (limited to 'src/environment.c')
| -rw-r--r-- | src/environment.c | 28 |
1 files changed, 9 insertions, 19 deletions
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) { |
