aboutsummaryrefslogtreecommitdiff
path: root/src/environment.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-08-24 14:18:22 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-08-24 14:18:22 -0400
commitbe534f5e511a1d3836254b827cdaa2b8c309f5c4 (patch)
tree478fc9ede3a1c61220d3b02a2524fb32d53e7300 /src/environment.c
parent788922fa2437c5b680b57d8adaaac9012fd5aba4 (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.c28
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) {