harec

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

commit 1350398abc63b71b0b4cd2c7c070d1e3950c304a
parent 6faec06c9543a42593ce939eeec8d47ed02879ea
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Tue, 12 Jan 2021 18:35:33 -0500

check: implement break/continue

Diffstat:
Minclude/expr.h | 6++++++
Minclude/scope.h | 3+++
Msrc/check.c | 40+++++++++++++++++++++++++++++++++++++---
3 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/include/expr.h b/include/expr.h @@ -138,7 +138,12 @@ union expression_constant { // TODO: Struct constants }; +struct expression_control { + char *label; +}; + struct expression_for { + char *label; struct scope *scope; struct expression *bindings; struct expression *cond; @@ -213,6 +218,7 @@ struct expression { struct expression_call call; struct expression_cast cast; union expression_constant constant; + struct expression_control control; struct expression_for _for; struct expression_if _if; struct expression_list list; diff --git a/include/scope.h b/include/scope.h @@ -1,5 +1,6 @@ #ifndef HAREC_SCOPE_H #define HAREC_SCOPE_H +#include "expr.h" #include "identifier.h" #include "trace.h" @@ -23,6 +24,8 @@ struct scope_object { }; struct scope { + enum expr_type type; + const char *label; struct scope_object *objects; struct scope_object **next; // List order matters for functions struct scope *parent; diff --git a/src/check.c b/src/check.c @@ -544,6 +544,33 @@ check_expr_constant(struct context *ctx, } static void +check_expr_control(struct context *ctx, + const struct ast_expression *aexpr, + struct expression *expr) +{ + trenter(TR_CHECK, "control"); + expr->type = aexpr->type; + expr->terminates = true; + char *label = expr->control.label = aexpr->control.label; + + struct scope *scope = ctx->scope; + for (; scope != NULL; scope = scope->parent) { + if (scope->type != EXPR_FOR) { + continue; + } + if (label == NULL) { + break; + } + if (scope->label != NULL && strcmp(label, scope->label) == 0) { + break; + } + } + expect(&aexpr->loc, scope != NULL, "Unknown label %s", + expr->control.label); + trleave(TR_CHECK, NULL); +} + +static void check_expr_for(struct context *ctx, const struct ast_expression *aexpr, struct expression *expr) @@ -552,8 +579,14 @@ check_expr_for(struct context *ctx, expr->type = EXPR_FOR; expr->result = &builtin_type_void; + if (aexpr->_for.label) { + expr->_for.label = strdup(aexpr->_for.label); + } + struct scope *scope = scope_push(&ctx->scope, TR_CHECK); expr->_for.scope = scope; + scope->type = expr->type; + scope->label = expr->_for.label; struct expression *bindings = NULL, *cond = NULL, *afterthought = NULL, *body = NULL; @@ -642,6 +675,7 @@ check_expr_list(struct context *ctx, struct scope *scope = scope_push(&ctx->scope, TR_CHECK); expr->list.scope = scope; + scope->type = expr->type; struct expressions *list = &expr->list.exprs; struct expressions **next = &list->next; @@ -874,7 +908,9 @@ check_expression(struct context *ctx, check_expr_binding(ctx, aexpr, expr); break; case EXPR_BREAK: - assert(0); // TODO + case EXPR_CONTINUE: + check_expr_control(ctx, aexpr, expr); + break; case EXPR_CALL: check_expr_call(ctx, aexpr, expr); break; @@ -884,8 +920,6 @@ check_expression(struct context *ctx, case EXPR_CONSTANT: check_expr_constant(ctx, aexpr, expr); break; - case EXPR_CONTINUE: - assert(0); // TODO case EXPR_FOR: check_expr_for(ctx, aexpr, expr); break;