diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-09-24 14:28:23 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-09-24 14:28:23 -0400 |
commit | b6b75a1e166c6ce5f18a2854e1c594b6bebd7049 (patch) | |
tree | 44e1f00d709d05ca24944d4b6b0303ea8363cd40 | |
parent | f68d40f063608c15d5cf7db2dd506f6676bbd440 (diff) |
bug fixes; no non-void if without else
-rw-r--r-- | parse.c | 1 | ||||
-rw-r--r-- | test.toc | 18 | ||||
-rw-r--r-- | types.c | 49 |
3 files changed, 49 insertions, 19 deletions
@@ -1007,6 +1007,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { if (token_is_kw(t->token, KW_LBRACE)) { /* it's a block */ + e->kind = EXPR_BLOCK; if (!parse_block(p, &e->block)) return false; if (t->token != end) { tokr_err(t, "Expression continues after end of block."); /* TODO: improve this err message */ @@ -1,13 +1,11 @@ main @= fn() { - //x := 1; - /*foo := if x { - 9 - } elif 7-3 { - 5 - } elif main { - 3 - } else {7 };*/ - - bar := if 1 { 9 }; + { + i := 0; + asdf := if (fn(i: i64) i64 { i - 1024 })(i) { + i = i * 2; + i + } else { 0 }; + } + (fn(){})(); }; @@ -374,8 +374,8 @@ static bool type_of_expr(Typer *tr, Expression *e) { } } - if (!has_else && t->kind == TYPE_VOID) { - err_print(e->where, "non-void if block with no else"); + if (!has_else && t->kind != TYPE_VOID) { + err_print(e->where, "Non-void if block with no else."); return false; } } break; @@ -583,26 +583,46 @@ static bool type_of_expr(Typer *tr, Expression *e) { } static bool types_block(Typer *tr, Block *b) { - bool ret = true; + bool success = true; Block *prev_block = tr->block; tr->block = b; if (!block_enter(b, &b->stmts)) return false; arr_foreach(&b->stmts, Statement, s) { - if (!types_stmt(tr, s)) ret = false; + if (!types_stmt(tr, s)) success = false; } - if (b->ret_expr) + if (!success) return false; + if (b->ret_expr) { if (!types_expr(tr, b->ret_expr)) - ret = false; + return false; + if (b->ret_expr->type.kind == TYPE_VOID) { + err_print(b->ret_expr->where, "Cannot return void value."); + return false; + } + } + block_exit(b, &b->stmts); tr->block = prev_block; - return ret; + return true; } -/* does descend into blocks, unlike type_of_expr. */ +/* does descend into functions, unlike type_of_expr. */ /* TODO: you still need to descend into other things */ static bool types_expr(Typer *tr, Expression *e) { if (!type_of_expr(tr, e)) return false; switch (e->kind) { + case EXPR_UNARY_OP: + if (!types_expr(tr, e->unary.of)) return false; + break; + case EXPR_BINARY_OP: + if (!types_expr(tr, e->binary.lhs)) return false; + if (!types_expr(tr, e->binary.rhs)) return false; + break; + case EXPR_CALL: + if (!types_expr(tr, e->call.fn)) return false; + arr_foreach(&e->call.args, Expression, arg) { + if (!types_expr(tr, arg)) return false; + } + break; case EXPR_FN: { assert(e->type.kind == TYPE_FN); FnExpr *f = e->fn; @@ -631,7 +651,18 @@ static bool types_expr(Typer *tr, Expression *e) { return false; } } break; - default: break; + case EXPR_IF: { + IfExpr *i = &e->if_; + if (i->cond && !types_expr(tr, i->cond)) return false; + + } break; + case EXPR_DIRECT: + case EXPR_BLOCK: + case EXPR_IDENT: + case EXPR_LITERAL_INT: + case EXPR_LITERAL_FLOAT: + case EXPR_LITERAL_STR: + break; } return true; } |