summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arr.c1
-rw-r--r--test.toc2
-rw-r--r--types.c82
3 files changed, 51 insertions, 34 deletions
diff --git a/arr.c b/arr.c
index 5c19307..10ad4a8 100644
--- a/arr.c
+++ b/arr.c
@@ -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)
diff --git a/test.toc b/test.toc
index 502f2cb..b3161bb 100644
--- a/test.toc
+++ b/test.toc
@@ -3,5 +3,5 @@ f ::= fn(y:f64=19.2, x : f64) f64 {
};
main ::= fn() {
- f(x = 13, y = 3);
+ f(13, y = 23);
};
diff --git a/types.c b/types.c
index f4e06ce..3627559 100644
--- a/types.c
+++ b/types.c
@@ -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.");
}