harec

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

commit 7737b24cefefc24e262e386e821dbacdbb7daa2b
parent ab56f0bc304805b8c7d4841e0e147e84bf04766e
Author: Drew DeVault <sir@cmpwn.com>
Date:   Tue, 31 Aug 2021 14:40:44 +0200

gen: basic yield implementation

This still needs some more refinement.

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Minclude/gen.h | 2++
Msrc/check.c | 1+
Msrc/gen.c | 42++++++++++++++++++++++++++++++------------
3 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/include/gen.h b/include/gen.h @@ -52,6 +52,8 @@ struct gen_defer { struct gen_scope { const char *label; const struct scope *scope; + struct gen_value result; + struct gen_value *out; struct qbe_value *after; struct qbe_value *end; struct gen_defer *defers; diff --git a/src/check.c b/src/check.c @@ -1307,6 +1307,7 @@ check_expr_compound(struct context *ctx, expr->terminates = lexpr->terminates; expr->result = type_store_reduce_result(ctx->store, scope->results); + // TODO: Cast all yields to this type assert(expr->result); scope_pop(&ctx->scope); } diff --git a/src/gen.c b/src/gen.c @@ -54,13 +54,14 @@ gen_scope_lookup(struct gen_context *ctx, const struct scope *which) abort(); } -static void +static struct gen_scope * push_scope(struct gen_context *ctx, const struct scope *scope) { struct gen_scope *new = xcalloc(1, sizeof(struct gen_scope)); new->parent = ctx->scope; new->scope = scope; ctx->scope = new; + return new; } static void @@ -896,7 +897,14 @@ gen_expr_control(struct gen_context *ctx, const struct expression *expr) break; case EXPR_YIELD: assert(scope->scope->class == SCOPE_COMPOUND); - assert(0); // TODO + if (expr->control.value) { + struct gen_value result = gen_expr_with(ctx, + expr->control.value, scope->out); + branch_copyresult(ctx, result, + scope->result, scope->out); + } + pushi(ctx->current, NULL, Q_JMP, scope->end, NULL); + break; default: abort(); // Invariant } return gv_void; @@ -1338,18 +1346,28 @@ gen_expr_compound_with(struct gen_context *ctx, const struct expression *expr, struct gen_value *out) { - push_scope(ctx, expr->compound.scope); - for (const struct expressions *exprs = &expr->compound.exprs; - exprs; exprs = exprs->next) { - if (!exprs->next) { - struct gen_value gv = gen_expr_with( - ctx, exprs->expr, out); - pop_scope(ctx, !exprs->expr->terminates); - return gv; - } + struct qbe_statement lend; + struct qbe_value bend = mklabel(ctx, &lend, ".%d"); + struct gen_scope *scope = push_scope(ctx, expr->compound.scope); + scope->end = &bend; + + struct gen_value gvout = gv_void; + if (!out) { + gvout = mktemp(ctx, expr->result, ".%d"); + } + scope->out = out; + scope->result = gvout; + + const struct expressions *exprs; + for (exprs = &expr->compound.exprs; exprs->next; exprs = exprs->next) { gen_expr(ctx, exprs->expr); } - abort(); // Unreachable + + struct gen_value last = gen_expr_with(ctx, exprs->expr, out); + branch_copyresult(ctx, last, gvout, out); + pop_scope(ctx, !exprs->expr->terminates); + push(&ctx->current->body, &lend); + return gvout; } static void