diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-11-25 09:47:03 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-11-25 09:47:03 -0500 |
commit | 0c1d471fa16aca1840ef792e9f123ecf78d3df25 (patch) | |
tree | 26c8a8ee059455913874113e4476ed017117dae0 | |
parent | 76f800ae81d5530e2b07a1edf97e57710bac0d13 (diff) |
fixed problems with return declarations
-rw-r--r-- | cgen.c | 2 | ||||
-rw-r--r-- | eval.c | 11 | ||||
-rw-r--r-- | main.c | 2 | ||||
-rw-r--r-- | parse.c | 4 | ||||
-rw-r--r-- | test.toc | 7 | ||||
-rw-r--r-- | types.c | 44 |
6 files changed, 36 insertions, 34 deletions
@@ -1691,7 +1691,7 @@ static bool cgen_val(CGenerator *g, Value v, Type *t, Location where) { static bool cgen_decl(CGenerator *g, Declaration *d) { int has_expr = d->flags & DECL_HAS_EXPR; bool is_tuple = d->type.kind == TYPE_TUPLE; - if ((d->flags & DECL_IS_CONST) || g->block == NULL) { + if ((d->flags & DECL_IS_CONST) || (g->block == NULL && g->fn == NULL)) { /* declarations where we use a value */ for (size_t idx = 0; idx < arr_len(d->idents); idx++) { Identifier i = d->idents[idx]; @@ -1431,17 +1431,22 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { } arr_foreach(fn->ret_decls, Declaration, d) { int idx = 0; + Value val; + if (d->flags & DECL_HAS_EXPR) + if (!eval_expr(ev, &d->expr, &val)) + return false; + arr_foreach(d->idents, Identifier, i) { - Type *type = d->type.kind == TYPE_TUPLE ? &d->type.tuple[idx++] : &d->type; + Type *type = d->type.kind == TYPE_TUPLE ? &d->type.tuple[idx] : &d->type; IdentDecl *id = ident_decl(*i); if (d->flags & DECL_HAS_EXPR) { - assert(d->expr.kind == EXPR_VAL); - copy_val(NULL, &id->val, &d->expr.val, type); + id->val = d->type.kind == TYPE_TUPLE ? val.tuple[idx] : val; id->flags |= IDECL_HAS_VAL; } else { id->flags |= IDECL_HAS_VAL; id->val = val_zero(type); } + idx++; } } arr_clear(&args); @@ -1,7 +1,5 @@ /* TODO: -get fn(x: int) y := x {} to work -don't cgen decls etc. in parameter initializers (hey we have a parameter flag now) check for leaks clean up @@ -824,10 +824,6 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) { return false; Declaration *new_params = NULL; arr_foreach(f->params, Declaration, param) { - if (param->type.kind == TYPE_TUPLE) { - err_print(param->where, "Functions can't have tuple parameters."); - return false; - } /* whenever there's (x, y: int), turn it into (x: int, y: int) */ arr_foreach(param->idents, Identifier, ident) { Declaration *new_param = parser_arr_add(p, &new_params); @@ -8,10 +8,11 @@ puti @= fn(x: int) { // }; -f @= fn(x: int) y := x { - puti(x); +f @= fn(x: int, r := x) y := x { }; main @= fn() { - puti(f(1238)); +R @= f(2837); +puti(R); + puti(f(3218)); };
\ No newline at end of file @@ -198,6 +198,7 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags) bool success = true; bool entered_fn = false; bool added_param_decls = false; + FnExpr *prev_fn = tr->fn; FnExpr fn_copy; if (!(flags & TYPE_OF_FN_NO_COPY_EVEN_IF_CONST) && fn_has_any_const_params(f)) { @@ -211,9 +212,16 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags) Type *ret_type = typer_arr_add(tr, &t->fn.types); if (!fn_enter(f, SCOPE_CHECK_REDECL)) return false; + tr->fn = f; + entered_fn = true; arr_foreach(f->params, Declaration, decl) { if (!types_decl(tr, decl)) return false; + if (decl->type.kind == TYPE_TUPLE) { + err_print(decl->where, "Functions can't have tuple parameters."); + return false; + } + if (!type_resolve(tr, &decl->type, where)) return false; U32 is_at_all_const = decl->flags & (DECL_IS_CONST | DECL_SEMI_CONST); @@ -230,13 +238,13 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags) Value val; if (!eval_expr(tr->evalr, &decl->expr, &val)) { info_print(decl->where, "Was trying to evaluate default arguments (which must be constants!)"); - fn_exit(f); for (Declaration *p = f->params; p != decl; p++) { if (p->flags & DECL_IS_CONST) arr_foreach(p->idents, Identifier, ident) arr_remove_last(&(*ident)->decls); } - return false; + success = false; + goto ret; } decl->expr.kind = EXPR_VAL; decl->expr.val = val; @@ -274,16 +282,6 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags) arr_foreach(f->ret_decls, Declaration, d) { if (!types_decl(tr, d)) return false; - /* evaluate ret decl initializer */ - if (d->flags & DECL_HAS_EXPR) { - Value val; - if (!eval_expr(tr->evalr, &d->expr, &val)) { - success = false; - goto ret; - } - d->expr.kind = EXPR_VAL; - d->expr.val = val; - } } if (arr_len(f->ret_decls) == 1 && arr_len(f->ret_decls[0].idents) == 1) { f->ret_type = f->ret_decls[0].type; @@ -313,17 +311,21 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags) } ret: /* cleanup */ - if (added_param_decls) { - /* remove constant parameter ident decls */ - arr_foreach(f->params, Declaration, param) { - if (param->flags & DECL_IS_CONST) { - arr_foreach(param->idents, Identifier, ident) - arr_remove_last(&(*ident)->decls); + + if (entered_fn) { + fn_exit(f); + tr->fn = prev_fn; + + if (added_param_decls) { + /* remove constant parameter ident decls */ + arr_foreach(f->params, Declaration, param) { + if (param->flags & DECL_IS_CONST) { + arr_foreach(param->idents, Identifier, ident) + arr_remove_last(&(*ident)->decls); + } } } } - - if (entered_fn) fn_exit(f); return success; } @@ -341,7 +343,7 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) { Declaration *d = decl->decl; bool captured = false; if (decl->scope != NULL) - for (Block *block = tr->block; block != decl->scope; block = block->parent) { + for (Block *block = tr->block; block && block != decl->scope; block = block->parent) { if (block->flags & BLOCK_IS_FN) { captured = true; break; |