diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-01-25 14:36:38 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-01-25 14:36:38 -0500 |
commit | 27acf3754529988de9d43ba0abb8e5b3bbb3da31 (patch) | |
tree | a0a2a81286be40c10f2ac8b8cf172ec9535a58a8 | |
parent | c74626a3dda0e416dbb0673230933ca223bc9a5b (diff) |
fixed cgen tuples
-rwxr-xr-x | build.sh | 2 | ||||
-rw-r--r-- | cgen.c | 71 | ||||
-rw-r--r-- | parse.c | 2 | ||||
-rw-r--r-- | scope.c | 2 | ||||
-rw-r--r-- | test.toc | 2 |
5 files changed, 68 insertions, 11 deletions
@@ -27,7 +27,7 @@ if [ "$1" = "" ]; then fi fi -DEBUG_FLAGS="-O0 -g3 $WARNINGS -std=c11 -DTOC_DEBUG" +DEBUG_FLAGS="-O0 -g3 -pipe $WARNINGS -std=c11 -DTOC_DEBUG" RELEASE_FLAGS="-O3 -s -DNDEBUG $WARNINGS -std=c11" if [ "$1" = "release" ]; then @@ -655,6 +655,11 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, case EXPR_TUPLE: /* e.g. a, b = 3, 5; */ for (size_t i = 0; i < arr_len(to->tuple); ++i) { + if (exprs) + if (!cgen_expr_pre(g, &exprs[i])) + return false; + } + for (size_t i = 0; i < arr_len(to->tuple); ++i) { char *s = NULL, buf[64]; Expression *e = NULL; if (idents) @@ -670,14 +675,23 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, } break; case EXPR_CALL: { + Constness *constness = to->call.fn->type.fn.constness; + int i = 0; /* e.g. a, b = fn_which_returns_tuple(); */ + arr_foreach(to->call.arg_exprs, Expression, arg) { + if (!constness || !arg_is_const(arg, constness[i])) { + if (!cgen_expr_pre(g, arg)) + return false; + } + } + if (!cgen_expr_pre(g, to->call.fn)) return false; + if (!cgen_expr(g, to->call.fn)) return false; if (to->call.instance) cgen_fn_instance_number(g, to->call.instance->c.id); cgen_write(g, "("); bool any_args = false; - Constness *constness = to->call.fn->type.fn.constness; - int i = 0; + i = 0; arr_foreach(to->call.arg_exprs, Expression, arg) { if (!constness || !arg_is_const(arg, constness[i])) { if (any_args) @@ -720,6 +734,11 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, prefix_id = to->each->c.id; goto prefixed; prefixed: + for (size_t i = 0; i < arr_len(to->type.tuple); ++i) { + if (exprs) + if (!cgen_expr_pre(g, &exprs[i])) + return false; + } for (unsigned long i = 0; i < (unsigned long)arr_len(to->type.tuple); ++i) { cgen_write(g, "("); if (exprs) { @@ -1024,7 +1043,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) { break; case EXPR_CALL: { if (!cgen_expr_pre(g, e->call.fn)) return false; - int i = 0; + size_t i = 0; Constness *constness = e->call.fn->type.fn.constness; arr_foreach(e->call.arg_exprs, Expression, arg) { if (!constness || !arg_is_const(arg, constness[i])) { @@ -1032,8 +1051,44 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) { } ++i; } - if (cgen_uses_ptr(&e->type) - && e->type.kind != TYPE_TUPLE) { + if (e->type.kind == TYPE_TUPLE) { + Type *t = &e->type; + size_t ntypes = arr_len(t->tuple); + IdentID *ids = err_malloc(ntypes * sizeof *ids); + for (i = 0; i < ntypes; ++i) { + ids[i] = ++g->ident_counter; + if (!cgen_type_pre(g, &t->tuple[i], e->where)) + return false; + cgen_write(g, " "); + cgen_ident_id(g, ids[i]); + if (!cgen_type_post(g, &t->tuple[i], e->where)) + return false; + cgen_write(g, "; "); + } + if (!cgen_expr(g, e->call.fn)) return false; + if (e->call.instance) { + cgen_fn_instance_number(g, e->call.instance->c.id); + } + cgen_write(g, "("); + bool any_args = false; + i = 0; + arr_foreach(e->call.arg_exprs, Expression, arg) { + if (!constness || !arg_is_const(arg, constness[i])) { + if (any_args) cgen_write(g, ", "); + any_args = true; + if (!cgen_expr(g, arg)) + return false; + } + ++i; + } + for (i = 0; i < ntypes; ++i) { + if (any_args) cgen_write(g, ", "); + any_args = true; + cgen_write(g, "&"); + cgen_ident_id(g, ids[i]); + } + cgen_write(g, ");"); + } else if (cgen_uses_ptr(&e->type)) { e->call.c.id = ++g->ident_counter; if (!cgen_type_pre(g, &e->type, e->where)) return false; cgen_write(g, " "); @@ -1436,7 +1491,9 @@ static bool cgen_expr(CGenerator *g, Expression *e) { cgen_ident_id(g, e->each->c.id); break; case EXPR_CALL: - if (cgen_uses_ptr(&e->type)) { + if (e->type.kind == TYPE_TUPLE) { + /* the only situation in which this could happen is if the return value doesn't matter */ + } else if (cgen_uses_ptr(&e->type)) { cgen_ident_id(g, e->call.c.id); } else { FnType *fn_type = &e->call.fn->type.fn; @@ -1862,10 +1919,10 @@ static bool cgen_decl(CGenerator *g, Declaration *d) { } if (has_expr) { assert((g->block || g->fn) && !(d->flags & DECL_IS_CONST)); - if (!cgen_expr_pre(g, &d->expr)) return false; if (d->expr.type.kind == TYPE_TUPLE) { if (!cgen_set_tuple(g, NULL, d->idents, NULL, &d->expr)) return false; } else { + if (!cgen_expr_pre(g, &d->expr)) return false; if (nidents > 1) { /* set expr__ first to make sure side effects don't happen twice */ cgen_write(g, "{"); @@ -954,7 +954,7 @@ static int op_precedence(Keyword op) { static bool parse_expr(Parser *p, Expression *e, Token *end) { Tokenizer *t = p->tokr; -#if 1 +#if 0 { Location where; where.file = p->file; @@ -21,7 +21,7 @@ static bool DEBUG_UNDERSCORE(add_ident_decls)(SOURCE_LOCATION_PARAMS Block *b, D err_print(d->where, "Re-declaration of identifier in the same block."); info_print(prev->decl->where, "Previous declaration was here."); #ifdef TOC_DEBUG - info_print(d->where, "First declaration was done by %s:%d, second was done by %s:%d.", prev->src_file, prev->src_line, src_file, src_line); + err_fprint(d->where.file->ctx, "First declaration was done by %s:%d, second was done by %s:%d.\n", prev->src_file, prev->src_line, src_file, src_line); #endif ret = false; continue; @@ -1,6 +1,6 @@ addmul ::= fn (x::=0, y:=0) add := x+y, mul := x*y { - + a : []char = x; }; main ::= fn() { |