harec

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

commit 1a0505eba114a4685a73a3aa6ab7c42088b8b566
parent d167704f1e5339b05d80ba81761f4c5cd4289669
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Tue, 19 Jan 2021 11:10:08 -0500

Require loop labels to be unique among ancestors

Also update tests acordingly

Diffstat:
Minclude/ast.h | 1+
Msrc/check.c | 10++++++++++
Msrc/parse.c | 1+
Mtests/12-loops.ha | 4+---
4 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -211,6 +211,7 @@ struct ast_expression_control { struct ast_expression_for { char *label; + struct location label_loc; struct ast_expression *bindings; struct ast_expression *cond; struct ast_expression *afterthought; diff --git a/src/check.c b/src/check.c @@ -652,6 +652,16 @@ check_expr_for(struct context *ctx, expr->_for.scope = scope; scope->type = expr->type; scope->label = expr->_for.label; + if (expr->_for.label) { + for (scope = scope->parent; scope; scope = scope->parent) { + if (scope->label == NULL) { + continue; + } + expect(&aexpr->_for.label_loc, + strcmp(scope->label, expr->_for.label) != 0, + "for loop label must be unique among its ancestors"); + } + } struct expression *bindings = NULL, *cond = NULL, *afterthought = NULL, *body = NULL; diff --git a/src/parse.c b/src/parse.c @@ -1554,6 +1554,7 @@ parse_for_expression(struct lexer *lexer) case T_FOR: break; case T_LABEL: + exp->_for.label_loc = tok.loc; exp->_for.label = tok.name; want(lexer, T_FOR, NULL); break; diff --git a/tests/12-loops.ha b/tests/12-loops.ha @@ -75,9 +75,6 @@ fn label() void = { let i = 0; :outer for (i < 10) { :inner for (let j = 0; j < 7; j += 1) { - :outer for (true) { - break :outer; - }; i += 1; if (j == 6) { continue :inner; @@ -92,6 +89,7 @@ fn label() void = { assert(rt::compile("fn test() void = { :foo for (true) { break :bar; }; };") != 0); assert(rt::compile("fn test() void = { for (true) { break :bar; }; };") != 0); assert(rt::compile("fn test() void = { break :bar; };") != 0); + assert(rt::compile("fn test() void = { :foo for (true) { :foo for (true) void; } ; };") != 0); }; export fn main() void = {