harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 8c2e89db18d8fcdde24ba540b00edfe6458efebe
parent a46a5164ef7c3c35f811316c843d7004b11ef0d2
Author: Drew DeVault <sir@cmpwn.com>
Date:   Tue, 29 Dec 2020 14:48:43 -0500

check: implement for loops

Diffstat:
Minclude/expr.h | 9+++++++++
Msrc/check.c | 44+++++++++++++++++++++++++++++++++++++++++++-
Msrc/parse.c | 2++
3 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/include/expr.h b/include/expr.h @@ -117,6 +117,14 @@ union expression_constant { // TODO: Struct constants }; +struct expression_for { + struct scope *scope; + struct expression *bindings; + struct expression *cond; + struct expression *afterthought; + struct expression *body; +}; + struct expression_if { struct expression *cond; struct expression *true_branch, *false_branch; @@ -176,6 +184,7 @@ struct expression { struct expression_binding binding; struct expression_call call; union expression_constant constant; + struct expression_for _for; struct expression_if _if; struct expression_list list; struct expression_measure measure; diff --git a/src/check.c b/src/check.c @@ -355,6 +355,46 @@ check_expr_constant(struct context *ctx, } static void +check_expr_for(struct context *ctx, + const struct ast_expression *aexpr, + struct expression *expr) +{ + trenter(TR_CHECK, "if"); + expr->type = EXPR_FOR; + + struct scope *scope = scope_push(&ctx->scope, TR_CHECK); + expr->_for.scope = scope; + + struct expression *bindings = NULL, + *cond = NULL, *afterthought = NULL, *body = NULL; + + if (aexpr->_for.bindings) { + bindings = xcalloc(1, sizeof(struct expression)); + check_expression(ctx, aexpr->_for.bindings, bindings); + expr->_for.bindings = bindings; + } + + cond = xcalloc(1, sizeof(struct expression)); + check_expression(ctx, aexpr->_for.cond, cond); + expr->_for.cond = cond; + expect(cond->result->storage == TYPE_STORAGE_BOOL, + "Expected for condition to be boolean"); + + if (aexpr->_for.afterthought) { + afterthought = xcalloc(1, sizeof(struct expression)); + check_expression(ctx, aexpr->_for.afterthought, afterthought); + expr->_for.afterthought = afterthought; + } + + body = xcalloc(1, sizeof(struct expression)); + check_expression(ctx, aexpr->_for.body, body); + expr->_for.body = body; + + scope_pop(&ctx->scope, TR_CHECK); + trleave(TR_CHECK, NULL); +} + +static void check_expr_if(struct context *ctx, const struct ast_expression *aexpr, struct expression *expr) @@ -560,8 +600,10 @@ check_expression(struct context *ctx, check_expr_constant(ctx, aexpr, expr); break; case EXPR_CONTINUE: - case EXPR_FOR: assert(0); // TODO + case EXPR_FOR: + check_expr_for(ctx, aexpr, expr); + break; case EXPR_IF: check_expr_if(ctx, aexpr, expr); break; diff --git a/src/parse.c b/src/parse.c @@ -1378,6 +1378,8 @@ parse_complex_expression(struct parser *par) return parse_if_expression(par); case T_FOR: return parse_for_expression(par); + case T_LABEL: + assert(0); // TODO: Loop labels case T_MATCH: case T_SWITCH: assert(0); // TODO