commit 5e23de9ae7d51d8e456d734fbc1826b9e49fb84c
parent d72310bf87436aec5a9f2008d6ab8d9f7884ce79
Author: Drew DeVault <sir@cmpwn.com>
Date: Thu, 5 Aug 2021 12:32:43 +0200
gen: implement for loops
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
3 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/src/gen.c b/src/gen.c
@@ -662,6 +662,38 @@ gen_expr_const(struct gen_context *ctx, const struct expression *expr)
}
static struct gen_value
+gen_expr_for(struct gen_context *ctx, const struct expression *expr)
+{
+ struct qbe_statement lloop, lbody, lafter, lend;
+ struct qbe_value bloop = mklabel(ctx, &lloop, "loop.%d");
+ struct qbe_value bbody = mklabel(ctx, &lbody, "body.%d");
+ struct qbe_value bend = mklabel(ctx, &lend, ".%d");
+ mklabel(ctx, &lafter, "after.%d");
+
+ if (expr->_for.bindings) {
+ gen_expr_binding(ctx, expr->_for.bindings);
+ }
+
+ push(&ctx->current->body, &lloop);
+ struct gen_value cond = gen_expr(ctx, expr->_for.cond);
+ struct qbe_value qcond = mkqval(ctx, &cond);
+ pushi(ctx->current, NULL, Q_JNZ, &qcond, &bbody, &bend, NULL);
+
+ push(&ctx->current->body, &lbody);
+ gen_expr(ctx, expr->_for.body);
+
+ push(&ctx->current->body, &lafter);
+ if (expr->_for.afterthought) {
+ gen_expr(ctx, expr->_for.afterthought);
+ }
+
+ pushi(ctx->current, NULL, Q_JMP, &bloop, NULL);
+
+ push(&ctx->current->body, &lend);
+ return gv_void;
+}
+
+static struct gen_value
gen_expr_if_with(struct gen_context *ctx,
const struct expression *expr,
struct gen_value *out)
@@ -876,7 +908,9 @@ gen_expr(struct gen_context *ctx, const struct expression *expr)
case EXPR_CONTINUE:
case EXPR_DEFER:
case EXPR_DELETE:
+ assert(0); // TODO
case EXPR_FOR:
+ return gen_expr_for(ctx, expr);
case EXPR_FREE:
assert(0); // TODO
case EXPR_IF:
diff --git a/tests/908-loops.ha b/tests/908-loops.ha
@@ -0,0 +1,26 @@
+fn basics() void = {
+ let x = 0z;
+ for (let i = 0z; i < 10; i += 1) {
+ assert(i == x);
+ x += 1;
+ };
+ assert(x == 10);
+
+ let x = 0z;
+ for (let i = 0z; i < 10) {
+ assert(i == x);
+ x += 1;
+ i += 1;
+ };
+ assert(x == 10);
+
+ let x = 0z;
+ for (x < 10; x += 1) void;
+ assert(x == 10);
+};
+
+export fn main() int = {
+ basics();
+ // TODO: test flow control
+ return 0;
+};
diff --git a/tests/configure b/tests/configure
@@ -11,7 +11,8 @@ tests() {
904-copy \
905-assign \
906-if \
- 907-casts
+ 907-casts \
+ 908-loops
do
cat <<EOF
tests/$t: harec tests/$t.ha tests/rt.o