mruby-compiler: implement variable-sized nodes for operators and expressions

Implements variable-sized nodes for operators and expressions
(NODE_NEGATE, NODE_COLON2, NODE_COLON3) 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 08:19:40 +09:00
parent ada87dffdb
commit d01be7af0f
4 changed files with 2038 additions and 1857 deletions
+77
View File
@@ -5724,6 +5724,63 @@ gen_match_var(codegen_scope *s, node *varnode, int val)
}
}
// Group 11: Operators and Expressions
static void
gen_not_var(codegen_scope *s, node *varnode, int val)
{
struct mrb_ast_not_node *n = (struct mrb_ast_not_node*)varnode;
// NOT nodes are rarely used - generate method call to !
if (val) {
codegen(s, n->operand, TRUE);
pop();
mrb_sym sym = new_sym(s, mrb_intern_lit(s->mrb, "!"));
genop_3(s, OP_SEND, cursp(), sym, 0);
push();
}
}
static void
gen_negate_var(codegen_scope *s, node *varnode, int val)
{
struct mrb_ast_negate_node *n = (struct mrb_ast_negate_node*)varnode;
codegen_negate(s, n->operand, val);
}
static void
gen_colon2_var(codegen_scope *s, node *varnode, int val)
{
struct mrb_ast_colon2_node *n = (struct mrb_ast_colon2_node*)varnode;
// Generate COLON2 (::) access manually
int sym = new_sym(s, n->name);
codegen(s, n->base, VAL);
pop();
genop_2(s, OP_GETMCNST, cursp(), sym);
if (val) push();
}
static void
gen_colon3_var(codegen_scope *s, node *varnode, int val)
{
struct mrb_ast_colon3_node *n = (struct mrb_ast_colon3_node*)varnode;
// Generate COLON3 (::Name) access manually
int sym = new_sym(s, n->name);
genop_2(s, OP_OCLASS, cursp(), sym);
if (val) push();
}
static void
gen_defined_var(codegen_scope *s, node *varnode, int val)
{
// DEFINED nodes are rarely used - generate basic implementation
(void)varnode; // suppress unused warning
if (val) {
// For now, just return nil (defined? is complex to implement correctly)
genop_1(s, OP_LOADNIL, cursp());
push();
}
}
static void
gen_args_tail_var(codegen_scope *s, node *varnode, int val)
{
@@ -5972,6 +6029,26 @@ codegen_variable_node(codegen_scope *s, node *varnode, int val)
gen_match_var(s, varnode, val);
return TRUE;
case NODE_NOT:
gen_not_var(s, varnode, val);
return TRUE;
case NODE_NEGATE:
gen_negate_var(s, varnode, val);
return TRUE;
case NODE_COLON2:
gen_colon2_var(s, varnode, val);
return TRUE;
case NODE_COLON3:
gen_colon3_var(s, varnode, val);
return TRUE;
case NODE_DEFINED:
gen_defined_var(s, varnode, val);
return TRUE;
default:
return FALSE; /* Not handled, fall through to main codegen */
}
+40
View File
@@ -787,4 +787,44 @@ struct mrb_ast_match_node {
#define DVAR_NODE_NAME(n) (dvar_node(n)->name)
#define MATCH_NODE_PATTERN(n) (match_node(n)->pattern)
// Group 11: Operators and Expressions
struct mrb_ast_not_node {
struct mrb_ast_var_header hdr;
struct mrb_ast_node *operand;
};
struct mrb_ast_negate_node {
struct mrb_ast_var_header hdr;
struct mrb_ast_node *operand;
};
struct mrb_ast_colon2_node {
struct mrb_ast_var_header hdr;
struct mrb_ast_node *base;
mrb_sym name;
};
struct mrb_ast_colon3_node {
struct mrb_ast_var_header hdr;
mrb_sym name;
};
struct mrb_ast_defined_node {
struct mrb_ast_var_header hdr;
struct mrb_ast_node *expr;
};
#define not_node(n) ((struct mrb_ast_not_node*)(n))
#define negate_node(n) ((struct mrb_ast_negate_node*)(n))
#define colon2_node(n) ((struct mrb_ast_colon2_node*)(n))
#define colon3_node(n) ((struct mrb_ast_colon3_node*)(n))
#define defined_node(n) ((struct mrb_ast_defined_node*)(n))
#define NOT_NODE_OPERAND(n) (not_node(n)->operand)
#define NEGATE_NODE_OPERAND(n) (negate_node(n)->operand)
#define COLON2_NODE_BASE(n) (colon2_node(n)->base)
#define COLON2_NODE_NAME(n) (colon2_node(n)->name)
#define COLON3_NODE_NAME(n) (colon3_node(n)->name)
#define DEFINED_NODE_EXPR(n) (defined_node(n)->expr)
#endif /* MRUBY_COMPILER_NODE_H */
+35 -3
View File
@@ -1535,14 +1535,35 @@ static node*
new_colon2(parser_state *p, node *b, mrb_sym c)
{
void_expr_error(p, b);
return cons_head((node*)NODE_COLON2, cons(b, sym_to_node(c)));
if (!p->var_nodes_enabled) {
return cons_head((node*)NODE_COLON2, cons(b, sym_to_node(c)));
}
size_t total_size = sizeof(struct mrb_ast_colon2_node);
enum mrb_ast_size_class class = size_to_class(total_size);
struct mrb_ast_colon2_node *colon2_node = (struct mrb_ast_colon2_node*)
parser_alloc_var(p, total_size, class);
init_var_header(&colon2_node->hdr, p, NODE_COLON2, class);
colon2_node->base = b;
colon2_node->name = c;
return cons_head((node*)NODE_VARIABLE, (node*)colon2_node);
}
/* (:colon3 . c) */
static node*
new_colon3(parser_state *p, mrb_sym c)
{
return cons_head((node*)NODE_COLON3, sym_to_node(c));
if (!p->var_nodes_enabled) {
return cons_head((node*)NODE_COLON3, sym_to_node(c));
}
size_t total_size = sizeof(struct mrb_ast_colon3_node);
enum mrb_ast_size_class class = size_to_class(total_size);
struct mrb_ast_colon3_node *colon3_node = (struct mrb_ast_colon3_node*)
parser_alloc_var(p, total_size, class);
init_var_header(&colon3_node->hdr, p, NODE_COLON3, class);
colon3_node->name = c;
return cons_head((node*)NODE_VARIABLE, (node*)colon3_node);
}
/* (:and a b) */
@@ -2502,9 +2523,20 @@ call_with_block(parser_state *p, node *a, node *b)
static node*
new_negate(parser_state *p, node *n)
{
return cons_head((node*)NODE_NEGATE, n);
if (!p->var_nodes_enabled) {
return cons_head((node*)NODE_NEGATE, n);
}
size_t total_size = sizeof(struct mrb_ast_negate_node);
enum mrb_ast_size_class class = size_to_class(total_size);
struct mrb_ast_negate_node *negate_node = (struct mrb_ast_negate_node*)
parser_alloc_var(p, total_size, class);
init_var_header(&negate_node->hdr, p, NODE_NEGATE, class);
negate_node->operand = n;
return cons_head((node*)NODE_VARIABLE, (node*)negate_node);
}
static node*
cond(node *n)
{
File diff suppressed because it is too large Load Diff