harec

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

commit 9e278c41af02695eaa14d34750826e8c389a7d76
parent bbec07c78850bce347f8143398891254cb85acd8
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Tue, 10 Aug 2021 09:59:42 +0000

gen: implement control expressions

Also enable 12-loops

Signed-off-by: Eyal Sawady <ecs@d2evs.net>

Diffstat:
Minclude/gen.h | 3+++
Msrc/gen.c | 50++++++++++++++++++++++++++++++++++++++++----------
Mtests/configure | 2+-
3 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/include/gen.h b/include/gen.h @@ -48,6 +48,9 @@ struct gen_defer { }; struct gen_scope { + const char *label; + struct qbe_value *after; + struct qbe_value *end; struct gen_defer *defers; struct gen_scope *parent; }; diff --git a/src/gen.c b/src/gen.c @@ -28,15 +28,15 @@ static void gen_global_decl(struct gen_context *ctx, const struct declaration *decl); static void -gen_defers(struct gen_context *ctx) +gen_defers(struct gen_context *ctx, struct gen_scope *scope) { - if (!ctx->scope) { + if (!scope) { return; } - if (ctx->scope->defers) { + if (scope->defers) { pushc(ctx->current, "gen defers"); } - for (struct gen_defer *defer = ctx->scope->defers; defer; + for (struct gen_defer *defer = scope->defers; defer; defer = defer->next) { gen_expr(ctx, defer->expr); } @@ -54,7 +54,7 @@ static void pop_scope(struct gen_context *ctx, bool gendefers) { if (gendefers) { - gen_defers(ctx); + gen_defers(ctx, ctx->scope); } struct gen_scope *scope = ctx->scope; ctx->scope = scope->parent; @@ -834,6 +834,30 @@ gen_expr_binding(struct gen_context *ctx, const struct expression *expr) } static struct gen_value +gen_expr_control(struct gen_context *ctx, const struct expression *expr) +{ + struct gen_scope *scope = ctx->scope; + while (scope != NULL) { + gen_defers(ctx, scope); + if (expr->control.label && scope->label) { + if (strcmp(expr->control.label, scope->label) == 0) { + break; + } + } else if (!expr->control.label && scope->after) { + break; + } + scope = scope->parent; + } + assert(scope != NULL); + if (expr->type == EXPR_BREAK) { + pushi(ctx->current, NULL, Q_JMP, scope->end, NULL); + } else { + pushi(ctx->current, NULL, Q_JMP, scope->after, NULL); + } + return gv_void; +} + +static struct gen_value gen_expr_call(struct gen_context *ctx, const struct expression *expr) { struct gen_value lvalue = gen_expr(ctx, expr->call.lvalue); @@ -1428,12 +1452,17 @@ gen_expr_for(struct gen_context *ctx, const struct expression *expr) 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"); + struct qbe_value bafter = mklabel(ctx, &lafter, "after.%d"); if (expr->_for.bindings) { gen_expr_binding(ctx, expr->_for.bindings); } + push_scope(ctx); + ctx->scope->label = expr->_for.label; + ctx->scope->after = &bafter; + ctx->scope->end = &bend; + push(&ctx->current->body, &lloop); struct gen_value cond = gen_expr(ctx, expr->_for.cond); struct qbe_value qcond = mkqval(ctx, &cond); @@ -1447,6 +1476,8 @@ gen_expr_for(struct gen_context *ctx, const struct expression *expr) gen_expr(ctx, expr->_for.afterthought); } + pop_scope(ctx, true); + pushi(ctx->current, NULL, Q_JMP, &bloop, NULL); push(&ctx->current->body, &lend); @@ -1884,7 +1915,7 @@ static struct gen_value gen_expr_return(struct gen_context *ctx, const struct expression *expr) { struct gen_value ret = gen_expr(ctx, expr->_return.value); - gen_defers(ctx); + gen_defers(ctx, ctx->scope); if (type_dealias(ret.type)->storage == STORAGE_VOID) { pushi(ctx->current, NULL, Q_RET, NULL); } else { @@ -2185,15 +2216,14 @@ gen_expr(struct gen_context *ctx, const struct expression *expr) case EXPR_BINDING: return gen_expr_binding(ctx, expr); case EXPR_BREAK: - assert(0); // TODO + case EXPR_CONTINUE: + return gen_expr_control(ctx, expr); case EXPR_CALL: return gen_expr_call(ctx, expr); case EXPR_CAST: return gen_expr_cast(ctx, expr); case EXPR_CONSTANT: return gen_expr_const(ctx, expr); - case EXPR_CONTINUE: - assert(0); // TODO case EXPR_DEFER: return gen_expr_defer(ctx, expr); case EXPR_DELETE: diff --git a/tests/configure b/tests/configure @@ -51,6 +51,7 @@ EOF 09-funcs \ 10-binarithms \ 11-globals \ + 12-loops \ 13-tagged \ 14-switch \ 15-enums \ @@ -63,7 +64,6 @@ EOF 29-unarithm # Disabled tests - #12-loops \ #16-defer \ #18-match \ #19-append \