summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c1
-rw-r--r--test.toc6
-rw-r--r--types.c58
-rw-r--r--types.h3
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(&param->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(&param->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(&param->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 {