From 095b24cce985bb56baf128ebcfcf2d9476d3104f Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Sat, 7 Mar 2020 22:21:02 -0500 Subject: more varargs --- main.c | 1 - test.toc | 6 +----- types.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++----------- types.h | 3 ++- 4 files changed, 50 insertions(+), 18 deletions(-) diff --git a/main.c b/main.c index fb07c1e..3f66be1 100644 --- a/main.c +++ b/main.c @@ -8,7 +8,6 @@ /* TODO: -are we using the val stack for struct params? we probably need to, in case a struct calls a function which returns a type which uses that struct. variadic fns #foreign variadic fns where diff --git a/test.toc b/test.toc index 441cc5f..c750510 100644 --- a/test.toc +++ b/test.toc @@ -1,13 +1,9 @@ #include "std/io.toc", io; foo ::= fn(x: ..) { - }; main ::= fn() { - a : [3]int; - a[0] = 1; - a[1] = 1; - a[2] = 1; + io.puti(foo(3,4,5)); }; main(); \ No newline at end of file diff --git a/types.c b/types.c index 782f3d6..8048f03 100644 --- a/types.c +++ b/types.c @@ -270,6 +270,14 @@ static Status expr_must_lval(Expression *e) { char *istr = ident_to_str(i); err_print(e->where, "Use of constant %s as a non-constant expression.", istr); info_print(d->where, "%s was declared here.", istr); + free(istr); + return false; + } + if (type_is_builtin(&d->type, BUILTIN_VARARGS)) { + char *istr = ident_to_str(i); + err_print(e->where, "varargs cannot be set or pointed to."); + info_print(d->where, "%s was declared here.", istr); + free(istr); return false; } @@ -434,6 +442,15 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { success = false; goto ret; } + + if (type_is_builtin(¶m->type, BUILTIN_VARARGS)) { + if (param_idx != nparams-1 || arr_len(param->idents) > 1) { + err_print(param->where, "varargs must be the last parameter to a function."); + success = false; + goto ret; + } + f->flags |= FN_EXPR_HAS_VARARGS; + } if (param->type.kind == TYPE_TUPLE) { err_print(param->where, "Functions can't have tuple parameters."); @@ -522,10 +539,16 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { success = false; goto ret; } + if (type_is_builtin(&f->ret_type, BUILTIN_VARARGS)) { + err_print(f->where, "Functions cannot return varargs."); + success = false; + goto ret; + } if (type_is_compileonly(&f->ret_type)) { if (type_is_builtin(&f->ret_type, BUILTIN_NMS)) { err_print(f->where, "Functions cannot return namespaces."); - return false; + success = false; + goto ret; } /* a function which returns a compile-only type but has non-constant parameters is weird... @@ -1076,7 +1099,7 @@ static Status call_arg_param_order(FnExpr *fn, Type *fn_type, Argument *args, Lo assert(fn_type->flags & TYPE_IS_RESOLVED); size_t nparams = arr_len(fn_type->fn.types)-1; size_t nargs = arr_len(args); - if (nargs > nparams) { + if (nargs > nparams && !(fn->flags & FN_EXPR_HAS_VARARGS)) { err_print(where, "Expected at most %lu argument%s to function, but got %lu.", nparams, plural_suffix(nparams), nargs); return false; @@ -1119,6 +1142,11 @@ static Status call_arg_param_order(FnExpr *fn, Type *fn_type, Argument *args, Lo arr_foreach(fn->params, Declaration, pa) { arr_foreach(pa->idents, Identifier, id) { if (ident_eq_str(*id, arg->name)) { + if (type_is_builtin(&pa->type, BUILTIN_VARARGS)) { + err_print(arg->where, "varargs arguments cannot be named."); + return false; + } + param = pa; found = true; break; } @@ -1155,21 +1183,29 @@ static Status call_arg_param_order(FnExpr *fn, Type *fn_type, Argument *args, Lo param_idx = p; } - if (param_idx != -1) { - if (order[param_idx] != -1) { - err_print(arg->where, "Parameter #%d set twice.", param_idx+1); - info_print(args[order[param_idx]].where, "Parameter was previously set here."); + if (type_is_builtin(¶m->type, BUILTIN_VARARGS)) { + if (param_idx < (int)nparams && order[param_idx] == -1) { + order[param_idx] = arg_idx; + } + } else { + if (param_idx != -1) { + if (order[param_idx] != -1) { + err_print(arg->where, "Parameter #%d set twice.", param_idx+1); + info_print(args[order[param_idx]].where, "Parameter was previously set here."); + } + order[param_idx] = arg_idx; } - order[param_idx] = arg_idx; } if (!named) { /* sequential order of parameters */ ++p; - ++ident_idx; - if (ident_idx == arr_len(param->idents)) { - ++param; - ident_idx = 0; + if (!type_is_builtin(¶m->type, BUILTIN_VARARGS)) { + ++ident_idx; + if (ident_idx == arr_len(param->idents)) { + ++param; + ident_idx = 0; + } } } } diff --git a/types.h b/types.h index 35fe207..1d1cf4a 100644 --- a/types.h +++ b/types.h @@ -650,7 +650,8 @@ typedef struct ForExpr { enum { FN_EXPR_FOREIGN = 0x01, - FN_EXPR_EXPORT = 0x02 /* set by sdecls_cgen.c */ + FN_EXPR_EXPORT = 0x02, /* set by sdecls_cgen.c */ + FN_EXPR_HAS_VARARGS = 0x04 }; typedef enum { -- cgit v1.2.3