mruby-compiler: complete NODE_ARRAY migration to variable-sized nodes exclusively

Following the proven NODE_HASH pattern:
- Inlined new_array_var functionality into new_array in parse.y
- Enhanced gen_array_var with full splat support from gen_values
- Removed obsolete codegen_array function and cons list NODE_ARRAY case
- All arrays now use variable-sized nodes with identical test success (1730/1731)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-09-07 08:35:15 +09:00
parent cd659927fa
commit d69bc16370
3 changed files with 1227 additions and 1212 deletions
+59 -26
View File
@@ -3792,21 +3792,6 @@ codegen_const(codegen_scope *s, mrb_sym sym, int val)
if (val) push();
}
static void
codegen_array(codegen_scope *s, node *tree, int val)
{
int n;
n = gen_values(s, tree, val, 0);
if (!val) return;
if (n >= 0) {
pop_n(n);
genop_2(s, OP_ARRAY, cursp(), n);
}
push();
}
static void
gen_hash_var(codegen_scope *s, node *varnode, int val)
{
@@ -4655,6 +4640,9 @@ gen_array_var(codegen_scope *s, node *varnode, int val)
int len = ARRAY_NODE_LEN(array);
struct mrb_ast_node **elements = ARRAY_NODE_ELEMENTS(array);
int i;
int regular_elements = 0;
int first = 1;
int slimit = GEN_VAL_STACK_MAX;
if (!val) return;
@@ -4664,15 +4652,65 @@ gen_array_var(codegen_scope *s, node *varnode, int val)
return;
}
/* Generate code for each element */
if (cursp() >= GEN_LIT_ARY_MAX) slimit = INT16_MAX;
/* Process each element, handling splats */
for (i = 0; i < len; i++) {
codegen(s, elements[i], VAL);
struct mrb_ast_node *element = elements[i];
int is_splat = node_to_int(element->car) == NODE_SPLAT;
if (is_splat || cursp() >= slimit) { /* flush accumulated elements */
if (regular_elements > 0) {
pop_n(regular_elements);
if (first) {
genop_2(s, OP_ARRAY, cursp(), regular_elements);
push();
first = 0;
}
else {
pop();
genop_2(s, OP_ARYPUSH, cursp(), regular_elements);
push();
}
regular_elements = 0;
}
else if (first && is_splat) {
/* First element is splat - create empty array */
genop_1(s, OP_LOADNIL, cursp());
genop_2(s, OP_ARRAY, cursp(), 0);
push();
first = 0;
}
}
codegen(s, element, val);
if (is_splat) {
/* Concatenate splat array */
pop(); pop();
genop_1(s, OP_ARYCAT, cursp());
push();
}
else {
regular_elements++;
}
}
/* Create array with elements on stack */
pop_n(len);
genop_2(s, OP_ARRAY, cursp(), len);
push();
/* Handle any remaining regular elements */
if (!first) {
/* Variable length - we have an array from splats */
if (regular_elements > 0) {
pop_n(regular_elements + 1);
genop_2(s, OP_ARYPUSH, cursp(), regular_elements);
push();
}
}
else {
/* Simple case: no splats, just create array */
pop_n(regular_elements);
genop_2(s, OP_ARRAY, cursp(), regular_elements);
push();
}
}
@@ -6421,7 +6459,6 @@ codegen(codegen_scope *s, node *tree, int val)
codegen_block(s, tree, val);
break;
case NODE_SCOPE:
codegen_scope_node(s, tree, val);
break;
@@ -6442,10 +6479,6 @@ codegen(codegen_scope *s, node *tree, int val)
codegen_colon3(s, tree, val);
break;
case NODE_ARRAY:
codegen_array(s, tree, val);
break;
case NODE_HASH:
case NODE_KW_HASH:
codegen_hash(s, tree, val);
+29 -38
View File
@@ -596,7 +596,6 @@ new_alias(parser_state *p, mrb_sym a, mrb_sym b)
}
/* Forward declarations for variable-sized AST node creation functions */
static node* new_array_var(parser_state *p, node *a);
static node* new_def_var(parser_state *p, mrb_sym name, node *args, node *body);
static node* new_class_var(parser_state *p, node *name, node *superclass, node *body);
static node* new_module_var(parser_state *p, node *name, node *body);
@@ -851,40 +850,6 @@ new_call_var(parser_state *p, node *receiver, mrb_sym method, node *args, int pa
#endif
/* Variable-sized array node creation */
static node*
new_array_var(parser_state *p, node *a)
{
/* Count array elements */
uint16_t len = 0;
node *elem_iter = a;
while (elem_iter) {
len++;
elem_iter = elem_iter->cdr;
}
/* Calculate total size needed */
size_t base_size = sizeof(struct mrb_ast_array_node);
size_t elems_size = len * sizeof(struct mrb_ast_node*);
size_t total_size = base_size + elems_size;
enum mrb_ast_size_class class = size_to_class(total_size);
struct mrb_ast_array_node *n = (struct mrb_ast_array_node*)
parser_alloc_var(p, total_size, class);
init_var_header(&n->header, p, NODE_ARRAY, class);
n->len = len;
n->flags = 0;
/* Copy elements into flexible array */
elem_iter = a;
for (int i = 0; i < len; i++) {
n->elements[i] = elem_iter->car;
elem_iter = elem_iter->cdr;
}
return cons_head((node*)NODE_VARIABLE, (node*)n);
}
@@ -1309,10 +1274,36 @@ new_or(parser_state *p, node *a, node *b)
static node*
new_array(parser_state *p, node *a)
{
if (p->cxt && p->cxt->use_variable_nodes) {
return new_array_var(p, a);
/* Count array elements */
uint16_t len = 0;
node *elem_iter = a;
while (elem_iter) {
len++;
elem_iter = elem_iter->cdr;
}
return cons_head((node*)NODE_ARRAY, a);
/* Calculate total size needed */
size_t base_size = sizeof(struct mrb_ast_array_node);
size_t elems_size = len * sizeof(struct mrb_ast_node*);
size_t total_size = base_size + elems_size;
enum mrb_ast_size_class class = size_to_class(total_size);
struct mrb_ast_array_node *n = (struct mrb_ast_array_node*)
parser_alloc_var(p, total_size, class);
init_var_header(&n->header, p, NODE_ARRAY, class);
n->len = len;
n->flags = 0;
/* Copy elements into flexible array */
elem_iter = a;
for (int i = 0; i < len; i++) {
n->elements[i] = elem_iter->car;
elem_iter = elem_iter->cdr;
}
return cons_head((node*)NODE_VARIABLE, (node*)n);
}
/* (:splat . a) */
File diff suppressed because it is too large Load Diff