summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c18
-rw-r--r--main.c4
-rw-r--r--test.toc6
-rw-r--r--types.c43
4 files changed, 49 insertions, 22 deletions
diff --git a/cgen.c b/cgen.c
index 5d98814..eed4f2e 100644
--- a/cgen.c
+++ b/cgen.c
@@ -125,21 +125,21 @@ static bool cgen_defs_decl(CGenerator *g, Declaration *d);
case EXPR_FN: { \
FnExpr *fn = &e->fn; \
if (e->type.fn.constness) { \
- Instance **data = fn->instance.data; \
- for (U64 i = 0; i < f->instances.cap; i++) { \
- if (f->instances.occupied[i]) { \
- cgen_recurse_subexprs_fn_simple(&(*data)->fn, decl_f, block_f); \
+ Instance **data = fn->instances.data; \
+ for (U64 i = 0; i < fn->instances.cap; i++) { \
+ if (fn->instances.occupied[i]) { \
+ cgen_recurse_subexprs_fn_simple((&(*data)->fn), decl_f, block_f); \
} \
data++; \
} \
} else { \
cgen_recurse_subexprs_fn_simple(fn, decl_f, block_f); \
} \
- break; \
- case EXPR_NEW: \
- if (e->new.n && !f(g, e->new.n)) \
- return false; \
- break; \
+ } break; \
+ case EXPR_NEW: \
+ if (e->new.n && !f(g, e->new.n)) \
+ return false; \
+ break; \
}
static bool cgen_block_enter(CGenerator *g, Block *b) {
diff --git a/main.c b/main.c
index b59d7ab..ea6c724 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,8 @@
/*
TODO:
-deal with typing functions with type parameters (we need to type every single instance)
+better errors (show where instance is)
+alias type, instead of creating a new type.
+make sure fn(t @ Type, x : t = 1598, y @ t = 9832) works
don't cgen decls etc. in parameter initializers
struct parameters
diff --git a/test.toc b/test.toc
index 8adf650..1d326d3 100644
--- a/test.toc
+++ b/test.toc
@@ -11,8 +11,10 @@ putf @= fn(x: float) {
main @= fn() {
puti(g(int));
+ puti(g());
};
-g @= fn(t @ Type) int {
+g @= fn(t @= u8) int {
87347 as t as int
-}; \ No newline at end of file
+};
+
diff --git a/types.c b/types.c
index c607f2f..6e1f3bd 100644
--- a/types.c
+++ b/types.c
@@ -1081,7 +1081,8 @@ static bool types_expr(Typer *tr, Expression *e) {
arr_foreach(fn_decl->params, Declaration, param) {
bool is_required = !(param->flags & DECL_HAS_EXPR);
- long ident_idx = 0;
+ int ident_idx = 0;
+
arr_foreach(param->idents, Identifier, ident) {
if (index == i) {
if (is_required) {
@@ -1090,15 +1091,37 @@ static bool types_expr(Typer *tr, Expression *e) {
free(s);
return false;
} else {
- assert(param->expr.kind == EXPR_VAL); /* evaluated in type_of_fn */
- new_args[i].kind = EXPR_VAL;
- new_args[i].flags = param->expr.flags;
- new_args[i].type = param->type.kind == TYPE_TUPLE
- ? param->type.tuple[ident_idx]
- : param->type;
- new_args[i].val = param->type.kind == TYPE_TUPLE
- ? param->expr.val.tuple[ident_idx]
- : param->expr.val;
+ Value default_val;
+ if (fn_type->constness) {
+ /* TODO: evaluate once per decl, not once per ident */
+ Expression copy;
+ /* make a copy of the default argument, and type and evaluate it. */
+ Copier cop = {.block = tr->block, .allocr = tr->allocr};
+ copy_expr(&cop, &copy, &param->expr);
+ if (!types_expr(tr, &copy))
+ return false;
+ if (!eval_expr(tr->evalr, &copy, &default_val))
+ return false;
+ new_args[i].kind = EXPR_VAL;
+ new_args[i].flags = copy.flags;
+ new_args[i].type = copy.type.kind == TYPE_TUPLE
+ ? copy.type.tuple[ident_idx]
+ : copy.type;
+ new_args[i].val = copy.type.kind == TYPE_TUPLE
+ ? default_val.tuple[ident_idx]
+ : default_val;
+ } else {
+ /* it's already been evaluated */
+ assert(param->expr.kind == EXPR_VAL); /* evaluated in type_of_fn */
+ new_args[i].kind = EXPR_VAL;
+ new_args[i].flags = param->expr.flags;
+ new_args[i].type = param->type.kind == TYPE_TUPLE
+ ? param->type.tuple[ident_idx]
+ : param->type;
+ new_args[i].val = param->type.kind == TYPE_TUPLE
+ ? param->expr.val.tuple[ident_idx]
+ : param->expr.val;
+ }
}
}
ident_idx++;