diff options
-rw-r--r-- | arr.c | 1 | ||||
-rw-r--r-- | test.toc | 2 | ||||
-rw-r--r-- | types.c | 82 |
3 files changed, 51 insertions, 34 deletions
@@ -156,6 +156,7 @@ You shouldn't rely on this, though, e.g. by doing #define arr_set_lena(arr, n, a) arr_set_lena_((void **)(arr), n, sizeof **(arr), a) #define arr_clear(arr) arr_clear_((void **)(arr)), (void)sizeof **arr /* second part makes sure most of the time that you don't accidentally call it without taking the address */ #define arr_last(arr) arr_last_((void *)(arr), sizeof *(arr)) +/* OPTIM: maybe replace with less standard-compliant version */ #define arr_foreach(arr, type, var) for (type *var = arr_len(arr) ? arr : NULL, *var##_foreach_end = arr_last(arr); var; var == var##_foreach_end ? var = NULL : var++) #define arr_remove_last(arr) arr_remove_last_((void **)(arr), sizeof **(arr)) #define arr_copya(out, in, a) do { assert(sizeof *(in) == sizeof **(out)); arr_copya_((void **)(out), (in), sizeof **(out), (a)); } while(0) @@ -3,5 +3,5 @@ f ::= fn(y:f64=19.2, x : f64) f64 { }; main ::= fn() { - f(x = 13, y = 3); + f(13, y = 23); }; @@ -1062,50 +1062,66 @@ static bool types_expr(Typer *tr, Expression *e) { } if (fn_decl) { - Argument *arg = args; - Argument *arg_end = args + nargs; + /* TODO: make sure # of arguments isn't MORE than # of params */ size_t p = 0; - if (args) arr_foreach(fn_decl->params, Declaration, param) { - arr_foreach(param->idents, Identifier, ident) { - if (arg->name) { - /* named argument */ - long index = 0; - bool found = false; - arr_foreach(fn_decl->params, Declaration, pa) { - arr_foreach(pa->idents, Identifier, id) { - if (*id == arg->name) { - found = true; - break; - } - index++; + + Declaration *last_param_without_default_value = NULL; + arr_foreach(fn_decl->params, Declaration, param) { + if (!(param->flags & DECL_HAS_EXPR)) { + last_param_without_default_value = param; + } + } + Declaration *param = fn_decl->params; + size_t ident_idx = 0; + + arr_foreach(args, Argument, arg) { + bool named = arg->name != NULL; + if (named) { + /* named argument */ + long index = 0; + bool found = false; + arr_foreach(fn_decl->params, Declaration, pa) { + arr_foreach(pa->idents, Identifier, id) { + if (*id == arg->name) { + found = true; + break; } - if (found) break; - } - if (!found) { - char *s = ident_to_str(arg->name); - err_print(arg->where, "Argument '%s' does not appear in declaration of function.", s); - free(s); - info_print(idecl_where(ident_decl(f->ident)), "Declaration is here."); - return false; + ++index; } - params_set[index] = true; - arg_exprs[index] = arg->val; - } else { - params_set[p] = true; - arg_exprs[p] = arg->val; - p++; + if (found) break; + } + if (!found) { + char *s = ident_to_str(arg->name); + err_print(arg->where, "Argument '%s' does not appear in declaration of function.", s); + free(s); + info_print(idecl_where(ident_decl(f->ident)), "Declaration is here."); + return false; + } + params_set[index] = true; + arg_exprs[index] = arg->val; + } else if ((param->flags & DECL_HAS_EXPR) && param < last_param_without_default_value) { + /* this param must be named; so this is referring to a later parameter */ + --arg; + } else { + params_set[p] = true; + arg_exprs[p] = arg->val; + } + if (!named) { + /* sequential order of parameters */ + ++p; + ++ident_idx; + if (ident_idx == arr_len(param->idents)) { + ++param; + ident_idx = 0; } - arg++; - if (arg == arg_end) break; } - if (arg == arg_end) break; } } else { if (nargs != nparams) { err_print(e->where, "Expected %lu arguments to function call, but got %lu.", (unsigned long)nparams, (unsigned long)nargs); return false; } - for (size_t p = 0; p < nargs; p++) { + for (size_t p = 0; p < nargs; ++p) { if (args[p].name) { err_print(args[p].where, "You can only use named arguments if you directly call a function."); } |