From 01ea2c088d975d0688dbb11d74f8e4dac14b7d1b Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 1 Dec 2024 11:33:23 +0900 Subject: [PATCH 1/3] Add more tests for `redo` keyword --- test/t/syntax.rb | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/t/syntax.rb b/test/t/syntax.rb index dedbbd1c2..134cd957c 100644 --- a/test/t/syntax.rb +++ b/test/t/syntax.rb @@ -95,6 +95,43 @@ assert('redo', '11.5.2.4.5') do a.push(n) end assert_equal [1,3,4], a + + a = [] + limit = 3 + e = RuntimeError.new("!") + for i in 0...3 + begin + limit -= 1 + break unless limit > 0 + a.push i * 3 + 1 + raise e + rescue + a.push i * 3 + 2 + redo + ensure + a.push i * 3 + 3 + end + end + assert_equal [1, 2, 3, 1, 2, 3, 3], a + + a = [] + limit = 3 + e = RuntimeError.new("!") + for i in 0...3 + a.push i * 4 + 1 + begin + limit -= 1 + break unless limit > 0 + a.push i * 4 + 2 + raise e + rescue + a.push i * 4 + 3 + redo + ensure + a.push i * 4 + 4 + end + end + assert_equal [1, 2, 3, 4, 1, 2, 3, 4, 1, 4], a end assert('Abbreviated variable assignment', '11.4.2.3.2') do From 939659e2db44a00832c43921df4dd765d4958c2f Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 1 Dec 2024 11:34:10 +0900 Subject: [PATCH 2/3] Allow `redo` from nested `LOOP_BEGIN` and `LOOP_RESCUE` --- mrbgems/mruby-compiler/core/codegen.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index fc9f0d0e6..96525e53e 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -3183,11 +3183,14 @@ codegen(codegen_scope *s, node *tree, int val) break; case NODE_REDO: - if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) { - raise_error(s, "unexpected redo"); - } - else { - genjmp(s, OP_JMPUW, s->loop->pc1); + for (const struct loopinfo *lp = s->loop; ; lp = lp->prev) { + if (!lp) { + raise_error(s, "unexpected redo"); + } + if (lp->type != LOOP_BEGIN && lp->type != LOOP_RESCUE) { + genjmp(s, OP_JMPUW, lp->pc1); + break; + } } if (val) push(); break; From 9a67bdb6aa875a8522afd8b3d81ea1d3fb99e60a Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 1 Dec 2024 11:40:17 +0900 Subject: [PATCH 3/3] Fix `redo` keyword Add `OP_NOP` to distinguish `retry` and jump targets while maintaining instruction compatibility. Ideally, it might be preferable to separate them into `OP_REDO`. fixed #6439 --- mrbgems/mruby-compiler/core/codegen.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 96525e53e..364ce2048 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1323,6 +1323,7 @@ for_body(codegen_scope *s, node *tree) /* construct loop */ lp = loop_push(s, LOOP_FOR); lp->pc1 = new_label(s); + genop_0(s, OP_NOP); /* for redo */ /* loop body */ codegen(s, tree->cdr->cdr->car, VAL); @@ -2589,6 +2590,7 @@ codegen(codegen_scope *s, node *tree, int val) pos = genjmp2_0(s, OP_JMPIF, cursp(), NOVAL); } lp->pc1 = new_label(s); + genop_0(s, OP_NOP); /* for redo */ codegen(s, tree->cdr, NOVAL); genjmp(s, OP_JMP, lp->pc0); dispatch(s, pos);