diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-05-15 13:24:43 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-05-15 13:24:43 -0400 |
| commit | af0c285d9643f6073df9ea83efd9b92a90dc74b9 (patch) | |
| tree | 3a94d3200cf45b1002e7527b174c6e2d17428061 /compile.c | |
| parent | ae9cb9e7e33742773f088d7abe2076f6db4c6f9c (diff) | |
Allow specifying function arg enums without qualifiers
Diffstat (limited to 'compile.c')
| -rw-r--r-- | compile.c | 38 |
1 files changed, 23 insertions, 15 deletions
@@ -15,6 +15,7 @@ #include "builtins/util.h" static CORD compile_to_pointer_depth(env_t *env, ast_t *ast, int64_t target_depth, bool allow_optional); +static env_t *arg_scope(env_t *env, type_t *t); CORD compile_type_ast(env_t *env, type_ast_t *t) { @@ -572,15 +573,7 @@ CORD compile_statement(env_t *env, ast_t *ast) auto ret = Match(ast, Return)->value; assert(env->fn_ctx->return_type); if (ret) { - if (env->fn_ctx->return_type->tag == EnumType) { - env = fresh_scope(env); - env_t *ns_env = Match(env->fn_ctx->return_type, EnumType)->env; - for (tag_t *tag = Match(env->fn_ctx->return_type, EnumType)->tags; tag; tag = tag->next) { - if (get_binding(env, tag->name)) - continue; - set_binding(env, tag->name, get_binding(ns_env, tag->name)); - } - } + env = arg_scope(env, env->fn_ctx->return_type); type_t *ret_t = get_type(env, ret); CORD value = compile(env, ret); if (!promote(env, &value, ret_t, env->fn_ctx->return_type)) @@ -912,6 +905,19 @@ CORD compile_to_pointer_depth(env_t *env, ast_t *ast, int64_t target_depth, bool return val; } +env_t *arg_scope(env_t *env, type_t *t) +{ + if (t->tag != EnumType) return env; + env = fresh_scope(env); + env_t *ns_env = Match(t, EnumType)->env; + for (tag_t *tag = Match(t, EnumType)->tags; tag; tag = tag->next) { + if (get_binding(env, tag->name)) + continue; + set_binding(env, tag->name, get_binding(ns_env, tag->name)); + } + return env; +} + static CORD compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg_ast_t *call_args) { table_t used_args = {}; @@ -922,9 +928,10 @@ static CORD compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg if (spec_arg->name) { for (arg_ast_t *call_arg = call_args; call_arg; call_arg = call_arg->next) { if (call_arg->name && streq(call_arg->name, spec_arg->name)) { - type_t *actual_t = get_type(env, call_arg->value); - CORD value = compile(env, call_arg->value); - if (!promote(env, &value, actual_t, spec_arg->type)) + env_t *arg_env = arg_scope(env, spec_arg->type); + type_t *actual_t = get_type(arg_env, call_arg->value); + CORD value = compile(arg_env, call_arg->value); + if (!promote(arg_env, &value, actual_t, spec_arg->type)) code_err(call_arg->value, "This argument is supposed to be a %T, but this value is a %T", spec_arg->type, actual_t); Table$str_set(&used_args, call_arg->name, call_arg); if (code) code = CORD_cat(code, ", "); @@ -939,9 +946,10 @@ static CORD compile_arguments(env_t *env, ast_t *call_ast, arg_t *spec_args, arg if (call_arg->name) continue; const char *pseudoname = heap_strf("%ld", i++); if (!Table$str_get(used_args, pseudoname)) { - type_t *actual_t = get_type(env, call_arg->value); - CORD value = compile(env, call_arg->value); - if (!promote(env, &value, actual_t, spec_arg->type)) + env_t *arg_env = arg_scope(env, spec_arg->type); + type_t *actual_t = get_type(arg_env, call_arg->value); + CORD value = compile(arg_env, call_arg->value); + if (!promote(arg_env, &value, actual_t, spec_arg->type)) code_err(call_arg->value, "This argument is supposed to be a %T, but this value is a %T", spec_arg->type, actual_t); Table$str_set(&used_args, pseudoname, call_arg); if (code) code = CORD_cat(code, ", "); |
