mruby-compiler: implement variable-sized nodes for function calls and special forms

Implements variable-sized nodes for function calls and special forms
(NODE_FCALL, NODE_ZSUPER, NODE_LAMBDA) with optimized memory allocation.
These nodes now use compact variable-sized structures instead of fixed-size
headers, reducing AST memory usage.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-08-28 14:32:15 +09:00
parent d01be7af0f
commit da8072e00a
4 changed files with 2006 additions and 1858 deletions
+56
View File
@@ -5781,6 +5781,50 @@ gen_defined_var(codegen_scope *s, node *varnode, int val)
}
}
// Group 12: Function Calls and Special Forms
static void
gen_fcall_var(codegen_scope *s, node *varnode, int val)
{
struct mrb_ast_fcall_node *n = fcall_node(varnode);
// Create a stack-allocated node structure for traditional codegen
struct mrb_ast_node stack_nodes[3];
stack_nodes[0].car = NULL; // no receiver (self)
stack_nodes[0].cdr = &stack_nodes[1];
stack_nodes[1].car = (node*)(intptr_t)n->method_name; // method name as int
stack_nodes[1].cdr = &stack_nodes[2];
stack_nodes[2].car = n->args;
stack_nodes[2].cdr = NULL;
gen_call(s, &stack_nodes[0], val, 0);
}
static void
gen_zsuper_var(codegen_scope *s, node *varnode, int val)
{
(void)varnode; // suppress unused warning
// Create a simple stack structure
struct mrb_ast_node stack_node;
stack_node.car = (node*)NODE_ZSUPER;
stack_node.cdr = NULL;
codegen_zsuper(s, &stack_node, val);
}
static void
gen_lambda_var(codegen_scope *s, node *varnode, int val)
{
struct mrb_ast_lambda_node *n = lambda_node(varnode);
// Create stack-allocated node structure for traditional codegen
struct mrb_ast_node stack_nodes[4];
stack_nodes[0].car = (node*)NODE_LAMBDA;
stack_nodes[0].cdr = &stack_nodes[1];
stack_nodes[1].car = n->locals;
stack_nodes[1].cdr = &stack_nodes[2];
stack_nodes[2].car = n->args;
stack_nodes[2].cdr = &stack_nodes[3];
stack_nodes[3].car = n->body;
stack_nodes[3].cdr = NULL;
codegen_lambda(s, &stack_nodes[0], val);
}
static void
gen_args_tail_var(codegen_scope *s, node *varnode, int val)
{
@@ -6049,6 +6093,18 @@ codegen_variable_node(codegen_scope *s, node *varnode, int val)
gen_defined_var(s, varnode, val);
return TRUE;
case NODE_FCALL:
gen_fcall_var(s, varnode, val);
return TRUE;
case NODE_ZSUPER:
gen_zsuper_var(s, varnode, val);
return TRUE;
case NODE_LAMBDA:
gen_lambda_var(s, varnode, val);
return TRUE;
default:
return FALSE; /* Not handled, fall through to main codegen */
}
+28
View File
@@ -827,4 +827,32 @@ struct mrb_ast_defined_node {
#define COLON3_NODE_NAME(n) (colon3_node(n)->name)
#define DEFINED_NODE_EXPR(n) (defined_node(n)->expr)
// Group 12: Function Calls and Special Forms
struct mrb_ast_fcall_node {
struct mrb_ast_var_header hdr;
mrb_sym method_name;
struct mrb_ast_node *args;
};
struct mrb_ast_zsuper_node {
struct mrb_ast_var_header hdr;
};
struct mrb_ast_lambda_node {
struct mrb_ast_var_header hdr;
struct mrb_ast_node *locals;
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_zsuper_node*)(n))
#define lambda_node(n) ((struct mrb_ast_lambda_node*)(n))
#define FCALL_NODE_METHOD_NAME(n) (fcall_node(n)->method_name)
#define FCALL_NODE_ARGS(n) (fcall_node(n)->args)
#define LAMBDA_NODE_LOCALS(n) (lambda_node(n)->locals)
#define LAMBDA_NODE_ARGS(n) (lambda_node(n)->args)
#define LAMBDA_NODE_BODY(n) (lambda_node(n)->body)
#endif /* MRUBY_COMPILER_NODE_H */
+36 -4
View File
@@ -1392,8 +1392,19 @@ new_args_tail_var(parser_state *p, node *keywords, node *kwrest, mrb_sym block)
static node*
new_fcall(parser_state *p, mrb_sym b, node *c)
{
node *n = list4((node*)NODE_FCALL, 0, sym_to_node(b), c);
return n;
if (!p->var_nodes_enabled) {
node *n = list4((node*)NODE_FCALL, 0, sym_to_node(b), c);
return n;
}
size_t total_size = sizeof(struct mrb_ast_fcall_node);
enum mrb_ast_size_class class = size_to_class(total_size);
struct mrb_ast_fcall_node *fcall_node = (struct mrb_ast_fcall_node*)
parser_alloc_var(p, total_size, class);
init_var_header(&fcall_node->hdr, p, NODE_FCALL, class);
fcall_node->method_name = b;
fcall_node->args = c;
return cons_head((node*)NODE_VARIABLE, (node*)fcall_node);
}
/* (a b . c) */
@@ -1417,7 +1428,16 @@ new_super(parser_state *p, node *c)
static node*
new_zsuper(parser_state *p)
{
return cons_head((node*)NODE_ZSUPER, 0);
if (!p->var_nodes_enabled) {
return cons_head((node*)NODE_ZSUPER, 0);
}
size_t total_size = sizeof(struct mrb_ast_zsuper_node);
enum mrb_ast_size_class class = size_to_class(total_size);
struct mrb_ast_zsuper_node *zsuper_node = (struct mrb_ast_zsuper_node*)
parser_alloc_var(p, total_size, class);
init_var_header(&zsuper_node->hdr, p, NODE_ZSUPER, class);
return cons_head((node*)NODE_VARIABLE, (node*)zsuper_node);
}
/* (:yield . c) */
@@ -2023,7 +2043,19 @@ static node*
new_lambda(parser_state *p, node *a, node *b)
{
a = setup_numparams(p, a);
return list4((node*)NODE_LAMBDA, locals_node(p), a, b);
if (!p->var_nodes_enabled) {
return list4((node*)NODE_LAMBDA, locals_node(p), a, b);
}
size_t total_size = sizeof(struct mrb_ast_lambda_node);
enum mrb_ast_size_class class = size_to_class(total_size);
struct mrb_ast_lambda_node *lambda_node = (struct mrb_ast_lambda_node*)
parser_alloc_var(p, total_size, class);
init_var_header(&lambda_node->hdr, p, NODE_LAMBDA, class);
lambda_node->locals = locals_node(p);
lambda_node->args = a;
lambda_node->body = b;
return cons_head((node*)NODE_VARIABLE, (node*)lambda_node);
}
/* (:asgn lhs rhs) */
File diff suppressed because it is too large Load Diff