mruby-compiler: remove cons-list support for NODE_BREAK, NODE_NEXT, NODE_REDO, NODE_RETRY

These node types always generate variable-sized nodes, so the cons-list
codegen support is no longer needed. This change:

codegen.c:
- Moves logic from codegen_break/next/redo/retry into gen_*_var functions
- Removes cons-list switch cases for these four node types
- Removes the now-unused codegen_break/next/redo/retry functions

parse.y:
- Updates call_with_block to handle NODE_BREAK and NODE_NEXT through
  NODE_VARIABLE case instead of cons-list cases
- Removes the now-unused cons-list cases for these node types

All control flow functionality remains identical, but the code path is
simplified since these nodes exclusively use variable-sized structures.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-09-09 10:40:58 +09:00
parent 5e130f5381
commit f4fe87c11e
3 changed files with 1333 additions and 1355 deletions
+47 -87
View File
@@ -4177,73 +4177,6 @@ codegen_undef(codegen_scope *s, node *tree, int val)
gen_load_nil(s, val);
}
static void
codegen_break(codegen_scope *s, node *tree, int val)
{
loop_break(s, tree);
if (!val) return;
push();
}
static void
codegen_next(codegen_scope *s, node *tree, int val)
{
if (!s->loop) {
raise_error(s, "unexpected next");
}
else if (s->loop->type == LOOP_NORMAL) {
codegen(s, tree, NOVAL);
genjmp(s, OP_JMPUW, s->loop->pc0);
}
else {
if (tree) {
codegen(s, tree, VAL);
pop();
}
else {
genop_1(s, OP_LOADNIL, cursp());
}
gen_return(s, OP_RETURN, cursp());
}
if (!val) return;
push();
}
static void
codegen_redo(codegen_scope *s, node *tree, int val)
{
for (const struct loopinfo *lp = s->loop; ; lp = lp->prev) {
if (!lp) {
raise_error(s, "unexpected redo");
break;
}
if (lp->type != LOOP_BEGIN && lp->type != LOOP_RESCUE) {
genjmp(s, OP_JMPUW, lp->pc1);
break;
}
}
if (!val) return;
push();
}
static void
codegen_retry(codegen_scope *s, node *tree, int val)
{
const struct loopinfo *lp = s->loop;
while (lp && lp->type != LOOP_RESCUE) {
lp = lp->prev;
}
if (!lp) {
raise_error(s, "unexpected retry");
}
else {
genjmp(s, OP_JMPUW, lp->pc0);
}
if (!val) return;
push();
}
static void
codegen_back_ref(codegen_scope *s, node *tree, int val)
{
@@ -5532,26 +5465,69 @@ static void
gen_break_var(codegen_scope *s, node *varnode, int val)
{
struct mrb_ast_break_node *n = (struct mrb_ast_break_node*)varnode;
codegen_break(s, n->value, val);
loop_break(s, n->value);
if (!val) return;
push();
}
static void
gen_next_var(codegen_scope *s, node *varnode, int val)
{
struct mrb_ast_next_node *n = (struct mrb_ast_next_node*)varnode;
codegen_next(s, n->value, val);
if (!s->loop) {
raise_error(s, "unexpected next");
}
else if (s->loop->type == LOOP_NORMAL) {
codegen(s, n->value, NOVAL);
genjmp(s, OP_JMPUW, s->loop->pc0);
}
else {
if (n->value) {
codegen(s, n->value, VAL);
pop();
}
else {
genop_1(s, OP_LOADNIL, cursp());
}
gen_return(s, OP_RETURN, cursp());
}
if (!val) return;
push();
}
static void
gen_redo_var(codegen_scope *s, node *varnode, int val)
{
codegen_redo(s, NULL, val);
for (const struct loopinfo *lp = s->loop; ; lp = lp->prev) {
if (!lp) {
raise_error(s, "unexpected redo");
break;
}
if (lp->type != LOOP_BEGIN && lp->type != LOOP_RESCUE) {
genjmp(s, OP_JMPUW, lp->pc1);
break;
}
}
if (!val) return;
push();
}
static void
gen_retry_var(codegen_scope *s, node *varnode, int val)
{
codegen_retry(s, NULL, val);
const struct loopinfo *lp = s->loop;
while (lp && lp->type != LOOP_RESCUE) {
lp = lp->prev;
}
if (!lp) {
raise_error(s, "unexpected retry");
}
else {
genjmp(s, OP_JMPUW, lp->pc0);
}
if (!val) return;
push();
}
static void
@@ -6399,22 +6375,6 @@ codegen(codegen_scope *s, node *tree, int val)
codegen_op_asgn(s, tree, val);
break;
case NODE_BREAK:
codegen_break(s, tree, val);
break;
case NODE_NEXT:
codegen_next(s, tree, val);
break;
case NODE_REDO:
codegen_redo(s, tree, val);
break;
case NODE_RETRY:
codegen_retry(s, tree, val);
break;
case NODE_LVAR:
codegen_lvar(s, node_to_sym(tree), val);
break;
+14 -5
View File
@@ -2185,6 +2185,20 @@ call_with_block(parser_state *p, node *a, node *b)
call_with_block(p, return_n->args, b);
return;
}
else if (var_type == NODE_BREAK) {
/* Variable-sized break nodes - recursively call with value */
struct mrb_ast_break_node *break_n = (struct mrb_ast_break_node*)a->cdr;
if (break_n->value == NULL) return;
call_with_block(p, break_n->value, b);
return;
}
else if (var_type == NODE_NEXT) {
/* Variable-sized next nodes - recursively call with value */
struct mrb_ast_next_node *next_n = (struct mrb_ast_next_node*)a->cdr;
if (next_n->value == NULL) return;
call_with_block(p, next_n->value, b);
return;
}
}
/* For other variable-sized nodes, fall through to default */
break;
@@ -2196,11 +2210,6 @@ call_with_block(parser_state *p, node *a, node *b)
if (!n->car) n->car = new_callargs(p, 0, 0, b);
else args_with_block(p, n->car, b);
break;
case NODE_BREAK:
case NODE_NEXT:
if (a->cdr == NULL) return;
call_with_block(p, a->cdr, b);
break;
default:
break;
}
File diff suppressed because it is too large Load Diff