summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c2
-rw-r--r--test.toc3
-rw-r--r--types.c28
3 files changed, 20 insertions, 13 deletions
diff --git a/main.c b/main.c
index 3f66be1..d0ad7a4 100644
--- a/main.c
+++ b/main.c
@@ -8,7 +8,9 @@
/*
TODO:
+why aren't we computing table_index at the end?
variadic fns
+make sure you can't have a variadic function pointer
#foreign variadic fns
where
#returns_code (function/struct body is a block, to be evaluated at compile time, which returns the actual statements -- you can use this for implementation of printf)
diff --git a/test.toc b/test.toc
index c750510..5f9f410 100644
--- a/test.toc
+++ b/test.toc
@@ -1,6 +1,7 @@
#include "std/io.toc", io;
-foo ::= fn(x: ..) {
+foo ::= fn(x: ..) int {
+ 3
};
main ::= fn() {
diff --git a/types.c b/types.c
index 8048f03..db5c1c5 100644
--- a/types.c
+++ b/types.c
@@ -2187,21 +2187,25 @@ static Status types_expr(Typer *tr, Expression *e) {
ret_type = f->type.fn.types;
param_types = ret_type + 1;
}
+
+ bool has_varargs = fn_decl && (fn_decl->flags & FN_EXPR_HAS_VARARGS);
/* check types of arguments */
for (size_t p = 0; p < nparams; ++p) {
- Expression *arg = &arg_exprs[p];
- Type *expected = &param_types[p];
- Type *got = &arg->type;
- if (!type_eq(expected, got)) {
- char *estr = type_to_str(expected);
- char *gstr = type_to_str(got);
- err_print(arg->where, "Expected type %s as argument to function, but got %s.", estr, gstr);
- return false;
- }
- if (got->flags & TYPE_IS_FLEXIBLE) {
- /* "cast" */
- *got = *expected;
+ if (p != nparams-1 || !has_varargs) {
+ Expression *arg = &arg_exprs[p];
+ Type *expected = &param_types[p];
+ Type *got = &arg->type;
+ if (!type_eq(expected, got)) {
+ char *estr = type_to_str(expected);
+ char *gstr = type_to_str(got);
+ err_print(arg->where, "Expected type %s as argument to function, but got %s.", estr, gstr);
+ return false;
+ }
+ if (got->flags & TYPE_IS_FLEXIBLE) {
+ /* "cast" */
+ *got = *expected;
+ }
}
}
if (fn_type->constness) {