commit 8c2e89db18d8fcdde24ba540b00edfe6458efebe
parent a46a5164ef7c3c35f811316c843d7004b11ef0d2
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 29 Dec 2020 14:48:43 -0500
check: implement for loops
Diffstat:
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