diff options
-rw-r--r-- | arr.c | 2 | ||||
-rw-r--r-- | cgen.c | 89 | ||||
-rw-r--r-- | decls_cgen.c | 11 | ||||
-rw-r--r-- | eval.c | 3 | ||||
-rw-r--r-- | main.c | 19 | ||||
-rw-r--r-- | parse.c | 15 | ||||
-rw-r--r-- | test.toc | 23 | ||||
-rw-r--r-- | toc.c | 3 | ||||
-rw-r--r-- | typedefs_cgen.c | 143 | ||||
-rw-r--r-- | types.c | 30 | ||||
-rw-r--r-- | types.h | 10 |
11 files changed, 270 insertions, 78 deletions
@@ -139,7 +139,7 @@ You shouldn't rely on this, though, e.g. by doing #define arr_last(arr) arr_last_((void *)(arr), sizeof *(arr)) #define arr_foreach(arr, type, var) for (type *var = arr_len(arr) ? arr : NULL, *var##_foreach_end = arr_last(arr); var; var == var##_foreach_end ? var = NULL : var++) #define arr_remove_last(arr) arr_remove_last_((void **)(arr), sizeof **(arr)) - + #ifdef TOC_DEBUG static void arr_test(void) { int *foos = NULL; @@ -13,7 +13,7 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where); static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *ev) { g->outc = out; - g->ident_counter = 0; + g->ident_counter = 1; /* some places use 0 to mean no id */ g->main_ident = ident_get(ids, "main"); g->evalr = ev; g->will_indent = true; @@ -185,9 +185,15 @@ static bool cgen_type_pre(CGenerator *g, Type *t, Location where) { /* We should never try to generate this type */ assert(0); return false; - case TYPE_USER: - cgen_ident(g, t->user.name); - break; + case TYPE_USER: { + Declaration *d = ident_decl(t->user.name)->decl; + assert(d->c.ids); + long i = decl_ident_index(d, t->user.name); + if (d->c.ids[i]) + cgen_ident_id(g, d->c.ids[i]); + else + cgen_ident(g, t->user.name); + } break; } return true; } @@ -200,14 +206,8 @@ static bool cgen_type_post(CGenerator *g, Type *t, Location where) { return false; break; case TYPE_ARR: - if (t->flags & TYPE_FLAG_RESOLVED) - cgen_write(g, "[%lu])", (unsigned long)t->arr.n); - else { - cgen_write(g, "["); - if (!cgen_expr(g, t->arr.n_expr)) - return false; - cgen_write(g, "])"); - } + assert(t->flags & TYPE_FLAG_RESOLVED); + cgen_write(g, "[%lu])", (unsigned long)t->arr.n); if (!cgen_type_post(g, t->arr.of, where)) return false; break; @@ -644,11 +644,36 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) { if (!cgen_block(g, &e->block, ret_name, 0)) return false; break; - case EXPR_CALL: + case EXPR_CALL: { if (!cgen_expr_pre(g, e->call.fn)) return false; arr_foreach(e->call.arg_exprs, Expression, arg) if (!cgen_expr_pre(g, arg)) return false; - break; + 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, " "); + cgen_ident_id(g, e->call.c.id); + if (!cgen_type_post(g, &e->type, e->where)) return false; + cgen_write(g, ";"); cgen_nl(g); + if (!cgen_expr(g, e->call.fn)) return false; + cgen_write(g, "("); + bool any_args = false; + arr_foreach(e->call.arg_exprs, Expression, arg) { + any_args = true; + if (arg != e->call.arg_exprs) + cgen_write(g, ", "); + if (!cgen_expr(g, arg)) + return false; + } + if (any_args) { + cgen_write(g, ", "); + } + cgen_write(g, "&"); + cgen_ident_id(g, e->call.c.id); + cgen_write(g, ");"); + cgen_nl(g); + } + } break; case EXPR_UNARY_OP: if (!cgen_expr_pre(g, e->unary.of)) return false; break; @@ -895,17 +920,21 @@ static bool cgen_expr(CGenerator *g, Expression *e) { cgen_ident_id(g, e->block_ret_id); break; case EXPR_CALL: - cgen_write(g, "("); - if (!cgen_expr(g, e->call.fn)) - return false; - cgen_write(g, "("); - arr_foreach(e->call.arg_exprs, Expression, arg) { - if (arg != e->call.arg_exprs) - cgen_write(g, ", "); - if (!cgen_expr(g, arg)) + if (cgen_uses_ptr(&e->type)) { + cgen_ident_id(g, e->call.c.id); + } else { + cgen_write(g, "("); + if (!cgen_expr(g, e->call.fn)) return false; + cgen_write(g, "("); + arr_foreach(e->call.arg_exprs, Expression, arg) { + if (arg != e->call.arg_exprs) + cgen_write(g, ", "); + if (!cgen_expr(g, arg)) + return false; + } + cgen_write(g, "))"); } - cgen_write(g, "))"); break; case EXPR_DIRECT: switch (e->direct.which) { @@ -1174,13 +1203,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) { Type *type = is_tuple ? &d->type.tuple[idx] : &d->type; Value *val = is_tuple ? &d->val.tuple[idx] : &d->val; if (type->kind == TYPE_TYPE) { - cgen_write(g, "typedef "); - if (!cgen_type_pre(g, val->type, d->where)) return false; - cgen_write(g, " "); - cgen_ident(g, i); - if (!cgen_type_post(g, val->type, d->where)) return false; - cgen_write(g, ";"); - cgen_nl(g); + /* handled in decls_cgen */ continue; } if (!cgen_val_pre(g, val, type, d->where)) @@ -1285,15 +1308,13 @@ static bool cgen_stmt(CGenerator *g, Statement *s) { cgen_nl(g); break; case STMT_RET: - if (!cgen_ret(g, s->ret.flags & RET_FLAG_EXPR ? &s->ret.expr : NULL)) + if (!cgen_ret(g, s->ret.flags & RET_HAS_EXPR ? &s->ret.expr : NULL)) return false; break; } return true; } -static bool cgen_decls_file(CGenerator *g, ParsedFile *f); - static bool cgen_file(CGenerator *g, ParsedFile *f) { g->block = NULL; g->file = f; @@ -1316,6 +1337,8 @@ static bool cgen_file(CGenerator *g, ParsedFile *f) { "static void *e__calloc(size_t n, size_t sz) { void *ret = calloc(n, sz); if (!ret) { fprintf(stderr, \"Out of memory.\\n\"); abort(); } return ret; }\n" "#define false ((bool)0)\n" "#define true ((bool)1)\n\n\n"); + if (!typedefs_file(g, f)) + return false; if (!cgen_decls_file(g, f)) return false; cgen_write(g, "/* code */\n"); diff --git a/decls_cgen.c b/decls_cgen.c index 58383f7..dcf5629 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -115,8 +115,13 @@ static bool cgen_decls_stmt(CGenerator *g, Statement *s) { return false; break; case STMT_EXPR: + if (!cgen_decls_expr(g, &s->expr)) + return false; break; case STMT_RET: + if (s->ret.flags & RET_HAS_EXPR) + if (!cgen_decls_expr(g, &s->ret.expr)) + return false; break; } return true; @@ -125,6 +130,12 @@ static bool cgen_decls_stmt(CGenerator *g, Statement *s) { static bool cgen_decls_file(CGenerator *g, ParsedFile *f) { cgen_write(g, "/* declarations */\n"); arr_foreach(f->stmts, Statement, s) { + /* if only (you need to recurse!) */ + /* OPTIM?? */ + if (s->kind == STMT_DECL) { + } + } + arr_foreach(f->stmts, Statement, s) { if (!cgen_decls_stmt(g, s)) return false; } @@ -20,6 +20,9 @@ static void evalr_free(Evaluator *ev) { static inline void *evalr_malloc(Evaluator *ev, size_t bytes) { return allocr_malloc(&ev->allocr, bytes); } +static inline void *evalr_calloc(Evaluator *ev, size_t n, size_t bytes) { + return allocr_calloc(&ev->allocr, n, bytes); +} static size_t compiler_sizeof_builtin(BuiltinType b) { switch (b) { @@ -1,6 +1,7 @@ /* TODO: -resolve user-defined types +don't cast in C for user types +fix [4]User make sure user defined types work structs length of slice/arr with .len @@ -65,12 +66,12 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } - arr_foreach(t.tokens, Token, token) { - if (token != t.tokens) - printf(" "); - fprint_token(stdout, token); - } - printf("\n"); + /* arr_foreach(t.tokens, Token, token) { */ + /* if (token != t.tokens) */ + /* printf(" "); */ + /* fprint_token(stdout, token); */ + /* } */ + /* printf("\n"); */ Parser p; parser_from_tokenizer(&p, &t); ParsedFile f; @@ -79,9 +80,9 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } tokr_free_tokens(&t); - fprint_parsed_file(stdout, &f); + /* fprint_parsed_file(stdout, &f); */ - printf("\n\n-----\n\n"); + /* printf("\n\n-----\n\n"); */ Typer tr; Evaluator ev; @@ -463,7 +463,6 @@ static bool parse_type(Parser *p, Type *type, U16 flags) { case TOKEN_IDENT: if (!(flags & PARSE_TYPE_EXPR)) { /* user-defined type */ - puts("user-defined type"); type->kind = TYPE_USER; type->user.name = t->token->ident; t->token++; @@ -1454,7 +1453,7 @@ static bool parse_stmt(Parser *p, Statement *s) { t->token++; return true; } - s->ret.flags |= RET_FLAG_EXPR; + s->ret.flags |= RET_HAS_EXPR; Token *end = expr_find_end(p, 0, NULL); if (!end) { while (t->token->kind != TOKEN_EOF) t->token++; /* move to end of file */ @@ -1735,7 +1734,7 @@ static void fprint_stmt(FILE *out, Statement *s) { break; case STMT_RET: fprintf(out, "return "); - if (s->ret.flags & RET_FLAG_EXPR) + if (s->ret.flags & RET_HAS_EXPR) fprint_expr(out, &s->ret.expr); fprintf(out, ";\n"); break; @@ -1747,3 +1746,13 @@ static void fprint_parsed_file(FILE *out, ParsedFile *f) { fprint_stmt(out, stmt); } } + +static long decl_ident_index(Declaration *d, Identifier i) { + long idx = 0; + arr_foreach(d->idents, Identifier, j) { + if (i == *j) + return idx; + idx++; + } + return -1; +} @@ -3,30 +3,17 @@ puti @= fn(x: int) { "); }; -putch @= fn(x: char) { - #C("printf(\"%c\\n\", x); -"); -}; - -putf @= fn(x: float) { - #C("printf(\"%f\\n\", (double)x); -"); -}; - Foo @= [3]int; f @= fn() Foo { a : Foo; - p := &(a as [3]int)[0]; - *p = 1; - *(p + 1) = 2; - *(p + 2) = 3; a }; main @= fn() { - foo := f(); - puti((foo as [3]int)[0]); - puti((foo as [3]int)[1]); - puti((foo as [3]int)[2]); + foo : Foo; + foo = f(); + // Bar @= int; + // x: Bar = 18 as Bar; + // puti(x as int); }; @@ -24,7 +24,10 @@ #include "scope.c" #include "eval.c" #include "types.c" +static bool cgen_decls_file(CGenerator *g, ParsedFile *f); +static bool typedefs_file(CGenerator *g, ParsedFile *f); #include "cgen.c" +#include "typedefs_cgen.c" #include "decls_cgen.c" #ifdef TOC_DEBUG 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; +} @@ -1147,24 +1147,30 @@ static bool types_decl(Typer *tr, Declaration *d) { } if ((d->flags & DECL_FLAG_CONST) || tr->block == NULL) { if (!(d->flags & DECL_FLAG_FOUND_VAL)) { - if (!eval_expr(tr->evalr, &d->expr, &d->val)) - return false; + if (!eval_expr(tr->evalr, &d->expr, &d->val)) { + success = false; + goto ret; + } d->flags |= DECL_FLAG_FOUND_VAL; } } - if (d->type.kind == TYPE_TUPLE) { - arr_foreach(d->type.tuple, Type, t) { - if (t->kind == TYPE_TYPE && !(d->flags & DECL_FLAG_CONST)) { + for (size_t i = 0; i < arr_len(d->idents); i++) { + Type *t = d->type.kind == TYPE_TUPLE ? &d->type.tuple[i] : &d->type; + Value *val = d->type.kind == TYPE_TUPLE ? &d->val.tuple[i] : &d->val; + if (t->kind == TYPE_TYPE) { + if (!(d->flags & DECL_FLAG_CONST)) { err_print(d->where, "Cannot declare non-constant type."); - return false; + success = false; + goto ret; + } + if (!type_resolve(tr, val->type)) { + success = false; + goto ret; } - } - } else { - if (d->type.kind == TYPE_TYPE && !(d->flags & DECL_FLAG_CONST)) { - err_print(d->where, "Cannot declare non-constant type."); - return false; } } + + } size_t n_idents = arr_len(d->idents); if (d->type.kind == TYPE_TUPLE) { @@ -1206,7 +1212,7 @@ static bool types_stmt(Typer *tr, Statement *s) { err_print(s->where, "return outside of a function."); return false; } - if (s->ret.flags & RET_FLAG_EXPR) { + if (s->ret.flags & RET_HAS_EXPR) { if (tr->ret_type.kind == TYPE_VOID) { err_print(s->where, "Return value in function which should not return a value."); return false; @@ -113,7 +113,6 @@ root.children[low part of 1st char].children[high part of 1st char] typedef struct IdentTree { /* zero value is an empty trie */ uint16_t depth; - uint16_t flags; unsigned char index_in_parent; /* index of this in .parent.children */ struct IdentTree *parent; struct IdentTree *children[TREE_NCHILDREN]; @@ -364,6 +363,9 @@ typedef struct { struct Argument *args; struct Expression *arg_exprs; }; + struct { + IdentID id; + } c; } CallExpr; typedef struct { @@ -480,6 +482,10 @@ typedef struct Declaration { uint16_t flags; Expression expr; Value val; /* only for constant decls. */ + + struct { + IdentID *ids; /* array of IDs used in place of ident names. unfortunately needed for user defined types. this is NOT a dynamic array, but is of length arr_len(idents). */ + } c; } Declaration; typedef enum { @@ -488,7 +494,7 @@ typedef enum { STMT_RET } StatementKind; -#define RET_FLAG_EXPR 0x01 +#define RET_HAS_EXPR 0x01 typedef struct { uint16_t flags; Expression expr; |