diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-10-14 11:37:30 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-10-14 11:37:30 -0400 |
commit | c687651c6d6ece2db2afe6ad0083bfec6c497e52 (patch) | |
tree | 92bf3e2c594b8b660347e302b37a5cf8a3ba981c | |
parent | bfc7a22d0674371995c21fde5463bf08edbaabe2 (diff) |
more out params
-rw-r--r-- | cgen.c | 127 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | out.c | 28 | ||||
-rw-r--r-- | test.toc | 7 |
4 files changed, 133 insertions, 30 deletions
@@ -3,12 +3,16 @@ typedef struct { unsigned long ident_counter; ParsedFile *file; Block *block; + FnExpr *fn; /* which function are we in? (NULL for none) - not used during decls */ Evaluator *evalr; Identifier main_ident; } CGenerator; static bool cgen_stmt(CGenerator *g, Statement *s); static bool cgen_block(CGenerator *g, Block *b); +static bool cgen_expr(CGenerator *g, Expression *e); +static bool cgen_type_pre(CGenerator *g, Type *t, Location where); +static bool cgen_type_post(CGenerator *g, Type *t, Location where); static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *ev) { g->outc = out; @@ -228,6 +232,77 @@ static bool cgen_fn_header(CGenerator *g, FnExpr *f, Location where) { return true; } + +/* +Either set_expr or set_str should be NULL and either to_expr or to_str should be NULL +Also, set_str and/or to_str should be NULL +*/ +static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, Expression *to_expr, + const char *to_str) { + Type *type; + Location where; + if (set_expr) { + type = &set_expr->type; + where = set_expr->where; + } else { + assert(to_expr); + type = &to_expr->type; + where = to_expr->where; + } + switch (type->kind) { + case TYPE_BUILTIN: + case TYPE_FN: + case TYPE_PTR: + case TYPE_UNKNOWN: + if (set_expr) { + if (!cgen_expr(g, set_expr)) return false; + } else { + cgen_write(g, set_str); + } + cgen_write(g, " = "); + if (to_expr) { + if (!cgen_expr(g, to_expr)) return false; + } else { + cgen_write(g, to_str); + } + cgen_write(g, ";"); + break; + case TYPE_ARR: + cgen_write(g, "{"); + cgen_nl(g); + cgen_write(g, "size_t i;"); + if (!cgen_type_pre(g, type->arr.of, where)) return false; + cgen_write(g, "(*arr__in)"); + if (!cgen_type_post(g, type->arr.of, where)) return false; + cgen_write(g, " = "); + if (set_expr) { + if (!cgen_expr(g, set_expr)) return false; + } else { + cgen_write(g, set_str); + } + cgen_write(g, "; "); + if (!cgen_type_pre(g, type->arr.of, where)) return false; + cgen_write(g, "(*arr__out)"); + if (!cgen_type_post(g, type->arr.of, where)) return false; + cgen_write(g, " = "); + if (to_expr) { + if (!cgen_expr(g, to_expr)) return false; + } else { + cgen_write(g, to_str); + } + cgen_write(g, ";"); + cgen_nl(g); + cgen_write(g, "for (i = 0; i < %lu; i++) arr__out[i] = arr__in[i];", (unsigned long)type->arr.n); + cgen_nl(g); + cgen_write(g, "}"); + break; + case TYPE_VOID: + assert(0); + return false; + } + return true; +} + static bool cgen_expr(CGenerator *g, Expression *e) { switch (e->kind) { case EXPR_LITERAL_FLOAT: @@ -255,6 +330,10 @@ static bool cgen_expr(CGenerator *g, Expression *e) { break; case EXPR_BINARY_OP: { const char *s = ""; + if (e->binary.op == BINARY_SET) { + if (!cgen_set(g, e->binary.lhs, NULL, e->binary.rhs, NULL)) return false; + break; + } switch (e->binary.op) { case BINARY_SUB: s = "-"; break; @@ -264,8 +343,7 @@ static bool cgen_expr(CGenerator *g, Expression *e) { s = "*"; break; case BINARY_DIV: s = "/"; break; - case BINARY_SET: - s = "="; break; + case BINARY_SET: assert(0); break; case BINARY_GT: s = ">"; break; case BINARY_LT: @@ -412,8 +490,11 @@ static bool cgen_decl(CGenerator *g, Declaration *d) { if (!cgen_fn_header(g, &d->expr.fn, d->where)) return false; cgen_write(g, " "); + FnExpr *prev_fn = g->fn; + g->fn = &d->expr.fn; if (!cgen_block(g, &d->expr.fn.body)) return false; + g->fn = prev_fn; cgen_nl(g); cgen_nl(g); } else if (d->flags & DECL_FLAG_CONST) { @@ -426,7 +507,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) { if (!cgen_type_post(g, &d->type, d->where)) return false; if (g->block == NULL && (d->flags & DECL_FLAG_HAS_EXPR)) { cgen_write(g, " = "); - /* repeat expression for each ident iff we are in global scope */ + /* directly initialize iff we are in global scope */ if (!cgen_expr(g, &d->expr)) return false; } else if (!(d->flags & DECL_FLAG_HAS_EXPR)) { @@ -436,14 +517,26 @@ static bool cgen_decl(CGenerator *g, Declaration *d) { cgen_write(g, "; "); } + /* TODO: tuples */ if (g->block != NULL && (d->flags & DECL_FLAG_HAS_EXPR)) { + cgen_write(g, "{"); + cgen_nl(g); + if (!cgen_type_pre(g, &d->expr.type, d->expr.where)) return false; + cgen_write(g, "expr__"); + if (!cgen_type_post(g, &d->expr.type, d->expr.where)) return false; + cgen_write(g, "; "); + if (!cgen_set(g, NULL, "expr__", &d->expr, NULL)) + return false; arr_foreach(d->idents, Identifier, i) { - cgen_ident(g, *i); - cgen_write(g, " = "); - if (!cgen_expr(g, &d->expr)) + Expression e; + e.flags = 0; + e.kind = EXPR_IDENT; + e.type = d->type; + e.ident = *i; + if (!cgen_set(g, &e, NULL, NULL, "expr__")) return false; - cgen_write(g, "; "); } + cgen_write(g, "}"); } cgen_nl(g); } @@ -462,19 +555,15 @@ static bool cgen_stmt(CGenerator *g, Statement *s) { cgen_nl(g); break; case STMT_RET: - /* TODO (this doesn't work -- add fn to CGenerator) */ - if (g->block->ret_expr) { - if (cgen_uses_out_param(&g->block->ret_expr->type)) { - cgen_write(g, "*ret__ = "); - if (!cgen_expr(g, &s->ret.expr)) return false; - cgen_write(g, ";"); - } else { - cgen_write(g, "return "); - - if (!cgen_expr(g, &s->ret.expr)) return false; - } - } else { + if (g->fn->ret_type.kind == TYPE_VOID) { + cgen_write(g, "return"); + } else if (cgen_uses_out_param(&g->fn->ret_type)) { + if (!cgen_set(g, NULL, "*ret__", &s->ret.expr, NULL)) return false; cgen_write(g, "return"); + } else { + cgen_write(g, "return "); + + if (!cgen_expr(g, &s->ret.expr)) return false; } cgen_write(g, ";"); cgen_nl(g); @@ -1,6 +1,7 @@ /* TODO: re-do cgen +arrs are pointers make sure initializers for global variables are compile-time constants any odd number of "s for a string */ @@ -31,23 +31,33 @@ printf("%ld\n", i); void asdf(i64 i, i64( (*ret__)[3])) { i64( ret[3]) = {0}; -((ret[0])=(0*i)); -((ret[1])=(1*i)); -((ret[2])=(2*i)); -return; +i64( asdf[3]) = {0}; +(ret[0]) = (0*i);; +(ret[1]) = (1*i);; +(ret[2]) = (2*i);; +{ +size_t i;i64(*arr__in) = asdf; i64(*arr__out) = ret; +for (i = 0; i < 3; i++) arr__out[i] = arr__in[i]; +}; +{ +size_t i;i64(*arr__in) = *ret__; i64(*arr__out) = asdf; +for (i = 0; i < 3; i++) arr__out[i] = arr__in[i]; +}return; } void main__() { -i64(* x); x = ((i64(*))calloc(1, sizeof(i64))); -((*x)=17); +i64(* x); { +i64(*expr__); expr__ = ((i64(*))calloc(1, sizeof(i64)));x = expr__;} +(*x) = 17;; if (((*x)==0)) { -((*x)=((1+2)+(3-(5/62)))); +(*x) = ((1+2)+(3-(5/62)));; } else { -((*x)=((4+5)+6)); +(*x) = ((4+5)+6);; }; (puti((*x))); (free(x)); -void (* fptr)(i64, i64((*)[3])); fptr = asdf; +void (* fptr)(i64, i64((*)[3])); { +void (*expr__)(i64, i64((*)[3])); expr__ = asdf;fptr = expr__;} } i64 foo = 5; @@ -1,13 +1,16 @@ + puti @= fn(i: int) { #C("printf(\"%ld\\n\", i)"); }; asdf @= fn(i: int) [3]int { ret : [3]int; + asdf : [3]int; ret[0] = 0*i; ret[1] = 1*i; ret[2] = 2*i; - return ret; + asdf = ret; + return asdf; }; main @= fn() { @@ -27,4 +30,4 @@ foo := 5; bar := "Hello"; a, b := 123; x := 'a'; -sadkfj := -1293812;
\ No newline at end of file +sadkfj := -1293812; |