mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-compiler: complete NODE_SCOPE migration to variable-sized nodes exclusively
Remove NODE_SCOPE case from main codegen() switch and migrate all node creation to variable-sized nodes. Add node_type_p() helper for unified node type checking across traditional and variable-sized nodes. Key fixes: - Use scope_node(node->cdr) pattern for NODE_VARIABLE wrapper extraction - Update parser_update_cxt and mrb_parser_foreach_top_variable - Add NODE_VARIABLE support to mrb_parser_dump for bintest compatibility - Fix mirb local variable handling preventing TypeError on evaluation Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3590,13 +3590,6 @@ codegen_stmts(codegen_scope *s, node *tree, int val)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_begin(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
/* NODE_BEGIN contains a single body node directly in cdr */
|
||||
codegen(s, tree, val);
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_lambda(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
@@ -3795,11 +3788,6 @@ codegen_splat(codegen_scope *s, node *tree, int val)
|
||||
codegen(s, tree, val);
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_scope_node(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
scope_body(s, tree, NOVAL);
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_call_fcall(codegen_scope *s, node *tree, int val)
|
||||
@@ -5906,26 +5894,26 @@ gen_scope_var(codegen_scope *s, const node *varnode, int val)
|
||||
{
|
||||
struct mrb_ast_scope_node *scope = scope_node(varnode);
|
||||
|
||||
// Convert variable-sized scope to traditional cons list for scope_body
|
||||
node *locals = scope->locals;
|
||||
node *body = scope->body;
|
||||
|
||||
// Create stack-allocated traditional node structure
|
||||
/* Create a traditional cons-list structure that scope_body() expects:
|
||||
* tree->car should contain the locals cons-list
|
||||
* tree->cdr should contain the body
|
||||
*/
|
||||
node scope_node_stack;
|
||||
scope_node_stack.car = locals;
|
||||
scope_node_stack.cdr = body;
|
||||
scope_node_stack.car = scope->locals;
|
||||
scope_node_stack.cdr = scope->body;
|
||||
|
||||
scope_body(s, &scope_node_stack, val);
|
||||
/* Traditional codegen_scope_node called scope_body with NOVAL, not val */
|
||||
scope_body(s, &scope_node_stack, NOVAL);
|
||||
}
|
||||
|
||||
static void
|
||||
gen_begin_var(codegen_scope *s, const node *varnode, int val)
|
||||
gen_begin_var(codegen_scope *s, node *varnode, int val)
|
||||
{
|
||||
struct mrb_ast_begin_node *begin = begin_node(varnode);
|
||||
|
||||
// Convert variable-sized begin to traditional cons list for codegen_begin
|
||||
node *body = begin->body;
|
||||
codegen_begin(s, body, val);
|
||||
|
||||
/* Inline codegen_begin logic - just generate code for the body */
|
||||
codegen(s, body, val);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -6397,10 +6385,6 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
codegen_stmts(s, tree, val);
|
||||
break;
|
||||
|
||||
case NODE_BEGIN:
|
||||
codegen_begin(s, tree, val);
|
||||
break;
|
||||
|
||||
case NODE_LAMBDA:
|
||||
codegen_lambda(s, tree, val);
|
||||
break;
|
||||
@@ -6409,10 +6393,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;
|
||||
|
||||
case NODE_CALL:
|
||||
case NODE_FCALL:
|
||||
codegen_call_fcall(s, tree, val);
|
||||
|
||||
@@ -53,6 +53,9 @@ static node* new_const_var(parser_state *p, mrb_sym symbol);
|
||||
static node* new_block_var(parser_state *p, node *locals, node *args, node *body);
|
||||
static node* new_args_tail_var(parser_state *p, node *keywords, node *kwrest, mrb_sym block);
|
||||
|
||||
/* Helper function to check node type for both traditional and variable-sized nodes */
|
||||
static mrb_bool node_type_p(node *n, enum node_type type);
|
||||
|
||||
#define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c))
|
||||
|
||||
typedef unsigned int stack_type;
|
||||
@@ -439,6 +442,21 @@ locals_node(parser_state *p)
|
||||
return p->locals ? p->locals->car : NULL;
|
||||
}
|
||||
|
||||
/* Helper function to check node type for both traditional and variable-sized nodes */
|
||||
static mrb_bool
|
||||
node_type_p(node *n, enum node_type type)
|
||||
{
|
||||
if (!n) return FALSE;
|
||||
|
||||
/* Check traditional cons-list nodes */
|
||||
if (node_to_int(n->car) == type) return TRUE;
|
||||
|
||||
/* Check variable-sized nodes */
|
||||
if (n->car == (node*)NODE_VARIABLE && VAR_NODE_TYPE(n->cdr) == type) return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
nvars_nest(parser_state *p)
|
||||
{
|
||||
@@ -461,10 +479,6 @@ nvars_unnest(parser_state *p)
|
||||
static node*
|
||||
new_scope(parser_state *p, node *body)
|
||||
{
|
||||
if (!p->var_nodes_enabled) {
|
||||
return cons_head((node*)NODE_SCOPE, cons(locals_node(p), body));
|
||||
}
|
||||
|
||||
size_t total_size = sizeof(struct mrb_ast_scope_node);
|
||||
enum mrb_ast_size_class class = size_to_class(total_size);
|
||||
struct mrb_ast_scope_node *scope_node = (struct mrb_ast_scope_node*)parser_alloc_var(p, total_size, class);
|
||||
@@ -488,14 +502,10 @@ new_stmts(parser_state *p, node *body)
|
||||
return cons_head((node*)NODE_STMTS, 0);
|
||||
}
|
||||
|
||||
/* (:begin body) */
|
||||
/* (:begin body) - Always use variable-sized nodes */
|
||||
static node*
|
||||
new_begin(parser_state *p, node *body)
|
||||
{
|
||||
if (!p->var_nodes_enabled) {
|
||||
return cons_head((node*)NODE_BEGIN, body);
|
||||
}
|
||||
|
||||
size_t total_size = sizeof(struct mrb_ast_begin_node);
|
||||
enum mrb_ast_size_class class = size_to_class(total_size);
|
||||
struct mrb_ast_begin_node *begin_node = (struct mrb_ast_begin_node*)parser_alloc_var(p, total_size, class);
|
||||
@@ -2704,7 +2714,7 @@ stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym
|
||||
}
|
||||
| stmt modifier_while expr_value
|
||||
{
|
||||
if ($1 && node_to_type($1->car) == NODE_BEGIN) {
|
||||
if ($1 && node_type_p($1, NODE_BEGIN)) {
|
||||
$$ = new_while_mod(p, cond($3), $1);
|
||||
}
|
||||
else {
|
||||
@@ -2713,7 +2723,7 @@ stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym
|
||||
}
|
||||
| stmt modifier_until expr_value
|
||||
{
|
||||
if ($1 && node_to_type($1->car) == NODE_BEGIN) {
|
||||
if ($1 && node_type_p($1, NODE_BEGIN)) {
|
||||
$$ = new_until_mod(p, cond($3), $1);
|
||||
}
|
||||
else {
|
||||
@@ -7560,8 +7570,11 @@ parser_update_cxt(parser_state *p, mrb_ccontext *cxt)
|
||||
|
||||
if (!cxt) return;
|
||||
if (!p->tree) return;
|
||||
if (node_to_int(p->tree->car) != NODE_SCOPE) return;
|
||||
n0 = n = p->tree->cdr->car;
|
||||
if (!node_type_p(p->tree, NODE_SCOPE)) return;
|
||||
|
||||
/* Extract locals from variable-sized NODE_SCOPE */
|
||||
struct mrb_ast_scope_node *scope = scope_node(p->tree->cdr);
|
||||
n0 = n = scope->locals;
|
||||
while (n) {
|
||||
i++;
|
||||
n = n->cdr;
|
||||
@@ -8805,6 +8818,44 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
|
||||
printf("NODE_KW_REST_ARGS\n");
|
||||
break;
|
||||
|
||||
case NODE_VARIABLE:
|
||||
/* Handle variable-sized nodes wrapped in NODE_VARIABLE */
|
||||
{
|
||||
enum node_type var_type = VAR_NODE_TYPE(tree);
|
||||
switch (var_type) {
|
||||
case NODE_SCOPE:
|
||||
printf("NODE_SCOPE:\n");
|
||||
{
|
||||
struct mrb_ast_scope_node *scope = scope_node(tree);
|
||||
node *n2 = scope->locals;
|
||||
mrb_bool first_lval = TRUE;
|
||||
|
||||
if (n2 && (n2->car || n2->cdr)) {
|
||||
dump_prefix(tree, offset+1);
|
||||
printf("local variables:\n");
|
||||
dump_prefix(tree, offset+2);
|
||||
while (n2) {
|
||||
if (n2->car) {
|
||||
if (!first_lval) printf(", ");
|
||||
printf("%s", mrb_sym_name(mrb, node_to_sym(n2->car)));
|
||||
first_lval = FALSE;
|
||||
}
|
||||
n2 = n2->cdr;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
tree = scope_node(tree)->body;
|
||||
offset++;
|
||||
goto again;
|
||||
|
||||
default:
|
||||
printf("NODE_VARIABLE (unsupported type: %d)\n", var_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("node type: %d (0x%x)\n", nodetype, (unsigned)nodetype);
|
||||
break;
|
||||
@@ -8819,11 +8870,15 @@ void
|
||||
mrb_parser_foreach_top_variable(mrb_state *mrb, struct mrb_parser_state *p, mrb_parser_foreach_top_variable_func *func, void *user)
|
||||
{
|
||||
const mrb_ast_node *n = p->tree;
|
||||
if ((intptr_t)n->car == NODE_SCOPE) {
|
||||
n = n->cdr->car;
|
||||
if (node_type_p((node*)n, NODE_SCOPE)) {
|
||||
/* Extract locals from variable-sized NODE_SCOPE */
|
||||
struct mrb_ast_scope_node *scope = scope_node(n->cdr);
|
||||
n = scope->locals;
|
||||
for (; n; n = n->cdr) {
|
||||
mrb_sym sym = node_to_sym(n->car);
|
||||
if (sym && !func(mrb, sym, user)) break;
|
||||
if (sym != 0) {
|
||||
if (!func(mrb, sym, user)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1236
-1181
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user