harec

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

commit d0dec8368368702e7ebe8528e7ad0f34711e9297
parent b92418e0104e0f5fc67f44f79fda92863f2209a2
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 20 Jan 2021 13:17:06 -0500

gen: generalize loop contexts -> scope contexts

Diffstat:
Minclude/gen.h | 13++++++++++---
Msrc/gen.c | 52++++++++++++++++++++++++++++++++++++----------------
2 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/include/gen.h b/include/gen.h @@ -22,11 +22,18 @@ struct gen_binding { struct gen_binding *next; }; -struct gen_loop_context { +enum scope_class { + SCOPE_LOOP, // used with continue, break + SCOPE_FUNC, // used with return + SCOPE_OTHER, // expression lists, etc +}; + +struct gen_scope_context { const char *label; + enum scope_class class; struct qbe_value *after; struct qbe_value *end; - struct gen_loop_context *parent; + struct gen_scope_context *parent; }; struct gen_context { @@ -36,7 +43,7 @@ struct gen_context { const struct qbe_value *end_label; const struct qbe_value *return_value; struct gen_binding *bindings; - struct gen_loop_context *loop; + struct gen_scope_context *scope; uint64_t id; }; diff --git a/src/gen.c b/src/gen.c @@ -31,6 +31,29 @@ ident_to_sym(const struct identifier *ident) return strdup(ident->name); } +static struct gen_scope_context * +push_scope(struct gen_context *ctx, + enum scope_class class, + struct qbe_value *end) +{ + struct gen_scope_context *scope = + xcalloc(1, sizeof(struct gen_scope_context)); + scope->class = class; + scope->end = end; + scope->parent = ctx->scope; + ctx->scope = scope; + return scope; +} + +static void +pop_scope(struct gen_context *ctx) +{ + struct gen_scope_context *scope = ctx->scope; + assert(scope); + ctx->scope = ctx->scope->parent; + free(scope); +} + static char * gen_name(struct gen_context *ctx, const char *fmt) { @@ -1134,18 +1157,20 @@ gen_expr_control(struct gen_context *ctx, const struct qbe_value *out) { assert(out == NULL); // Invariant - struct gen_loop_context *loop = ctx->loop; - while (expr->control.label != NULL && loop != NULL) { - if (loop->label && strcmp(expr->control.label, loop->label) == 0) { + struct gen_scope_context *scope = ctx->scope; + while (expr->control.label != NULL && scope != NULL) { + if (scope->label + && strcmp(expr->control.label, scope->label) == 0 + && scope->class == SCOPE_LOOP) { break; } - loop = loop->parent; + scope = scope->parent; } - assert(loop != NULL); + assert(scope != NULL); if (expr->type == EXPR_BREAK) { - pushi(ctx->current, NULL, Q_JMP, loop->end, NULL); + pushi(ctx->current, NULL, Q_JMP, scope->end, NULL); } else { - pushi(ctx->current, NULL, Q_JMP, loop->after, NULL); + pushi(ctx->current, NULL, Q_JMP, scope->after, NULL); } } @@ -1172,13 +1197,9 @@ gen_expr_for(struct gen_context *ctx, push(&ctx->current->body, &loopl); - struct gen_loop_context *loop_ctx = - xcalloc(sizeof(struct gen_loop_context), 1); - loop_ctx->after = &after; - loop_ctx->end = &end; - loop_ctx->label = expr->_for.label; - loop_ctx->parent = ctx->loop; - ctx->loop = loop_ctx; + struct gen_scope_context *scope = push_scope(ctx, SCOPE_LOOP, &end); + scope->after = &after; + scope->label = expr->_for.label; struct qbe_value cond = {0}; gen_temp(ctx, &cond, &qbe_word, "cond.%d"); @@ -1194,8 +1215,7 @@ gen_expr_for(struct gen_context *ctx, gen_expression(ctx, expr->_for.afterthought, NULL); } - ctx->loop = ctx->loop->parent; - free(loop_ctx); + pop_scope(ctx); pushi(ctx->current, NULL, Q_JMP, &loop, NULL);