diff options
-rw-r--r-- | cgen.c | 30 | ||||
-rw-r--r-- | main.c | 6 | ||||
-rw-r--r-- | parse.c | 19 | ||||
-rw-r--r-- | test.toc | 50 | ||||
-rw-r--r-- | types.c | 2 |
5 files changed, 48 insertions, 59 deletions
@@ -1929,13 +1929,22 @@ static void cgen_ret(CGenerator *g, Block *returning_from, Expression *ret_expr) FnExpr *f = g->fn; if (ret_expr) { cgen_expr_pre(g, ret_expr); - /* set ret_ to ret_expr */ - cgen_type_pre(g, &ret_expr->type); - cgen_write(g, " ret_"); - cgen_type_post(g, &ret_expr->type); - cgen_write(g, "; "); - cgen_set(g, NULL, "ret_", ret_expr, NULL); - cgen_nl(g); + if (cgen_uses_ptr(&f->ret_type)) { + if (f->ret_type.kind == TYPE_TUPLE) { + cgen_set_tuple(g, NULL, NULL, "*ret__", ret_expr); + } else { + cgen_set(g, NULL, "*ret__", ret_expr, NULL); + } + } else { + /* set ret_ to ret_expr */ + cgen_type_pre(g, &ret_expr->type); + cgen_write(g, " ret_"); + cgen_type_post(g, &ret_expr->type); + cgen_write(g, "; "); + cgen_set(g, NULL, "ret_", ret_expr, NULL); + cgen_nl(g); + } + } cgen_deferred_up_to(g, returning_from); if (f->ret_decls) { @@ -1976,16 +1985,13 @@ static void cgen_ret(CGenerator *g, Block *returning_from, Expression *ret_expr) return; } if (cgen_uses_ptr(&f->ret_type)) { + #if 0 Expression ret = {0}; ret.kind = EXPR_IDENT; ret.ident = ident_get(g->globals, "ret_"); ret.flags = EXPR_FOUND_TYPE; ret.type = f->ret_type; - if (f->ret_type.kind == TYPE_TUPLE) { - cgen_set_tuple(g, NULL, NULL, "*ret__", &ret); - } else { - cgen_set(g, NULL, "*ret__", &ret, NULL); - } + #endif cgen_writeln(g, " return;"); } else if (f->ret_type.kind == TYPE_VOID) { cgen_writeln(g, "return;"); @@ -8,10 +8,10 @@ /* TODO: -switch to: - static void - foo() { get rid of angle brackets for tuple types - just check if a TYPE_EXPR which is an EXPR_TUPLE is returned +allow #ifs in structs + - you can just have a dyn array of stmts and when you want to resolve the struct, + just type the statements, then loop over them (going into blocks if necessary) use &&, || start making a standard library... (printf; stringbuilder would be nice to have) @@ -455,6 +455,22 @@ static Status parse_args(Parser *p, Argument **args) { ++t->token; /* move past ) */ return true; } +static void correct_ret_type(Parser *p, Type *ret_type) { + if (ret_type->kind == TYPE_EXPR && ret_type->expr->kind == EXPR_TUPLE) { + /* it's returning a tuple! */ + Expression *tuple_members = ret_type->expr->tuple; + size_t ntuple_members = arr_len(tuple_members); + ret_type->kind = TYPE_TUPLE; + ret_type->tuple = NULL; + arr_set_lena(&ret_type->tuple, ntuple_members, p->allocr); + for (size_t i = 0; i < ntuple_members; ++i) { + Type *out_type = &ret_type->tuple[i]; + out_type->flags = 0; + out_type->kind = TYPE_EXPR; + out_type->expr = &tuple_members[i]; + } + } +} /* where will be filled out with the location, if not NULL */ static Status parse_type(Parser *p, Type *type, Location *where) { @@ -521,6 +537,7 @@ static Status parse_type(Parser *p, Type *type, Location *where) { } else { if (!parse_type(p, ret_type, NULL)) return false; + correct_ret_type(p, ret_type); } break; } @@ -1003,6 +1020,7 @@ static Status parse_fn_expr(Parser *p, FnExpr *f) { success = false; goto ret; } + correct_ret_type(p, &f->ret_type); } p->block = prev_block; /* be nice to parse_block */ if (!parse_block(p, &f->body, PARSE_BLOCK_DONT_CREATE_IDENTS)) @@ -1759,6 +1777,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { Token *new_end = end - 1; /* parse to ending ) */ if (!parse_expr(p, e, new_end)) return false; + e->where.start = start; /* make sure we keep e->where.start intact */ ++t->token; /* move past closing ) */ goto success; } @@ -1,48 +1,12 @@ #include "std/io.toc", io; - -plusone ::= fn(n : int) x := n { +f ::= fn() (int, int) { + x := 5; + y := 88; defer x += 1; + x, y } - -same ::= fn(n : int) int { - x := n; - defer x += 1; - x -} - main ::= fn() { - io.puti(plusone(3)); - io.puti(same(3)); - defer io.puts("deferred from main()"); - for i := 1..10 { - defer io.puts("deferred from for"); - io.puti(i); - if i == 2 { - defer io.puts("deferred from if1"); - defer io.puts("deferred from if2"); - defer io.puts("deferred from if3"); - defer io.puts("deferred from if4"); - defer io.puts("deferred from if5"); - defer io.puts("deferred from if6"); - defer io.puts("deferred from if7"); - defer io.puts("deferred from if8"); - continue; - } - if i == 8 { - break; - } - } - i := 0; - while { - defer io.puts("deferred from while"); - i += 1; - io.puti(i); - if i % 2 == 0 { continue; } - if i == 7 { - defer io.puts("deferred from if"); - break; - } - - } - io.puts("end of main()"); + a,b := f(); + io.puti(a); + io.puti(b); } @@ -828,7 +828,7 @@ static Status type_resolve(Typer *tr, Type *t, Location where) { if (t->expr->type.kind == TYPE_UNKNOWN && tr->err_ctx->have_errored) return false; /* silently fail (e.g. if a function couldn't be typed) */ if (!type_is_builtin(&t->expr->type, BUILTIN_TYPE)) { - err_print(where, "This expression is not a type, but it's being used as one."); + err_print(t->expr->where, "This expression is not a type, but it's being used as one."); return false; } Expression *expr = t->expr; |