mruby-compiler: migrate NODE_DEF and NODE_SDEF to variable-sized nodes

Complete migration of method definition nodes to variable-sized format:
- Convert NODE_DEF and NODE_SDEF from fixed cons-based to variable-sized nodes
- Update parser to create variable-sized def/sdef nodes directly
- Remove old codegen_def and codegen_sdef functions
- Consolidate method setup logic in defn_setup function
- Rename lambda_body_ex to lambda_body after removing wrapper layer
- Update all method definition code generation to use new node structure

This completes the variable-sized node migration for method definitions,
improving memory efficiency and enabling more flexible AST handling.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-09-13 12:58:00 +09:00
parent 2596005750
commit ecbf25378b
4 changed files with 1299 additions and 1431 deletions
+9 -62
View File
@@ -2305,7 +2305,7 @@ search_upvar(codegen_scope *s, mrb_sym id, int *idx)
* @return The index of the newly created `mrb_irep` in the parent scope's `reps` array.
*/
static int
lambda_body_ex(codegen_scope *s, node *locals, node *args, node *body, int blk)
lambda_body(codegen_scope *s, node *locals, node *args, node *body, int blk)
{
codegen_scope *parent = s;
/* Create a new scope for the lambda/block body. */
@@ -2514,18 +2514,6 @@ lambda_body_ex(codegen_scope *s, node *locals, node *args, node *body, int blk)
return parent->irep->rlen - 1; /* Return the index of this IREP in the parent's REP list. */
}
static int
lambda_body(codegen_scope *s, node *tree, int blk)
{
/* Extract locals, args, and body from the cons structure */
node *locals = tree->car;
node *args = tree->cdr ? tree->cdr->car : NULL;
node *body = (tree->cdr && tree->cdr->cdr) ? tree->cdr->cdr->car : NULL;
/* Call the new lambda_body_ex with individual parameters */
return lambda_body_ex(s, locals, args, body, blk);
}
/*
* Generates code for a new lexical scope, typically for class/module definitions
* or the top-level script.
@@ -3656,39 +3644,6 @@ codegen_regx(codegen_scope *s, node *tree, int val)
}
}
static void
codegen_def(codegen_scope *s, node *tree, int val)
{
int sym = new_sym(s, node_to_sym(tree->car));
int idx = lambda_body(s, tree->cdr, 0);
genop_1(s, OP_TCLASS, cursp());
push();
genop_2(s, OP_METHOD, cursp(), idx);
push(); pop();
pop();
genop_2(s, OP_DEF, cursp(), sym);
if (val) push();
}
static void
codegen_sdef(codegen_scope *s, node *tree, int val)
{
node *recv = tree->car;
int sym = new_sym(s, node_to_sym(tree->cdr->car));
int idx = lambda_body(s, tree->cdr->cdr, 0);
codegen(s, recv, VAL);
pop();
genop_1(s, OP_SCLASS, cursp());
push();
genop_2(s, OP_METHOD, cursp(), idx);
push(); pop();
pop();
genop_2(s, OP_DEF, cursp(), sym);
if (val) push();
}
/* Handle variable-sized node types */
static void
gen_call_var(codegen_scope *s, node *varnode, int val)
@@ -4343,9 +4298,9 @@ gen_def_var(codegen_scope *s, node *varnode, int val)
struct mrb_ast_def_node *def_n = def_node(varnode);
int sym = new_sym(s, def_n->name);
/* Call lambda_body_ex directly with individual parameters */
/* Call lambda_body directly with individual parameters */
/* For NODE_DEF, args should contain the full locals structure from defn_setup */
int idx = lambda_body_ex(s, NULL, def_n->args, def_n->body, 0);
int idx = lambda_body(s, def_n->locals, def_n->args, def_n->body, 0);
genop_1(s, OP_TCLASS, cursp());
push();
@@ -5103,8 +5058,8 @@ gen_block_var(codegen_scope *s, node *varnode, int val)
struct mrb_ast_block_node *n = block_node(varnode);
/* Call lambda_body_ex directly with individual parameters */
int idx = lambda_body_ex(s, n->locals, n->args, n->body, 1);
/* Call lambda_body directly with individual parameters */
int idx = lambda_body(s, n->locals, n->args, n->body, 1);
genop_2(s, OP_BLOCK, cursp(), idx);
push();
}
@@ -5536,8 +5491,8 @@ gen_lambda_var(codegen_scope *s, node *varnode, int val)
struct mrb_ast_lambda_node *n = lambda_node(varnode);
/* Call lambda_body_ex directly with individual parameters */
int idx = lambda_body_ex(s, n->locals, n->args, n->body, 1);
/* Call lambda_body directly with individual parameters */
int idx = lambda_body(s, n->locals, n->args, n->body, 1);
genop_2(s, OP_LAMBDA, cursp(), idx);
push();
}
@@ -5716,9 +5671,9 @@ gen_sdef_var(codegen_scope *s, const node *varnode, int val)
node *recv = sdef->obj;
int sym = new_sym(s, sdef->name);
/* Call lambda_body_ex directly with individual parameters */
/* Call lambda_body directly with individual parameters */
/* For NODE_SDEF, args should contain the full locals structure from defs_setup */
int idx = lambda_body_ex(s, NULL, sdef->args, sdef->body, 0);
int idx = lambda_body(s, sdef->locals, sdef->args, sdef->body, 0);
codegen(s, recv, VAL);
pop();
@@ -6104,14 +6059,6 @@ codegen(codegen_scope *s, node *tree, int val)
codegen_scall(s, tree, val);
break;
case NODE_DEF:
codegen_def(s, tree, val);
break;
case NODE_SDEF:
codegen_sdef(s, tree, val);
break;
case NODE_VARIABLE:
codegen_variable_node(s, tree, val);
break;
+13 -10
View File
@@ -252,11 +252,22 @@ struct mrb_ast_hash_node {
struct mrb_ast_def_node {
struct mrb_ast_var_header header; /* 8 bytes */
mrb_sym name; /* Method name */
struct mrb_ast_node *args; /* Arguments node */
struct mrb_ast_node *args; /* Method arguments */
struct mrb_ast_node *body; /* Method body */
struct mrb_ast_node *locals; /* Local Variables */
} ;
/* Variable-sized singleton method definition node */
struct mrb_ast_sdef_node {
struct mrb_ast_var_header header; /* 8 bytes */
mrb_sym name; /* Method name */
struct mrb_ast_node *args; /* Method arguments */
struct mrb_ast_node *body; /* Method body */
struct mrb_ast_node *locals; /* Local Variables */
struct mrb_ast_node *obj; /* receiver */
};
/* Variable-sized class definition node */
/* variable-sized class definition node */
struct mrb_ast_class_node {
struct mrb_ast_var_header header; /* 8 bytes */
struct mrb_ast_node *name; /* Class name (NODE_CONST or NODE_COLON2) */
@@ -906,14 +917,6 @@ struct mrb_ast_postexe_node {
struct mrb_ast_node *body;
};
struct mrb_ast_sdef_node {
struct mrb_ast_var_header hdr;
struct mrb_ast_node *obj;
mrb_sym name;
struct mrb_ast_node *args;
struct mrb_ast_node *body;
};
#define fcall_node(n) ((struct mrb_ast_fcall_node*)(n))
#define zsuper_node(n) ((struct mrb_ast_super_node*)(n))
#define lambda_node(n) ((struct mrb_ast_lambda_node*)(n))
+33 -74
View File
@@ -262,20 +262,6 @@ list4_gen(parser_state *p, node *a, node *b, node *c, node *d)
}
#define list4(a,b,c,d) list4_gen(p, (a),(b),(c),(d))
static node*
list5_gen(parser_state *p, node *a, node *b, node *c, node *d, node *e)
{
return cons_head(a, cons(b, cons(c, cons(d, cons(e, 0)))));
}
#define list5(a,b,c,d,e) list5_gen(p, (a),(b),(c),(d),(e))
static node*
list6_gen(parser_state *p, node *a, node *b, node *c, node *d, node *e, node *f)
{
return cons_head(a, cons(b, cons(c, cons(d, cons(e, cons(f, 0))))));
}
#define list6(a,b,c,d,e,f) list6_gen(p, (a),(b),(c),(d),(e),(f))
static node*
append_gen(parser_state *p, node *a, node *b)
{
@@ -605,9 +591,6 @@ new_alias(parser_state *p, mrb_sym a, mrb_sym b)
return cons_head((node*)NODE_VARIABLE, (node*)alias_node);
}
/* Forward declarations for variable-sized AST node creation functions */
static node* new_def_var(parser_state *p, mrb_sym name, node *args, node *body);
/* (:if cond then else) */
static node*
new_if(parser_state *p, node *condition, node *then_body, node *else_body)
@@ -853,25 +836,6 @@ new_call_var(parser_state *p, node *receiver, mrb_sym method, node *args, int pa
}
#endif
/* Variable-sized method definition node creation */
static node*
new_def_var(parser_state *p, mrb_sym name, node *args, node *body)
{
size_t total_size = sizeof(struct mrb_ast_def_node);
enum mrb_ast_size_class class = size_to_class(total_size);
struct mrb_ast_def_node *n = (struct mrb_ast_def_node*)parser_alloc_var(p, total_size, class);
init_var_header(&n->header, p, NODE_DEF, class);
n->name = name;
n->args = args;
n->body = body;
return cons_head((node*)NODE_VARIABLE, (node*)n);
}
/* Variable-sized simple node creation functions */
/* (:fcall self mid args) */
static node*
new_fcall(parser_state *p, mrb_sym b, node *c)
@@ -1357,58 +1321,53 @@ new_module(parser_state *p, node *m, node *b)
/* (:def m lv (arg . body)) */
static node*
new_def(parser_state *p, mrb_sym m, node *a, node *b)
new_def(parser_state *p, mrb_sym name)
{
if (p->var_nodes_enabled) {
return new_def_var(p, m, a, b);
}
return list5((node*)NODE_DEF, sym_to_node(m), 0, a, b);
size_t total_size = sizeof(struct mrb_ast_def_node);
enum mrb_ast_size_class class = size_to_class(total_size);
struct mrb_ast_def_node *n = (struct mrb_ast_def_node*)parser_alloc_var(p, total_size, class);
init_var_header(&n->header, p, NODE_DEF, class);
n->name = name;
n->args = int_to_node(p->cmdarg_stack);
n->locals = local_switch(p);
n->body = NULL;
return cons_head((node*)NODE_VARIABLE, (node*)n);
}
static void
defn_setup(parser_state *p, node *d, node *a, node *b)
{
node *n = d->cdr->cdr;
struct mrb_ast_def_node *n = def_node(d->cdr);
node *locals = n->locals;
n->car = locals_node(p);
p->cmdarg_stack = node_to_int(n->cdr->car);
n->cdr->car = a;
local_resume(p, n->cdr->cdr->car);
n->cdr->cdr->car = b;
n->locals = locals_node(p);
p->cmdarg_stack = node_to_int(n->args);
n->args = a;
n->body = b;
local_resume(p, locals);
}
/* (:sdef obj m lv (arg . body)) */
static node*
new_sdef(parser_state *p, node *o, mrb_sym m, node *a, node *b)
new_sdef(parser_state *p, node *o, mrb_sym name)
{
void_expr_error(p, o);
if (!p->var_nodes_enabled) {
return list6((node*)NODE_SDEF, o, sym_to_node(m), 0, a, b);
}
size_t total_size = sizeof(struct mrb_ast_sdef_node);
enum mrb_ast_size_class class = size_to_class(total_size);
struct mrb_ast_sdef_node *sdef_node = (struct mrb_ast_sdef_node*)parser_alloc_var(p, total_size, class);
init_var_header(&sdef_node->hdr, p, NODE_SDEF, class);
init_var_header(&sdef_node->header, p, NODE_SDEF, class);
sdef_node->obj = o;
sdef_node->name = m;
sdef_node->args = a;
sdef_node->body = b;
sdef_node->name = name;
sdef_node->args = int_to_node(p->cmdarg_stack);
sdef_node->locals = local_switch(p);
sdef_node->body = NULL;
return cons_head((node*)NODE_VARIABLE, (node*)sdef_node);
}
static void
defs_setup(parser_state *p, node *d, node *a, node *b)
{
node *n = d->cdr->cdr->cdr;
n->car = locals_node(p);
p->cmdarg_stack = node_to_int(n->cdr->car);
n->cdr->car = a;
local_resume(p, n->cdr->cdr->car);
n->cdr->cdr->car = b;
}
/* (:arg . sym) */
static node*
new_arg(parser_state *p, mrb_sym sym)
@@ -2711,7 +2670,7 @@ command_asgn : lhs '=' command_rhs
{
$$ = $1;
void_expr_error(p, $4);
defs_setup(p, $$, $2, $4);
defn_setup(p, $$, $2, $4);
nvars_unnest(p);
p->in_def--;
p->in_single--;
@@ -2720,7 +2679,7 @@ command_asgn : lhs '=' command_rhs
{
$$ = $1;
void_expr_error(p, $4);
defs_setup(p, $$, $2, new_mod_rescue(p, $4, $6));
defn_setup(p, $$, $2, new_mod_rescue(p, $4, $6));
nvars_unnest(p);
p->in_def--;
p->in_single--;
@@ -2762,7 +2721,7 @@ expr : command_call
defn_head : keyword_def fname
{
$$ = new_def(p, $2, int_to_node(p->cmdarg_stack), local_switch(p));
$$ = new_def(p, $2);
p->cmdarg_stack = 0;
p->in_def++;
nvars_block(p);
@@ -2775,7 +2734,7 @@ defs_head : keyword_def singleton dot_or_colon
}
fname
{
$$ = new_sdef(p, $2, $5, int_to_node(p->cmdarg_stack), local_switch(p));
$$ = new_sdef(p, $2, $5);
p->cmdarg_stack = 0;
p->in_def++;
p->in_single++;
@@ -3342,7 +3301,7 @@ arg : lhs '=' arg_rhs
{
$$ = $1;
void_expr_error(p, $4);
defs_setup(p, $$, $2, $4);
defn_setup(p, $$, $2, $4);
nvars_unnest(p);
p->in_def--;
p->in_single--;
@@ -3351,7 +3310,7 @@ arg : lhs '=' arg_rhs
{
$$ = $1;
void_expr_error(p, $4);
defs_setup(p, $$, $2, new_mod_rescue(p, $4, $6));
defn_setup(p, $$, $2, new_mod_rescue(p, $4, $6));
nvars_unnest(p);
p->in_def--;
p->in_single--;
@@ -3767,7 +3726,7 @@ primary : literal
keyword_end
{
$$ = $1;
defs_setup(p, $$, $2, $3);
defn_setup(p, $$, $2, $3);
nvars_unnest(p);
p->in_def--;
p->in_single--;
File diff suppressed because it is too large Load Diff