diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-11-13 14:35:26 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-11-13 14:35:26 -0500 |
commit | 41bb75cea1821ad2b676fdbb4847ce5441f00f42 (patch) | |
tree | 9faedd528ff1a10e1041ebf437ce513d8b99800f | |
parent | b1352ae5faada93af4443ec9a0e66c2d08872484 (diff) |
evaluating default arguments
-rw-r--r-- | cgen.c | 24 | ||||
-rw-r--r-- | main.c | 3 | ||||
-rw-r--r-- | test.toc | 9 | ||||
-rw-r--r-- | types.c | 24 |
4 files changed, 53 insertions, 7 deletions
@@ -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; @@ -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){} @@ -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(); @@ -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; |