From de3116ca0cac2fc431b9b567f25673468891d2bc Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Tue, 24 Sep 2019 14:39:33 -0400 Subject: started while --- eval.c | 5 +++-- parse.c | 28 +++++++++++++++++++++++++++- test.toc | 6 +++--- types.c | 9 +++++++++ 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/eval.c b/eval.c index c6a659a..9764c1f 100644 --- a/eval.c +++ b/eval.c @@ -136,8 +136,9 @@ static bool eval_expr(Expression *e, Value *v) { case EXPR_FN: v->fn = *e->fn; return true; - case EXPR_IF: { - err_print(e->where, "compile time if not supported yet."); /* TODO */ + case EXPR_IF: + case EXPR_WHILE: { + err_print(e->where, "compile time if/while not supported yet."); /* TODO */ } break; case EXPR_CALL: err_print(e->where, "Compile time function calling not supported yet."); /* TODO */ diff --git a/parse.c b/parse.c index a753bda..63a8637 100644 --- a/parse.c +++ b/parse.c @@ -68,6 +68,7 @@ typedef enum { EXPR_BINARY_OP, EXPR_UNARY_OP, EXPR_IF, + EXPR_WHILE, EXPR_FN, EXPR_CALL, EXPR_BLOCK, @@ -106,6 +107,11 @@ typedef struct { Block body; } IfExpr; +typedef struct { + struct Expression *cond; + Block body; +} WhileExpr; + #define EXPR_FLAG_FOUND_TYPE 0x01 typedef struct Expression { @@ -130,6 +136,7 @@ typedef struct Expression { DirectExpr direct; Identifier ident; IfExpr if_; + WhileExpr while_; struct FnExpr *fn; Block block; }; @@ -799,7 +806,21 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { return true; } case KW_WHILE: { - /* TODO */ + e->kind = EXPR_WHILE; + WhileExpr *w = &e->while_; + t->token++; + Token *cond_end = expr_find_end(p, EXPR_CAN_END_WITH_LBRACE, NULL); + if (!cond_end) return false; + if (!token_is_kw(cond_end, KW_LBRACE)) { + t->token = cond_end; + tokr_err(t, "Expected { to open while body."); + return false; + } + Expression *cond = parser_new_expr(p); + w->cond = cond; + if (!parse_expr(p, cond, cond_end)) + return false; + if (!parse_block(p, &w->body)) return false; return true; } default: break; @@ -1429,6 +1450,11 @@ static void fprint_expr(FILE *out, Expression *e) { if (e->if_.next_elif) fprint_expr(out, e->if_.next_elif); break; + case EXPR_WHILE: + fprintf(out, "while "); + fprint_expr(out, e->while_.cond); + fprint_block(out, &e->while_.body); + break; case EXPR_CALL: fprint_expr(out, e->call.fn); fprint_args(out, &e->call.args); diff --git a/test.toc b/test.toc index 94e8ff7..846008d 100644 --- a/test.toc +++ b/test.toc @@ -1,10 +1,10 @@ main @= fn() { { - i := 0; - asdf := if (fn(i: i64) i64 { i - 1024 })(i) { + i := 1; + asdf := while (fn(i: i64) i64 { i - 1024 })(i) { i = i * 2; i - } else { 0 }; + }; } (fn(){})(); }; diff --git a/types.c b/types.c index 7e9e929..021c3ee 100644 --- a/types.c +++ b/types.c @@ -379,6 +379,15 @@ static bool type_of_expr(Typer *tr, Expression *e) { return false; } } break; + case EXPR_WHILE: { + WhileExpr *w = &e->while_; + if (!types_block(tr, &w->body)) + return false; + if (!type_of_expr()) { + /* TODO: is type_of_expr really necessary? why not just never descend into fns unless it's a decl? */ + } + *t = w->body.ret_expr->type; + } break; case EXPR_CALL: { CallExpr *c = &e->call; Expression *f = c->fn; -- cgit v1.2.3