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:
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