mruby-compiler: convert new_yield to always use variable-sized nodes

- Remove conditional var_nodes_enabled logic from new_yield
- Delete unused new_yield_var function and forward declaration
- Move NODE_YIELD handling to NODE_VARIABLE branch in call_with_block
- Remove traditional NODE_YIELD case from main codegen function
- Inline codegen_yield logic directly into gen_yield_var

This completes the modernization of yield node handling to exclusively
use variable-sized nodes throughout the compiler pipeline.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-09-03 23:02:56 +09:00
parent e02bb13d00
commit 2000ef7820
3 changed files with 1160 additions and 1191 deletions
+35 -48
View File
@@ -4791,47 +4791,6 @@ codegen_block_arg(codegen_scope *s, node *tree, int val)
}
static void
codegen_yield(codegen_scope *s, node *tree, int val)
{
codegen_scope *s2 = s;
int lv = 0, ainfo = -1;
int n = 0, nk = 0, sendv = 0;
while (!s2->mscope) {
lv++;
s2 = s2->prev;
if (!s2) break;
}
if (s2) {
ainfo = (int)s2->ainfo;
}
if (ainfo < 0) codegen_error(s, "invalid yield (SyntaxError)");
if (lv > 0xf) codegen_error(s, "too deep nesting");
push();
if (tree) {
if (tree->car) {
n = gen_values(s, tree->car, VAL, 14);
if (n < 0) {
n = sendv = 1;
push();
}
}
if (tree->cdr->car) {
nk = gen_hash(s, tree->cdr->car->cdr, VAL, 14);
if (nk < 0) {
nk = 15;
}
}
}
push();pop(); /* space for a block */
pop_n(n + (nk == 15 ? 1 : nk * 2) + 1);
genop_2S(s, OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf));
if (sendv) n = CALL_MAXARGS;
genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_SYM_2(s->mrb, call)), n|(nk<<4));
if (val) push();
}
/* Handle variable-sized node types */
static void
gen_call_var(codegen_scope *s, node *varnode, int val)
@@ -5317,9 +5276,42 @@ gen_yield_var(codegen_scope *s, node *varnode, int val)
{
struct mrb_ast_yield_node *yield_n = yield_node(varnode);
node *args = YIELD_NODE_ARGS(yield_n);
codegen_scope *s2 = s;
int lv = 0, ainfo = -1;
int n = 0, nk = 0, sendv = 0;
/* Use traditional yield codegen logic */
codegen_yield(s, args, val);
while (!s2->mscope) {
lv++;
s2 = s2->prev;
if (!s2) break;
}
if (s2) {
ainfo = (int)s2->ainfo;
}
if (ainfo < 0) codegen_error(s, "invalid yield (SyntaxError)");
if (lv > 0xf) codegen_error(s, "too deep nesting");
push();
if (args) {
if (args->car) {
n = gen_values(s, args->car, VAL, 14);
if (n < 0) {
n = sendv = 1;
push();
}
}
if (args->cdr->car) {
nk = gen_hash(s, args->cdr->car->cdr, VAL, 14);
if (nk < 0) {
nk = 15;
}
}
}
push();pop(); /* space for a block */
pop_n(n + (nk == 15 ? 1 : nk * 2) + 1);
genop_2S(s, OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf));
if (sendv) n = CALL_MAXARGS;
genop_3(s, OP_SEND, cursp(), new_sym(s, MRB_SYM_2(s->mrb, call)), n|(nk<<4));
if (val) push();
}
static void
@@ -6473,15 +6465,10 @@ codegen(codegen_scope *s, node *tree, int val)
codegen_op_asgn(s, tree, val);
break;
case NODE_RETURN:
codegen_return(s, tree, val);
break;
case NODE_YIELD:
codegen_yield(s, tree, val);
break;
case NODE_BREAK:
codegen_break(s, tree, val);
break;
+15 -24
View File
@@ -611,7 +611,6 @@ static node* new_op_asgn_var(parser_state *p, node *lhs, mrb_sym op, node *rhs);
static node* new_and_var(parser_state *p, node *left, node *right);
static node* new_or_var(parser_state *p, node *left, node *right);
static node* new_return_var(parser_state *p, node *args);
static node* new_yield_var(parser_state *p, node *args);
static node* new_float_var(parser_state *p, const char *value);
/* (:if cond then else) */
@@ -1166,19 +1165,6 @@ new_return_var(parser_state *p, node *args)
return cons_head((node*)NODE_VARIABLE, (node*)n);
}
static node*
new_yield_var(parser_state *p, node *args)
{
size_t total_size = sizeof(struct mrb_ast_yield_node);
enum mrb_ast_size_class class = size_to_class(total_size);
struct mrb_ast_yield_node *n = (struct mrb_ast_yield_node*)parser_alloc_var(p, total_size, class);
init_var_header(&n->header, p, NODE_YIELD, class);
n->args = args;
return cons_head((node*)NODE_VARIABLE, (node*)n);
}
/* Variable-sized literal node creation functions */
@@ -1351,10 +1337,15 @@ new_yield(parser_state *p, node *c)
yyerror(NULL, p, "both block arg and actual block given");
}
if (p->var_nodes_enabled) {
return new_yield_var(p, c);
}
return cons_head((node*)NODE_YIELD, c);
size_t total_size = sizeof(struct mrb_ast_yield_node);
enum mrb_ast_size_class class = size_to_class(total_size);
struct mrb_ast_yield_node *n = (struct mrb_ast_yield_node*)parser_alloc_var(p, total_size, class);
init_var_header(&n->header, p, NODE_YIELD, class);
n->args = c;
return cons_head((node*)NODE_VARIABLE, (node*)n);
}
/* (:return . c) */
@@ -2323,6 +2314,11 @@ call_with_block(parser_state *p, node *a, node *b)
}
return;
}
else if (var_type == NODE_YIELD) {
/* Variable-sized yield nodes should generate an error when given a block */
yyerror(NULL, p, "block given to yield");
return;
}
}
/* For other variable-sized nodes, fall through to default */
break;
@@ -4270,12 +4266,7 @@ do_block : keyword_do_block
block_call : command do_block
{
if (node_to_type($1->car) == NODE_YIELD) {
yyerror(&@1, p, "block given to yield");
}
else {
call_with_block(p, $1, $2);
}
call_with_block(p, $1, $2);
$$ = $1;
}
| block_call call_op2 operation2 opt_paren_args
File diff suppressed because it is too large Load Diff