harec

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

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:
Msrc/gen.c | 34++++++++++++++++++++++++++++++++++
Atests/908-loops.ha | 26++++++++++++++++++++++++++
Mtests/configure | 3++-
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