summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-11-13 14:35:26 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-11-13 14:35:26 -0500
commit41bb75cea1821ad2b676fdbb4847ce5441f00f42 (patch)
tree9faedd528ff1a10e1041ebf437ce513d8b99800f
parentb1352ae5faada93af4443ec9a0e66c2d08872484 (diff)
evaluating default arguments
-rw-r--r--cgen.c24
-rw-r--r--main.c3
-rw-r--r--test.toc9
-rw-r--r--types.c24
4 files changed, 53 insertions, 7 deletions
diff --git a/cgen.c b/cgen.c
index 956fd83..0e27220 100644
--- a/cgen.c
+++ b/cgen.c
@@ -982,8 +982,14 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
break;
case EXPR_CALL: {
if (!cgen_expr_pre(g, e->call.fn)) return false;
- arr_foreach(e->call.arg_exprs, Expression, arg)
- if (!cgen_expr_pre(g, arg)) return false;
+ int i = 0;
+ bool *constant = e->call.fn->type.fn.constant;
+ arr_foreach(e->call.arg_exprs, Expression, arg) {
+ if (!constant || !constant[i]) {
+ if (!cgen_expr_pre(g, arg)) return false;
+ }
+ i++;
+ }
if (cgen_uses_ptr(&e->type)) {
e->call.c.id = g->ident_counter++;
if (!cgen_type_pre(g, &e->type, e->where)) return false;
@@ -1078,6 +1084,18 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
return false;
break;
case EXPR_VAL:
+ if (!cgen_val_pre(g, e->val, &e->type, e->where))
+ return false;
+ if (!cgen_type_pre(g, &e->type, e->where)) return false;
+ e->val_c_id = g->ident_counter++;
+ cgen_write(g, " ");
+ cgen_ident_id(g, e->val_c_id);
+ if (!cgen_type_post(g, &e->type, e->where)) return false;
+ cgen_write(g, " = ");
+ if (!cgen_val(g, e->val, &e->type, e->where))
+ return false;
+ cgen_write(g, ";");
+ cgen_nl(g);
break;
case EXPR_LITERAL_INT:
case EXPR_LITERAL_FLOAT:
@@ -1399,7 +1417,7 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
cgen_ident_id(g, e->slice.c.id);
break;
case EXPR_VAL:
- assert(!*"Value expressions cannot be cgenerated!!!");
+ cgen_ident_id(g, e->val_c_id);
break;
}
return true;
diff --git a/main.c b/main.c
index 1378718..a7a0888 100644
--- a/main.c
+++ b/main.c
@@ -1,8 +1,9 @@
/*
TODO:
+evaluate default arguments
+make sure they're only evaluated once
compile time arguments + out parameters (in C)
double check that val_get_ptr is being used everywhere it should be
-evaluate default arguments
compile-time arguments for out parameter functions
compile-time arguments for functions returning tuples
deal with x, y @= fn(x: int, y @ int){}
diff --git a/test.toc b/test.toc
index 8e52b1b..dda957a 100644
--- a/test.toc
+++ b/test.toc
@@ -22,15 +22,22 @@ puti @= fn(x: int) {
// f.z += 43.2;
// };
-f @= fn(x @ int) i: int {
+f @= fn(x @ int = 3+5) i: int {
i = x;
};
+g @= fn(x, y : (int, int) = (3+5, 4+9)) i: int {
+ i = x + y;
+};
+
main @= fn() {
puti(f(313));
puti(f(128));
puti(f(231));
puti(f(100+213));
+ puti(f());
+ puti(g());
+
};
// b := bar();
diff --git a/types.c b/types.c
index 00f72e8..dcfbfd8 100644
--- a/types.c
+++ b/types.c
@@ -254,6 +254,15 @@ static bool type_of_fn(Typer *tr, Expression *e, Type *t) {
}
}
}
+ if (decl->flags & DECL_HAS_EXPR) {
+ Value val;
+ if (!eval_expr(tr->evalr, &decl->expr, &val)) {
+ info_print(decl->where, "Was trying to evaluate default arguments (which must be constants!)");
+ return false;
+ }
+ decl->expr.kind = EXPR_VAL;
+ decl->expr.val = val;
+ }
for (size_t i = 0; i < arr_len(decl->idents); i++) {
Type *param_type = typer_arr_add(tr, &t->fn.types);
*param_type = decl->type;
@@ -1050,6 +1059,7 @@ 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;
arr_foreach(param->idents, Identifier, ident) {
if (index == i) {
if (is_required) {
@@ -1058,9 +1068,18 @@ static bool types_expr(Typer *tr, Expression *e) {
free(s);
return false;
} else {
- new_args[i] = param->expr;
+ 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++;
index++;
}
}
@@ -1449,7 +1468,8 @@ static bool types_expr(Typer *tr, Expression *e) {
t->tuple = NULL;
arr_foreach(e->tuple, Expression, x) {
Type *x_type = typer_arr_add(tr, &t->tuple);
- types_expr(tr, x);
+ if (!types_expr(tr, x))
+ return false;
*x_type = x->type;
}
break;