mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-compiler: add NODE_MARG for parameter destructuring
Implement NODE_MARG as a dedicated node type for parameter destructuring to separate it architecturally from general multiple assignment (NODE_MASGN). This resolves crashes when dumping parameter destructuring nodes and improves code organization. Key changes: - Add NODE_MARG to node type enum - Create new_marg() function for parameter destructuring - Consolidate new_masgn() and new_marg() using shared helper - Fix parameter context checks in lambda_body() to use NODE_MARG only - Enable shared dumping logic for both NODE_MASGN and NODE_MARG - Optimize memory management with immediate RHS cleanup - Combine gen_assignment() cases for code deduplication 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2471,7 +2471,7 @@ lambda_body(codegen_scope *s, node *locals, struct mrb_ast_args *args, node *bod
|
||||
node *n = margs;
|
||||
pos = 1; /* Start from register 1 (after self). */
|
||||
while (n) {
|
||||
if (get_node_type(n->car) == NODE_MASGN) { /* If the argument is a mass assignment (e.g., |(a,b)| ). */
|
||||
if (get_node_type(n->car) == NODE_MARG) { /* If the argument is a mass assignment (e.g., |(a,b)| ). */
|
||||
struct mrb_ast_masgn_node *masgn_n = (struct mrb_ast_masgn_node*)n->car;
|
||||
/* Use dedicated parameter destructuring logic instead of general codegen_masgn */
|
||||
int nn = 0;
|
||||
@@ -2498,7 +2498,7 @@ lambda_body(codegen_scope *s, node *locals, struct mrb_ast_args *args, node *bod
|
||||
node *n = pargs;
|
||||
pos = ma+oa+ra+1; /* Calculate starting register for post-mandatory args. */
|
||||
while (n) {
|
||||
if (get_node_type(n->car) == NODE_MASGN) { /* If argument is a mass assignment. */
|
||||
if (get_node_type(n->car) == NODE_MARG) { /* If argument is a mass assignment. */
|
||||
struct mrb_ast_masgn_node *masgn_n = (struct mrb_ast_masgn_node*)n->car;
|
||||
/* Use dedicated parameter destructuring logic instead of general codegen_masgn */
|
||||
int nn = 0;
|
||||
@@ -2933,6 +2933,8 @@ gen_assignment(codegen_scope *s, node *tree, node *rhs, int sp, int val)
|
||||
gen_xvar_assignment(s, tree, rhs, sp, val, OP_SETCONST);
|
||||
break;
|
||||
case NODE_MASGN:
|
||||
case NODE_MARG:
|
||||
/* Multiple assignment: expressions (MASGN) and parameter destructuring (MARG) */
|
||||
codegen_masgn(s, tree, rhs, sp, val);
|
||||
return;
|
||||
case NODE_LVAR:
|
||||
@@ -5667,6 +5669,11 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
codegen_masgn(s, tree, NULL, 0, val);
|
||||
break;
|
||||
|
||||
case NODE_MARG:
|
||||
/* Parameter destructuring should be handled inline by lambda_body */
|
||||
/* This case should not be reached in normal execution */
|
||||
break;
|
||||
|
||||
case NODE_OP_ASGN:
|
||||
codegen_op_asgn(s, tree, val);
|
||||
break;
|
||||
|
||||
@@ -29,6 +29,7 @@ enum node_type {
|
||||
NODE_OR,
|
||||
NODE_NOT,
|
||||
NODE_MASGN,
|
||||
NODE_MARG,
|
||||
NODE_ASGN,
|
||||
NODE_OP_ASGN,
|
||||
NODE_CALL,
|
||||
|
||||
@@ -1034,7 +1034,7 @@ static void
|
||||
local_add_margs(parser_state *p, node *n)
|
||||
{
|
||||
while (n) {
|
||||
if (get_node_type(n->car) == NODE_MASGN) {
|
||||
if (get_node_type(n->car) == NODE_MARG) {
|
||||
struct mrb_ast_masgn_node *masgn_n = (struct mrb_ast_masgn_node*)n->car;
|
||||
node *rhs = masgn_n->rhs;
|
||||
|
||||
@@ -1045,6 +1045,8 @@ local_add_margs(parser_state *p, node *n)
|
||||
local_add_f(p, node_to_sym(t->car));
|
||||
t = t->cdr;
|
||||
}
|
||||
/* Clear cons list RHS immediately after use */
|
||||
masgn_n->rhs = NULL;
|
||||
}
|
||||
|
||||
/* Process nested destructuring in lhs components */
|
||||
@@ -1059,6 +1061,7 @@ local_add_margs(parser_state *p, node *n)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
local_add_lv(parser_state *p, node *lv)
|
||||
{
|
||||
@@ -1255,14 +1258,12 @@ new_asgn(parser_state *p, node *a, node *b)
|
||||
return (node*)n;
|
||||
}
|
||||
|
||||
/* (:masgn mlhs=(pre rest post) mrhs) */
|
||||
/* Helper function to create MASGN/MARG nodes */
|
||||
static node*
|
||||
new_masgn(parser_state *p, node *a, node *b)
|
||||
new_masgn_helper(parser_state *p, node *a, node *b, enum node_type node_type)
|
||||
{
|
||||
void_expr_error(p, b);
|
||||
|
||||
struct mrb_ast_masgn_node *n = (struct mrb_ast_masgn_node*)parser_palloc(p, sizeof(struct mrb_ast_masgn_node));
|
||||
init_var_header(&n->header, p, NODE_MASGN);
|
||||
init_var_header(&n->header, p, node_type);
|
||||
|
||||
/* Extract pre, rest, post from cons list structure (a b c) */
|
||||
if (a) {
|
||||
@@ -1294,38 +1295,19 @@ new_masgn(parser_state *p, node *a, node *b)
|
||||
return (node*)n;
|
||||
}
|
||||
|
||||
/* (:masgn mlhs mrhs) no check */
|
||||
/* (:masgn mlhs=(pre rest post) mrhs) */
|
||||
static node*
|
||||
new_masgn_param(parser_state *p, node *a, node *b)
|
||||
new_masgn(parser_state *p, node *a, node *b)
|
||||
{
|
||||
struct mrb_ast_masgn_node *n = (struct mrb_ast_masgn_node*)parser_palloc(p, sizeof(struct mrb_ast_masgn_node));
|
||||
init_var_header(&n->header, p, NODE_MASGN);
|
||||
void_expr_error(p, b);
|
||||
return new_masgn_helper(p, a, b, NODE_MASGN);
|
||||
}
|
||||
|
||||
/* Extract pre, rest, post from cons list structure (a b c) */
|
||||
if (a) {
|
||||
n->pre = a->car; /* Pre-splat variables */
|
||||
if (a->cdr) {
|
||||
n->rest = a->cdr->car; /* Splat variable (or -1 for anonymous) */
|
||||
if (a->cdr->cdr) {
|
||||
n->post = a->cdr->cdr->car; /* Post-splat variables */
|
||||
}
|
||||
else {
|
||||
n->post = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
n->rest = NULL;
|
||||
n->post = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
n->pre = NULL;
|
||||
n->rest = NULL;
|
||||
n->post = NULL;
|
||||
}
|
||||
n->rhs = b;
|
||||
|
||||
return (node*)n;
|
||||
/* (:marg mlhs mrhs) no check - for parameter destructuring */
|
||||
static node*
|
||||
new_marg(parser_state *p, node *a)
|
||||
{
|
||||
return new_masgn_helper(p, a, p->locals->car, NODE_MARG);
|
||||
}
|
||||
|
||||
/* (:asgn lhs rhs) */
|
||||
@@ -4398,7 +4380,7 @@ f_arg_item : f_norm_arg
|
||||
}
|
||||
f_margs rparen
|
||||
{
|
||||
$$ = new_masgn_param(p, $3, p->locals->car);
|
||||
$$ = new_marg(p, $3);
|
||||
local_resume(p, $<nd>2);
|
||||
local_add_f(p, 0);
|
||||
}
|
||||
@@ -7900,7 +7882,8 @@ dump_node(mrb_state *mrb, node *tree, int offset)
|
||||
break;
|
||||
|
||||
case NODE_MASGN:
|
||||
printf("NODE_MASGN:\n");
|
||||
case NODE_MARG:
|
||||
printf("%s:\n", get_node_type(tree) == NODE_MASGN ? "NODE_MASGN" : "NODE_MARG");
|
||||
/* Handle pre-splat variables */
|
||||
if (MASGN_NODE_PRE(tree)) {
|
||||
dump_prefix(offset+1, lineno);
|
||||
@@ -8441,9 +8424,8 @@ dump_node(mrb_state *mrb, node *tree, int offset)
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Fallback: treat as a traditional cons-list and recursively dump */
|
||||
printf("unknown node type %d (0x%x), dumping as list:\n", nodetype, (unsigned)nodetype);
|
||||
dump_recur(mrb, tree, offset+1);
|
||||
/* Fallback: unknown node type - skip like codegen.c does */
|
||||
printf("unknown node type %d (0x%x)\n", nodetype, (unsigned)nodetype);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
+1234
-1252
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user