diff options
-rw-r--r-- | cgen.c | 140 | ||||
-rw-r--r-- | out.c | 42 | ||||
-rw-r--r-- | parse.c | 20 | ||||
-rw-r--r-- | test.toc | 21 |
4 files changed, 132 insertions, 91 deletions
@@ -2,7 +2,7 @@ static bool cgen_stmt(CGenerator *g, Statement *s); static bool cgen_block(CGenerator *g, Block *b, const char *ret_name); static bool cgen_expr_pre(CGenerator *g, Expression *e); static bool cgen_expr(CGenerator *g, Expression *e); -static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, Expression *to); +static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, const char *prefix, Expression *to); static bool cgen_type_pre(CGenerator *g, Type *t, Location where); static bool cgen_type_post(CGenerator *g, Type *t, Location where); static bool cgen_decl(CGenerator *g, Declaration *d); @@ -352,7 +352,7 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E assert(set_expr); assert(to_expr); assert(set_expr->kind == EXPR_TUPLE); - if (!cgen_set_tuple(g, set_expr->tuple, NULL, to_expr)) + if (!cgen_set_tuple(g, set_expr->tuple, NULL, NULL, to_expr)) return false; break; case TYPE_VOID: @@ -362,21 +362,64 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E return true; } +static bool cgen_if_pre(CGenerator *g, Expression *e) { + char ret_name[64]; + IfExpr *curr = &e->if_; + curr->c.id = g->ident_counter++; + cgen_ident_id_to_str(ret_name, curr->c.id); + char *p = ret_name + strlen(ret_name); + if (e->type.kind != TYPE_VOID) { + if (e->type.kind == TYPE_TUPLE) { + for (unsigned long i = 0; i < arr_len(e->type.tuple); i++) { + sprintf(p, "%lu_", i); + if (!cgen_type_pre(g, &e->type.tuple[i], e->where)) return false; + cgen_write(g, " %s", ret_name); + if (!cgen_type_post(g, &e->type.tuple[i], e->where)) return false; + cgen_write(g, "; "); + } + + } else { + cgen_type_pre(g, &e->type, e->where); + cgen_write(g, " %s", ret_name); + cgen_type_post(g, &e->type, e->where); + cgen_write(g, ";"); + cgen_nl(g); + } + } + *p = 0; /* clear tuple suffixes */ + + while (1) { + if (curr->cond) { + cgen_write(g, "if ("); + if (!cgen_expr(g, curr->cond)) + return false; + cgen_write(g, ") "); + } + if (!cgen_block(g, &curr->body, ret_name)) + return false; + if (curr->next_elif) { + cgen_write(g, " else "); + curr = &curr->next_elif->if_; + } else break; + } + return true; +} -/* exprs and/or idents should be NULL. if both are NULL, *retN_ will be used. */ -static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, Expression *to) { +/* one of exprs, idents, and prefix should be NULL. */ +static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, const char *prefix, Expression *to) { + IdentID prefix_id; /* ID of prefix for block */ switch (to->kind) { case EXPR_TUPLE: /* e.g. a, b = 3, 5; */ for (size_t i = 0; i < arr_len(to->tuple); i++) { - char *s = NULL, buf[32]; + char *s = NULL, buf[64]; Expression *e = NULL; if (idents) s = cgen_ident_to_str(idents[i]); else if (exprs) e = &exprs[i]; else { - snprintf(buf, sizeof buf, "(*ret%lu_)", i); + snprintf(buf, sizeof buf, "(%s%lu_)", prefix, i); s = buf; } if (!cgen_set(g, e, s, &to->tuple[i], NULL)) return false; @@ -397,7 +440,7 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, /* out params */ size_t len = exprs ? arr_len(exprs) : arr_len(idents); - for (size_t i = 0; i < len; i++) { + for (unsigned long i = 0; i < (unsigned long)len; i++) { if (any_args || i > 0) cgen_write(g, ", "); if (exprs) { @@ -408,12 +451,43 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, cgen_write(g, "&"); cgen_ident(g, idents[i]); } else { - cgen_write(g, "ret%lu_", i); + cgen_write(g, "&(%s%lu_)", prefix, i); } } cgen_writeln(g, ");"); } break; - default: + case EXPR_IF: + prefix_id = to->if_.c.id; + goto prefixed; + prefixed: + for (unsigned long i = 0; i < (unsigned long)arr_len(to->type.tuple); i++) { + cgen_write(g, "("); + if (exprs) { + if (!cgen_expr(g, &exprs[i])) + return false; + } else if (idents) { + cgen_ident(g, idents[i]); + } else { + cgen_write(g, "%s%lu_", prefix, i); + } + cgen_write(g, ") = "); + cgen_ident_id(g, prefix_id); + cgen_write(g, "%lu_", i); + cgen_write(g, "; "); + } + break; + case EXPR_IDENT: + case EXPR_LITERAL_INT: + case EXPR_LITERAL_CHAR: + case EXPR_LITERAL_BOOL: + case EXPR_LITERAL_STR: + case EXPR_LITERAL_FLOAT: + case EXPR_UNARY_OP: + case EXPR_BINARY_OP: + case EXPR_FN: + case EXPR_CAST: + case EXPR_NEW: + case EXPR_DIRECT: assert(0); return false; } @@ -422,34 +496,9 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, static bool cgen_expr_pre(CGenerator *g, Expression *e) { switch (e->kind) { - case EXPR_IF: { - char ret_name[32]; - IfExpr *curr = &e->if_; - curr->c.id = g->ident_counter++; - cgen_ident_id_to_str(ret_name, curr->c.id); - if (e->type.kind != TYPE_VOID) { - cgen_type_pre(g, &e->type, e->where); - cgen_write(g, " %s", ret_name); - cgen_type_post(g, &e->type, e->where); - cgen_write(g, ";"); - cgen_nl(g); - } - - while (1) { - if (curr->cond) { - cgen_write(g, "if ("); - if (!cgen_expr(g, curr->cond)) - return false; - cgen_write(g, ") "); - } - if (!cgen_block(g, &curr->body, ret_name)) - return false; - if (curr->next_elif) { - cgen_write(g, " else "); - curr = &curr->next_elif->if_; - } else break; - } - } break; + case EXPR_IF: + cgen_if_pre(g, e); + break; case EXPR_WHILE: break; case EXPR_BLOCK: @@ -482,8 +531,8 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) { case EXPR_DIRECT: break; case EXPR_TUPLE: - assert(0); - return false; + arr_foreach(e->tuple, Expression, x) + if (!cgen_expr_pre(g, x)) return false; } return true; } @@ -658,8 +707,13 @@ static bool cgen_block(CGenerator *g, Block *b, const char *ret_name) { return false; if (b->ret_expr && ret_name) { - if (!cgen_set(g, NULL, ret_name, b->ret_expr, NULL)) - return false; + if (b->ret_expr->type.kind == TYPE_TUPLE) { + if (!cgen_set_tuple(g, NULL, NULL, ret_name, b->ret_expr)) + return false; + } else { + if (!cgen_set(g, NULL, ret_name, b->ret_expr, NULL)) + return false; + } cgen_nl(g); } cgen_block_exit(g, prev); @@ -755,7 +809,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) { /* TODO: global tuples */ if (g->block != NULL && (d->flags & DECL_FLAG_HAS_EXPR)) { if (d->expr.type.kind == TYPE_TUPLE) { - if (!cgen_set_tuple(g, NULL, d->idents, &d->expr)) return false; + if (!cgen_set_tuple(g, NULL, d->idents, NULL, &d->expr)) return false; } else { cgen_write(g, "{"); @@ -789,7 +843,7 @@ static bool cgen_ret(CGenerator *g, Expression *ret) { cgen_write(g, "return"); } else if (cgen_uses_ptr(&g->fn->ret_type)) { if (g->fn->ret_type.kind == TYPE_TUPLE) { - if (!cgen_set_tuple(g, NULL, NULL, ret)) + if (!cgen_set_tuple(g, NULL, NULL, "*ret", ret)) return false; } else { if (!cgen_set(g, NULL, "*ret_", ret, NULL)) return false; @@ -17,8 +17,6 @@ typedef unsigned char bool; /* declarations */ void puti(i64 x); -void mktup(i64 a, i64 b, i64(*ret0_), i64(*ret1_)); -i64 asdf(void); void main__(void); /* code */ int main() { @@ -26,44 +24,20 @@ int main() { return 0; } +#include <stdio.h> +; void puti(i64 x) { { printf("%ld\n", (long)x); }} -void mktup(i64 a, i64 b, i64(*ret0_), i64(*ret1_)) { - { -}(*ret0_) = a;(*ret1_) = (a+b);return; -} - - -i64 asdf(void) { - { -}return 32187318; -} - - void main__(void) { { - i64 a; i64 b; mktup(10, 20, &a, &b); - - (puti(((i64)(((u8)((asdf()))))))); - (puti(a)); - (puti(b)); - i64 a0_; - if (5) { - a0_ = 6; - } else { - a0_ = 7; - }i64 x; { - i64 expr__; i64 a1_; - if (5) { - a1_ = 6; + i64 a0_0_; i64 a0_1_; if (0) { + (a0_0_) = 3;(a0_1_) = 5; } else { - a1_ = 7; - }expr__ = (5+(-a1_));x = expr__;} - (puti(x)); -}} - - + (a0_0_) = 4;(a0_1_) = 6; + }i64 A; i64 B; (A) = a0_0_; (B) = a0_1_; + (puti(A)); + (puti(B)); @@ -340,6 +340,10 @@ static bool parse_type(Parser *p, Type *type) { while (1) { Type *param_type = parser_arr_add(p, &type->fn.types); if (!parse_type(p, param_type)) return false; + if (param_type->kind == TYPE_TUPLE) { + err_print(param_type->where, "Functions cannot have tuples as parameters."); + return false; + } if (token_is_kw(t->token, KW_RPAREN)) break; if (!token_is_kw(t->token, KW_COMMA)) { @@ -377,6 +381,10 @@ static bool parse_type(Parser *p, Type *type) { t->token = end + 1; /* go past ] */ type->arr.of = parser_malloc(p, sizeof *type->arr.of); if (!parse_type(p, type->arr.of)) return false; + if (type->arr.of->kind == TYPE_TUPLE) { + err_print(type->arr.of->where, "You cannot have an array of tuples."); + return false; + } type->flags = 0; type->where = start->where; break; @@ -389,6 +397,10 @@ static bool parse_type(Parser *p, Type *type) { while (1) { Type *child = parser_arr_add(p, &type->tuple); if (!parse_type(p, child)) return false; + if (child->kind == TYPE_TUPLE) { + err_print(child->where, "Tuples cannot contain tuples."); + return false; + } if (token_is_kw(t->token, KW_RPAREN)) { /* we're done with the tuple */ t->token++; /* move past ) */ break; @@ -408,6 +420,10 @@ static bool parse_type(Parser *p, Type *type) { type->ptr.of = parser_malloc(p, sizeof *type->ptr.of); t->token++; /* move past & */ if (!parse_type(p, type->ptr.of)) return false; + if (type->ptr.of->kind == TYPE_TUPLE) { + err_print(type->ptr.of->where, "You cannot have a pointer to a tuple."); + return false; + } break; default: tokr_err(t, "Unrecognized type."); @@ -923,6 +939,10 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { t->token++; e->kind = EXPR_NEW; if (!parse_type(p, &e->new.type)) return false; + if (e->new.type.kind == TYPE_TUPLE) { + err_print(e->where, "You cannot new a tuple."); + return false; + } return true; case KW_DEL: op = UNARY_DEL; @@ -1,20 +1,13 @@ +#C("#include <stdio.h>\n"); + puti @= fn(x: int) { #C("printf(\"%ld\\n\", (long)x)"); }; -mktup @= fn(a: int, b: int) (int, int) { - a, a+b -}; - -asdf @= fn() int { - 32187318 -}; - main @= fn() { - a, b := mktup(10, 20); - // x := mktup; - puti(asdf() as u8 as i64); - puti(a); puti(b); - x := 5+-if 5 { 6 } else { 7 }; - puti(x); + A, B := if 0 { 3, 5 } else { 4, 6 }; + // A, B := 3, 5; + puti(A); + puti(B); + asdfas := new (int, int); };
\ No newline at end of file |