summaryrefslogtreecommitdiff
path: root/typedefs_cgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'typedefs_cgen.c')
-rw-r--r--typedefs_cgen.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/typedefs_cgen.c b/typedefs_cgen.c
new file mode 100644
index 0000000..d6a3f5e
--- /dev/null
+++ b/typedefs_cgen.c
@@ -0,0 +1,143 @@
+static bool typedefs_stmt(CGenerator *g, Statement *s);
+
+static bool typedefs_block(CGenerator *g, Block *b) {
+ Block *prev = g->block;
+ if (!cgen_block_enter(g, b))
+ return false;
+ arr_foreach(b->stmts, Statement, s)
+ typedefs_stmt(g, s);
+ cgen_block_exit(g, prev);
+ return true;
+}
+
+static bool typedefs_expr(CGenerator *g, Expression *e) {
+ switch (e->kind) {
+ case EXPR_UNARY_OP:
+ if (!typedefs_expr(g, e->unary.of))
+ return false;
+ break;
+ case EXPR_BINARY_OP:
+ if (!typedefs_expr(g, e->binary.lhs)
+ || !typedefs_expr(g, e->binary.rhs))
+ return false;
+ break;
+ case EXPR_CAST:
+ if (!typedefs_expr(g, e->cast.expr))
+ return false;
+ break;
+ case EXPR_CALL:
+ if (!typedefs_expr(g, e->call.fn))
+ return false;
+ arr_foreach(e->call.arg_exprs, Expression, a)
+ if (!typedefs_expr(g, a))
+ return false;
+ break;
+ case EXPR_BLOCK:
+ if (!typedefs_block(g, &e->block))
+ return false;
+ break;
+ case EXPR_IF:
+ if (e->if_.cond)
+ if (!typedefs_expr(g, e->if_.cond))
+ return false;
+ if (!typedefs_block(g, &e->if_.body))
+ return false;
+ if (e->if_.next_elif)
+ if (!typedefs_expr(g, e->if_.next_elif))
+ return false;
+ break;
+ case EXPR_WHILE:
+ if (e->while_.cond)
+ if (!typedefs_expr(g, e->while_.cond))
+ return false;
+ if (!typedefs_block(g, &e->while_.body))
+ return false;
+ break;
+ case EXPR_TUPLE:
+ arr_foreach(e->tuple, Expression, x)
+ if (!typedefs_expr(g, x))
+ return false;
+ break;
+ case EXPR_SLICE:
+ if (!typedefs_expr(g, e->slice.of)) return false;
+ if (e->slice.from && !typedefs_expr(g, e->slice.from)) return false;
+ if (e->slice.to && !typedefs_expr(g, e->slice.to)) return false;
+ break;
+ case EXPR_FN:
+ fn_enter(&e->fn, 0);
+ if (!typedefs_block(g, &e->fn.body))
+ return false;
+ fn_exit(&e->fn);
+ break;
+ case EXPR_TYPE:
+ 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 typedefs_decl(CGenerator *g, Declaration *d) {
+ d->c.ids = NULL;
+ for (size_t idx = 0; idx < arr_len(d->idents); idx++) {
+ Identifier i = d->idents[idx];
+ Type *type = d->type.kind == TYPE_TUPLE ? &d->type.tuple[idx] : &d->type;
+ Value *val = d->type.kind == TYPE_TUPLE ? &d->val.tuple[idx] : &d->val;
+ if (type->kind == TYPE_TYPE) {
+ /* generate typedef */
+ cgen_write(g, "typedef ");
+ if (!cgen_type_pre(g, val->type, d->where)) return false;
+ cgen_write(g, " ");
+ /* can we use the name directly? */
+ if (!d->c.ids)
+ d->c.ids = evalr_calloc(g->evalr, arr_len(d->idents), sizeof *d->c.ids);
+ if (g->block == NULL) {
+ d->c.ids[idx] = 0; /* yes! */
+ cgen_ident(g, i);
+ } else {
+ cgen_ident_id(g, d->c.ids[idx] = g->ident_counter++); /* no ): */
+ }
+ if (!cgen_type_post(g, val->type, d->where)) return false;
+ cgen_write(g, ";");
+ cgen_nl(g);
+ }
+ }
+ if (d->flags & DECL_FLAG_HAS_EXPR)
+ if (!typedefs_expr(g, &d->expr))
+ return false;
+ return true;
+}
+
+static bool typedefs_stmt(CGenerator *g, Statement *s) {
+ switch (s->kind) {
+ case STMT_DECL:
+ if (!typedefs_decl(g, &s->decl))
+ return false;
+ break;
+ case STMT_EXPR:
+ if (!typedefs_expr(g, &s->expr))
+ return false;
+ break;
+ case STMT_RET:
+ if (s->ret.flags & RET_HAS_EXPR)
+ if (!typedefs_expr(g, &s->ret.expr))
+ return false;
+ break;
+ }
+ return true;
+}
+
+static bool typedefs_file(CGenerator *g, ParsedFile *f) {
+ arr_foreach(f->stmts, Statement, s) {
+ if (!typedefs_stmt(g, s))
+ return false;
+ }
+ return true;
+}