diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-10-11 11:20:04 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-10-11 11:20:04 -0400 |
commit | 60566944cb85c60e4243475c964b88b206cfb959 (patch) | |
tree | acdd8ae14fdb83a953c9e64479ce912c5559dfe7 | |
parent | 27319a805be7c9dfcee62efd6181dec9afc50dd4 (diff) |
more cgen (bin ops, direct c)
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | cgen.c | 130 | ||||
-rw-r--r-- | decls_cgen.c | 76 | ||||
-rw-r--r-- | main.c | 2 | ||||
-rw-r--r-- | out.c | bin | 563 -> 818 bytes | |||
-rw-r--r-- | test.toc | 13 |
6 files changed, 208 insertions, 14 deletions
@@ -1 +1,2 @@ toc +a.out
\ No newline at end of file @@ -3,13 +3,17 @@ typedef struct { unsigned long ident_counter; ParsedFile *file; Block *block; + Evaluator *evalr; Identifier main_ident; } CGenerator; -static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids) { +static bool cgen_stmt(CGenerator *g, Statement *s); + +static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *ev) { g->outc = out; g->ident_counter = 0; g->main_ident = ident_get(ids, "main"); + g->evalr = ev; } static void cgen_block_enter(CGenerator *g, Block *b) { @@ -64,6 +68,10 @@ static void cgen_ident(CGenerator *g, Identifier i) { } } +static void cgen_ident_id(CGenerator *g, unsigned long id) { + cgen_write(g, "a%lu_", id); +} + static bool cgen_type_post(CGenerator *g, Type *t, Location where); static bool cgen_type_pre(CGenerator *g, Type *t, Location where) { switch (t->kind) { @@ -150,12 +158,14 @@ static bool cgen_fn_header(CGenerator *g, FnExpr *f, Location where) { if (f->c.name) { cgen_ident(g, f->c.name); } else { - /* TODO */ + cgen_ident_id(g, f->c.id); } if (!cgen_type_post(g, &f->ret_type, where)) return false; cgen_write(g, "("); arr_foreach(f->params, Declaration, d) { arr_foreach(d->idents, Identifier, i) { + if (d != f->params || i != d->idents) + cgen_write(g, ", "); if (!cgen_type_pre(g, &d->type, where)) return false; cgen_write(g, " "); @@ -193,6 +203,44 @@ static bool cgen_expr(CGenerator *g, Expression *e) { case EXPR_IDENT: cgen_ident(g, e->ident); break; + case EXPR_BINARY_OP: { + const char *s = ""; + switch (e->binary.op) { + case BINARY_SUB: + s = "-"; break; + case BINARY_ADD: + s = "+"; break; + case BINARY_MUL: + s = "*"; break; + case BINARY_DIV: + s = "/"; break; + case BINARY_SET: + s = "="; break; + case BINARY_GT: + s = ">"; break; + case BINARY_LT: + s = "<"; break; + case BINARY_GE: + s = ">="; break; + case BINARY_LE: + s = "<="; break; + case BINARY_EQ: + s = "=="; break; + case BINARY_NE: + s = "!="; break; + case BINARY_AT_INDEX: + s = "["; break; + } + cgen_write(g, "("); + if (!cgen_expr(g, e->binary.lhs)) + return false; + cgen_write(g, "%s", s); + if (!cgen_expr(g, e->binary.rhs)) + return false; + if (e->binary.op == BINARY_AT_INDEX) + cgen_write(g, "]"); + cgen_write(g, ")"); + } break; case EXPR_UNARY_OP: { const char *s = ""; switch (e->unary.op) { @@ -207,23 +255,79 @@ static bool cgen_expr(CGenerator *g, Expression *e) { case UNARY_DEL: s = "free("; break; } - cgen_write(g, s); + cgen_write(g, "("); + cgen_write(g, "%s", s); if (!cgen_expr(g, e->unary.of)) return false; if (e->unary.op == UNARY_DEL) cgen_write(g, ")"); + cgen_write(g, ")"); } break; + case EXPR_NEW: + cgen_write(g, "calloc(1, sizeof("); + if (!cgen_type_pre(g, &e->new.type, e->where)) + return false; + if (!cgen_type_post(g, &e->new.type, e->where)) + return false; + cgen_write(g, "))"); + break; + case EXPR_DIRECT: + switch (e->direct.which) { + case DIRECT_C: { + Value val; + eval_expr(g->evalr, &e->direct.args[0], &val); + fwrite(val.arr, 1, e->direct.args[0].type.arr.n, cgen_writing_to(g)); + } break; + case DIRECT_COUNT: assert(0); break; + } + break; } return true; } +static bool cgen_block(CGenerator *g, Block *b) { + Block *prev = g->block; + cgen_block_enter(g, b); + cgen_write(g, "{"); + cgen_nl(g); + arr_foreach(b->stmts, Statement, s) + if (!cgen_stmt(g, s)) + return false; + + cgen_block_exit(g, prev); + cgen_write(g, "}"); + return true; +} + +static void cgen_zero_value(CGenerator *g, Type *t) { + switch (t->kind) { + case TYPE_BUILTIN: + cgen_write(g, "0"); + break; + case TYPE_PTR: + case TYPE_FN: + cgen_write(g, "NULL"); + break; + case TYPE_ARR: + cgen_write(g, "{"); + cgen_zero_value(g, t->arr.of); + cgen_write(g, "}"); + break; + case TYPE_VOID: + case TYPE_UNKNOWN: + case TYPE_TUPLE: + assert(0); + break; + } +} + static bool cgen_decl(CGenerator *g, Declaration *d) { if (cgen_is_fn_direct(g, d)) { if (!cgen_fn_header(g, &d->expr.fn, d->where)) return false; - cgen_write(g, " {"); - cgen_nl(g); - cgen_write(g, "}"); + cgen_write(g, " "); + if (!cgen_block(g, &d->expr.fn.body)) + return false; cgen_nl(g); cgen_nl(g); } else if (d->flags & DECL_FLAG_CONST) { @@ -234,20 +338,25 @@ static bool cgen_decl(CGenerator *g, Declaration *d) { cgen_write(g, " "); cgen_ident(g, *i); if (!cgen_type_post(g, &d->type, d->where)) return false; - if (g->block == NULL) { - /* repeat expression for each ident iff we are in global scope */ + if (g->block == NULL && (d->flags & DECL_FLAG_HAS_EXPR)) { cgen_write(g, " = "); + /* repeat expression for each ident iff we are in global scope */ if (!cgen_expr(g, &d->expr)) return false; + } else if (!(d->flags & DECL_FLAG_HAS_EXPR)) { + cgen_write(g, " = "); + cgen_zero_value(g, &d->type); } + cgen_write(g, "; "); } - if (g->block != NULL) { + if (g->block != NULL && (d->flags & DECL_FLAG_HAS_EXPR)) { arr_foreach(d->idents, Identifier, i) { cgen_ident(g, *i); cgen_write(g, " = "); if (!cgen_expr(g, &d->expr)) return false; + cgen_write(g, "; "); } } cgen_nl(g); @@ -263,6 +372,8 @@ static bool cgen_stmt(CGenerator *g, Statement *s) { break; case STMT_EXPR: if (!cgen_expr(g, &s->expr)) return false; + cgen_write(g, ";"); + cgen_nl(g); break; case STMT_RET: /* TODO */ @@ -276,6 +387,7 @@ static bool cgen_decls_file(CGenerator *g, ParsedFile *f); static bool cgen_file(CGenerator *g, ParsedFile *f) { g->file = f; cgen_write(g, "#include <stdint.h>\n" + "#include <stdlib.h>\n" "typedef int8_t i8;\n" "typedef int16_t i16;\n" "typedef int32_t i32;\n" diff --git a/decls_cgen.c b/decls_cgen.c index 5310981..bbdb8a3 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -1,13 +1,87 @@ +static bool cgen_decls_stmt(CGenerator *g, Statement *s); +static bool cgen_decls_block(CGenerator *g, Block *b); + static bool cgen_decls_expr(CGenerator *g, Expression *e) { + switch (e->kind) { + case EXPR_UNARY_OP: + if (!cgen_decls_expr(g, e->unary.of)) + return false; + break; + case EXPR_BINARY_OP: + if (!cgen_decls_expr(g, e->binary.lhs) + || !cgen_decls_expr(g, e->binary.rhs)) + return false; + break; + case EXPR_CAST: + if (!cgen_decls_expr(g, e->cast.expr)) + return false; + break; + case EXPR_CALL: + if (!cgen_decls_expr(g, e->call.fn)) + return false; + arr_foreach(e->call.arg_exprs, Expression, a) + if (!cgen_decls_expr(g, a)) + return false; + break; + case EXPR_BLOCK: + if (!cgen_decls_block(g, &e->block)) + return false; + break; + case EXPR_IF: + if (e->if_.cond) + if (!cgen_decls_expr(g, e->if_.cond)) + return false; + if (!cgen_decls_block(g, &e->if_.body)) + return false; + if (e->if_.next_elif) + if (!cgen_decls_expr(g, e->if_.next_elif)) + return false; + break; + case EXPR_WHILE: + if (e->while_.cond) + if (!cgen_decls_expr(g, e->while_.cond)) + return false; + if (!cgen_decls_block(g, &e->while_.body)) + return false; + break; + case EXPR_TUPLE: + arr_foreach(e->tuple, Expression, x) + if (!cgen_decls_expr(g, x)) + return false; + break; + case EXPR_FN: + e->fn.c.name = NULL; + e->fn.c.id = g->ident_counter++; + if (!cgen_fn_header(g, &e->fn, e->where)) + return false; + cgen_write(g, ";\n"); + if (!cgen_decls_block(g, &e->fn.body)) + return false; + break; + case EXPR_DIRECT: + case EXPR_NEW: + case EXPR_IDENT: + case EXPR_LITERAL_BOOL: + case EXPR_LITERAL_INT: + case EXPR_LITERAL_STR: + case EXPR_LITERAL_CHAR: + case EXPR_LITERAL_FLOAT: + break; + } return true; } static bool cgen_decls_block(CGenerator *g, Block *b) { + Block *prev = g->block; + cgen_block_enter(g, b); + arr_foreach(b->stmts, Statement, s) + cgen_decls_stmt(g, s); + cgen_block_exit(g, prev); return true; } static bool cgen_decls_decl(CGenerator *g, Declaration *d) { - if ((d->flags & DECL_FLAG_HAS_EXPR) && d->expr.kind == EXPR_FN && arr_len(d->idents) == 1) { + if (cgen_is_fn_direct(g, d)) { d->expr.fn.c.name = d->idents[0]; if (!cgen_fn_header(g, &d->expr.fn, d->where)) return false; @@ -83,7 +83,7 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } CGenerator g; - cgen_create(&g, out, &file_idents); + cgen_create(&g, out, &file_idents, &ev); cgen_file(&g, &f); tokr_free(&t); Binary files differ@@ -1,10 +1,17 @@ main @= fn() { - + adsf @= fn(x,asdf,sadf,sdf,fds : i64, y,zdfsadf,sd: &&f32) u8 { + 0 + }; + x := new int; + *x = 1+2+3-5/62; + adsfklk : [5]int; + adsfklk[0] = 521; + #C("printf(\"%ld %ld\\n\", *x, adsfklk[0]);"); +del x; }; foo := 5; bar := "Hello"; a, b := 123; x := 'a'; -sadkfj := -1293812; -kjdshaf := *&*&*&*&*&x;
\ No newline at end of file +sadkfj := -1293812;
\ No newline at end of file |