summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-03-09 14:58:51 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-03-09 14:58:51 -0400
commit5edaca6cf2ea681c01c7ee0ef5daa041ed185640 (patch)
treeddeaf59400efb5ed68cb7bb4a62bb43d8e54d940
parente2d31615fcf2e3d02d5ff75e98524885c66e49b6 (diff)
more varargs and bugfixes
-rw-r--r--cgen.c6
-rw-r--r--main.c2
-rw-r--r--test.toc55
-rw-r--r--types.c14
4 files changed, 61 insertions, 16 deletions
diff --git a/cgen.c b/cgen.c
index 3bdf47f..94baf18 100644
--- a/cgen.c
+++ b/cgen.c
@@ -433,7 +433,7 @@ static void cgen_full_fn_name(CGenerator *g, FnExpr *f, U64 instance) {
}
}
-static void cgen_fn_args(CGenerator *g, FnExpr *f, U64 instance, U64 which_are_const) {
+static void cgen_fn_params(CGenerator *g, FnExpr *f, U64 instance, U64 which_are_const) {
(void)instance; /* not needed atm */
bool out_param = cgen_uses_ptr(&f->ret_type);
cgen_write(g, "(");
@@ -456,6 +456,8 @@ static void cgen_fn_args(CGenerator *g, FnExpr *f, U64 instance, U64 which_are_c
}
} else if ((d->flags & DECL_SEMI_CONST)
&& (which_are_const & (((U64)1) << semi_const_idx++))) {
+ /* semi constant argument is constant */
+ } else {
int idx = 0;
arr_foreach(d->idents, Identifier, i) {
if (any_params)
@@ -534,7 +536,7 @@ static void cgen_fn_header(CGenerator *g, FnExpr *f, U64 instance, U64 which_are
cgen_write(g, " ");
}
cgen_full_fn_name(g, f, instance);
- cgen_fn_args(g, f, instance, which_are_const);
+ cgen_fn_params(g, f, instance, which_are_const);
if (!out_param) {
cgen_type_post(g, &f->ret_type);
}
diff --git a/main.c b/main.c
index 4fe435d..63efe85 100644
--- a/main.c
+++ b/main.c
@@ -10,9 +10,11 @@
TODO:
variadic fns
const varargs
+varargs only exist in decls. not a type of its own
don't allow default varargs
don't allow semiconst varargs
make sure you can't have a variadic function pointer
+make sure varargs works with inference
#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 6a00236..a6d1b14 100644
--- a/test.toc
+++ b/test.toc
@@ -1,9 +1,54 @@
-f ::= fn(x: ..) int {
- 3
+#include "io.toc";
+
+Arr ::= struct (t :: Type) {
+ data: []t;
+ len, cap: int;
};
-main ::= fn() {
- f(1,2,3);
+
+arr_add ::= fn(t ::=, a : &Arr(t), x : t) {
+ if a.len >= a.cap {
+ a.cap = a.cap * 2 + 2;
+ new_data := new(t, a.cap);
+ for i := 0..a.len-1 {
+ new_data[i] = a.data[i];
+ }
+ a.data = new_data;
+ }
+ a.data[a.len] = x;
+ a.len += 1;
};
-main(); \ No newline at end of file
+square ::= fn(t ::=, x : t) t {
+ a : Arr(t);
+ for i := 1,2..2*x-1 {
+ arr_add(&a, i);
+ };
+ sum := 0 as t;
+ for i := 0..a.len-1 {
+ sum += a.data[i];
+ };
+ sum
+};
+
+
+// ArrInt ::= Arr(int);
+
+inc ::= fn(t ::=, x : t) t {
+ x + 1
+};
+
+main ::= fn() {
+ arr : Arr(int);
+ farr : Arr(float);
+ for i := 1..100 {
+ arr_add(&arr, inc(square(i)));
+ arr_add(&farr, inc(square(i as float)));
+ }
+ for i := 0..arr.len - 1 {
+ puti(arr.data[i]);
+ }
+ for i := 0..farr.len - 1 {
+ puti(farr.data[i] as int);
+ }
+};
diff --git a/types.c b/types.c
index ed5508b..b11f39b 100644
--- a/types.c
+++ b/types.c
@@ -489,12 +489,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) {
}
for (size_t i = 0; i < arr_len(param->idents); ++i) {
Type *param_type = typer_arr_add(tr, &t->fn.types);
- if (!generic) {
- *param_type = param->type;
- } else {
- param_type->flags = 0;
- param_type->kind = TYPE_UNKNOWN;
- }
+ *param_type = param->type;
if (has_constant_params) {
Constness constn;
if (param->flags & DECL_IS_CONST) {
@@ -1807,7 +1802,7 @@ static Status types_expr(Typer *tr, Expression *e) {
err_print(e->where, "Calling non-function (type %s).", type);
return false;
}
- bool has_varargs = fn_type_has_varargs(&f->type.fn);
+ bool has_varargs = f->type.kind == TYPE_FN && fn_type_has_varargs(&f->type.fn);
if (expr_is_definitely_const(f) || type_is_builtin(&f->type, BUILTIN_TYPE) || has_varargs) {
Value val;
@@ -1958,7 +1953,7 @@ static Status types_expr(Typer *tr, Expression *e) {
}
}
- size_t nvarargs;
+ size_t nvarargs = 0;
if (has_varargs) {
assert(fn_decl);
nvarargs = nargs - (size_t)order[nparams-1];
@@ -1972,8 +1967,9 @@ static Status types_expr(Typer *tr, Expression *e) {
if (fn_decl && !(fn_decl->flags & FN_EXPR_FOREIGN)) {
size_t i = 0;
+ Declaration *last_param = arr_last(fn_decl->params);
arr_foreach(fn_decl->params, Declaration, param) {
- if (type_is_builtin(&param->type, BUILTIN_VARARGS)) continue;
+ if (has_varargs && param == last_param) continue;
arr_foreach(param->idents, Identifier, ident) {
I16 arg_idx = order[i];
if (arg_idx == -1) {