From a2f5cd5069df70436228c8f6cb6ed82edcdcaae8 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Wed, 9 Oct 2019 11:16:07 -0400 Subject: started cgen --- base_cgen.c | 295 ------------------------------------------------------------ 1 file changed, 295 deletions(-) delete mode 100644 base_cgen.c (limited to 'base_cgen.c') diff --git a/base_cgen.c b/base_cgen.c deleted file mode 100644 index d773ba9..0000000 --- a/base_cgen.c +++ /dev/null @@ -1,295 +0,0 @@ -/* figures out types and writes function prototypes */ -/* TODO: check ferror */ -typedef enum { - CGEN_WRITING_TO_H, - CGEN_WRITING_TO_C -} CGenWritingTo; -typedef struct { - FILE *c_out; - FILE *h_out; - unsigned long anon_fn_count; - unsigned long anon_var_count; - Block *block; - int indent_level; - bool indent_next; /* should the next thing written be indented? */ - CGenWritingTo writing_to; - Identifier main_ident; -} CGenerator; - -static FILE *cgen_writing_to(CGenerator *g) { - switch (g->writing_to) { - case CGEN_WRITING_TO_H: - return g->h_out; - case CGEN_WRITING_TO_C: - return g->c_out; - } - assert(0); - return NULL; -} - -static void cgen_indent(CGenerator *g) { - if (g->indent_next) { - for (int i = 0; i < g->indent_level; i++) - fprintf(cgen_writing_to(g), "\t"); - g->indent_next = false; - } -} - -static void cgen_vwrite(CGenerator *g, const char *fmt, va_list args) { - cgen_indent(g); - vfprintf(cgen_writing_to(g), fmt, args); -} - -static void cgen_write(CGenerator *g, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - cgen_vwrite(g, fmt, args); - va_end(args); -} - -/* Used to write an UNNECESSARY space */ -static void cgen_space(CGenerator *g) { - cgen_write(g, " "); -} - -/* Used to write something followed by an UNNECESSARY newline */ -static void cgen_writeln(CGenerator *g, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - cgen_vwrite(g, fmt, args); - va_end(args); - cgen_write(g, "\n"); - g->indent_next = true; -} - -/* static void cgen_write_comment(CGenerator *g, const char *fmt, ...) { */ -/* cgen_write(g, "/\* "); */ -/* va_list args; */ -/* va_start(args, fmt); */ -/* cgen_vwrite(g, fmt, args); */ -/* va_end(args); */ -/* cgen_write(g, " *\/"); */ -/* } */ - -static void cgen_write_line_comment(CGenerator *g, const char *fmt, ...) { - /* could switch to // for c99 */ - cgen_write(g, "/* "); - va_list args; - va_start(args, fmt); - cgen_vwrite(g, fmt, args); - va_end(args); - cgen_write(g, " */\n"); -} - - -/* Pass NULL for where if you don't want to check if it's declared */ -static bool cgen_fn_name(CGenerator *g, FnExpr *f, Location *where); -static bool cgen_ident(CGenerator *g, Identifier i, Location *where) { - if (where) { - IdentDecl *id_decl = ident_decl(i); - if (!id_decl) { - err_print(*where, "Identifier undeclared: %s", ident_to_str(i)); - return false; - } - Declaration *decl = id_decl->decl; - if ((decl->flags & DECL_FLAG_HAS_EXPR) && (decl->flags & DECL_FLAG_CONST)) { - if (decl->expr.kind == EXPR_FN) { - cgen_fn_name(g, decl->expr.fn, NULL); - return true; - } - } - } - cgen_indent(g); - fprint_ident_reduced_charset(cgen_writing_to(g), i); - return true; -} - -static const char *builtin_type_to_str(BuiltinType b) { - /* TODO: make this return int/long/etc. if stdint.h is not available */ - switch (b) { - case BUILTIN_I8: return "int8_t"; - case BUILTIN_I16: return "int16_t"; - case BUILTIN_I32: return "int32_t"; - case BUILTIN_I64: return "int64_t"; - case BUILTIN_U8: return "uint8_t"; - case BUILTIN_U16: return "uint16_t"; - case BUILTIN_U32: return "uint32_t"; - case BUILTIN_U64: return "uint64_t"; - case BUILTIN_FLOAT: return "float"; - case BUILTIN_DOUBLE: return "double"; - case BUILTIN_TYPE_COUNT: break; - } - assert(0); - return NULL; -} - -/* will this function use a pointer parameter for output? (e.g. fn()[3]int => void(int (*x)[3]) */ -static bool cgen_fn_uses_out_param(Type *fn_ret_type) { - switch (fn_ret_type->kind) { - case TYPE_TUPLE: - case TYPE_ARR: - return true; - default: - return false; - } -} - - -static void cgen_anon_var(CGenerator *g, unsigned long v) { - cgen_write(g, "av___%lu", v); -} - -static void cgen_anon_fn(CGenerator *g, unsigned long f) { - cgen_write(g, "af___%lu", f); -} - -static void cgen_type_pre(CGenerator *g, Type *t) { - switch (t->kind) { - case TYPE_VOID: - cgen_write(g, "void "); - break; - case TYPE_BUILTIN: - cgen_write(g, "%s ", builtin_type_to_str(t->builtin)); - break; - case TYPE_FN: { - Type *types = t->fn.types.data; - Type *ret_type = &types[0]; - if (cgen_fn_uses_out_param(ret_type)) { - cgen_write(g, "void "); - } else { - cgen_type_pre(g, ret_type); - } - cgen_write(g, "(*"); - } break; - case TYPE_TUPLE: - assert(0); - return; - case TYPE_UNKNOWN: - err_print(t->where, "Type of unknown-typed expression required (x := #C(\"...\") will not work; you need to annotate the type of x)."); - abort(); - case TYPE_ARR: - cgen_type_pre(g, t->arr.of); - break; - } -} - -static void cgen_type_post(CGenerator *g, Type *t); -/* either pass NULL for param_types (x)or for params */ -static void cgen_fn_params(CGenerator *g, Type *param_types, Param *params, size_t nparams, Type *ret_type) { - bool uses_out_param = cgen_fn_uses_out_param(ret_type); - - cgen_write(g, "("); - if (nparams) { - for (size_t i = 0; i < nparams; i++) { - if (i) { - cgen_write(g, ","); - cgen_space(g); - } - if (param_types) { - cgen_type_pre(g, ¶m_types[i]); - cgen_type_post(g, ¶m_types[i]); - } else { - Param *p = ¶ms[i]; - cgen_type_pre(g, &p->type); - cgen_ident(g, p->name, NULL); - cgen_type_post(g, &p->type); - } - } - } else { - if (!uses_out_param) - cgen_write(g, "void"); - } - if (uses_out_param) { - if (nparams) { - cgen_write(g, ","); - cgen_space(g); - } - /* write out param */ - cgen_type_pre(g, ret_type); - cgen_write(g, "(*out__)"); /* TODO: fix this for named return values */ - cgen_type_post(g, ret_type); - - } - cgen_write(g, ")"); -} - -static void cgen_type_post(CGenerator *g, Type *t) { - switch (t->kind) { - case TYPE_VOID: - case TYPE_BUILTIN: - break; - case TYPE_FN: { - Type *types = t->fn.types.data; - Type *ret_type = &types[0]; - Type *param_types = types + 1; - assert(t->fn.types.len > 0); - size_t nparams = t->fn.types.len-1; - bool uses_out_param = cgen_fn_uses_out_param(ret_type); - cgen_write(g, ")"); - cgen_fn_params(g, param_types, NULL, nparams, ret_type); - if (!uses_out_param) { - cgen_type_post(g, ret_type); - } - cgen_space(g); - } break; - case TYPE_TUPLE: - assert(0); - return; - case TYPE_ARR: - cgen_write(g, "[%lu]", t->arr.n); - cgen_type_post(g, t->arr.of); - break; - case TYPE_UNKNOWN: /* we should always do pre first */ - assert(0); - break; - } -} - -static bool cgen_fn_name(CGenerator *g, FnExpr *f, Location *where) { - if (f->name) { - /* TODO: check block */ - if (f->name == g->main_ident) { - cgen_write(g, "main__"); - return true; - } else { - return cgen_ident(g, f->name, where); - } - } else { - cgen_anon_fn(g, f->id); - return true; - } -} - -static bool cgen_fn_header(CGenerator *g, FnExpr *f) { - if (!f->name || g->block != NULL) { - cgen_write(g, "static "); /* anonymous functions only exist in this translation unit */ - } - - bool uses_out_param = cgen_fn_uses_out_param(&f->ret_type); - size_t nparams = f->params.len; - if (uses_out_param) { - cgen_write(g, "void "); - cgen_fn_name(g, f, NULL); - cgen_fn_params(g, NULL, (Param*)f->params.data, nparams, &f->ret_type); - - } else { - cgen_type_pre(g, &f->ret_type); - cgen_fn_name(g, f, NULL); - cgen_fn_params(g, NULL, (Param*)f->params.data, nparams, &f->ret_type); - cgen_type_post(g, &f->ret_type); - } - - return true; -} - -static bool cgen_block_enter(CGenerator *g, Block *b) { - g->block = b; - return block_enter(b, &b->stmts); -} - -static bool cgen_block_exit(CGenerator *g, Block *into) { - Block *b = g->block; - g->block = into; - return block_exit(b, &b->stmts); -} - -- cgit v1.2.3