mruby-compiler: simplify callargs to use direct pointer casting

Replace variable-sized NODE_VARIABLE wrapper with fixed-size struct
allocation, following the same pattern as new_args(). This eliminates
the need for NODE_VARIABLE checking and uses direct casting instead.

Changes:
- Remove mrb_ast_var_header from callargs struct
- Use parser_palloc instead of parser_alloc_var for fixed-size allocation
- Update all access points to use direct casting: (struct mrb_ast_callargs*)
- Remove unnecessary backward compatibility code for newly introduced NODE_CALLARGS

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-09-18 08:19:33 +09:00
parent 8a88734e49
commit 4f3abb8068
4 changed files with 1286 additions and 1227 deletions
+106 -88
View File
@@ -3470,33 +3470,36 @@ gen_call_var(codegen_scope *s, node *varnode, int val)
}
/* Generate arguments - use gen_values to properly handle splat */
if (args && args->car) {
n = gen_values(s, args->car, VAL, 14);
if (n < 0) { /* variable length (contains splat) */
n = 15;
push();
noop = 1;
}
}
/* Handle keyword arguments if present */
if (CALL_NODE_HAS_KWARGS(call)) {
if (args && args->cdr && args->cdr->car) {
nk = gen_hash(s, args->cdr->car->cdr, VAL, 14);
if (nk < 0) {
nk = 15;
if (args) {
struct mrb_ast_callargs *callargs = (struct mrb_ast_callargs*)args;
if (callargs->regular_args) {
n = gen_values(s, callargs->regular_args, VAL, 14);
if (n < 0) { /* variable length (contains splat) */
n = 15;
push();
noop = 1;
}
noop = 1;
}
}
/* Handle block if present */
if (CALL_NODE_HAS_BLOCK(call)) {
if (args && args->cdr && args->cdr->cdr) {
codegen(s, args->cdr->cdr, VAL);
pop();
blk = 1;
noop = 1;
/* Handle keyword arguments if present */
if (CALL_NODE_HAS_KWARGS(call)) {
if (callargs->keyword_args) {
nk = gen_hash(s, callargs->keyword_args->cdr, VAL, 14);
if (nk < 0) {
nk = 15;
}
noop = 1;
}
}
/* Handle block if present */
if (CALL_NODE_HAS_BLOCK(call)) {
if (callargs->block_arg) {
codegen(s, callargs->block_arg, VAL);
pop();
blk = 1;
noop = 1;
}
}
}
@@ -3609,44 +3612,47 @@ gen_call_assign_var(codegen_scope *s, node *varnode, node *rhs, int sp, int val)
}
/* Generate arguments from original call */
if (args && args->car) {
node *regular_args = args->car;
node *arg_iter = regular_args;
while (arg_iter) {
codegen(s, arg_iter->car, VAL);
n++;
arg_iter = arg_iter->cdr;
if (args) {
struct mrb_ast_callargs *callargs = (struct mrb_ast_callargs*)args;
if (callargs->regular_args) {
node *regular_args = callargs->regular_args;
node *arg_iter = regular_args;
while (arg_iter) {
codegen(s, arg_iter->car, VAL);
n++;
arg_iter = arg_iter->cdr;
}
if (n > 13) { /* leave room for rhs */
pop_n(n);
genop_2(s, OP_ARRAY, cursp(), n);
push();
n = 15;
noop = 1;
}
}
if (n > 13) { /* leave room for rhs */
pop_n(n);
genop_2(s, OP_ARRAY, cursp(), n);
/* Handle keyword arguments if present */
if (callargs->keyword_args) {
node *kwargs = callargs->keyword_args;
if (n == 13 || n == 14) {
pop_n(n);
genop_2(s, OP_ARRAY, cursp(), n);
push();
n = 15;
}
gen_hash(s, kwargs->cdr, VAL, 0);
if (n < 14) {
n++;
}
else {
pop_n(2);
genop_2(s, OP_ARYPUSH, cursp(), 1);
}
push();
n = 15;
noop = 1;
}
}
/* Handle keyword arguments if present */
if (args && args->cdr && args->cdr->car) {
node *kwargs = args->cdr->car;
if (n == 13 || n == 14) {
pop_n(n);
genop_2(s, OP_ARRAY, cursp(), n);
push();
n = 15;
}
gen_hash(s, kwargs->cdr, VAL, 0);
if (n < 14) {
n++;
}
else {
pop_n(2);
genop_2(s, OP_ARYPUSH, cursp(), 1);
}
push();
noop = 1;
}
/* Generate rhs (the assigned value) */
if (rhs) {
codegen(s, rhs, VAL);
@@ -4696,15 +4702,16 @@ gen_yield_var(codegen_scope *s, node *varnode, int val)
if (lv > 0xf) codegen_error(s, "too deep nesting");
push();
if (args) {
if (args->car) {
n = gen_values(s, args->car, VAL, 14);
struct mrb_ast_callargs *callargs = (struct mrb_ast_callargs*)args;
if (callargs->regular_args) {
n = gen_values(s, callargs->regular_args, VAL, 14);
if (n < 0) {
n = sendv = 1;
push();
}
}
if (args->cdr->car) {
nk = gen_hash(s, args->cdr->car->cdr, VAL, 14);
if (callargs->keyword_args) {
nk = gen_hash(s, callargs->keyword_args->cdr, VAL, 14);
if (nk < 0) {
nk = 15;
}
@@ -4735,31 +4742,36 @@ gen_super_var(codegen_scope *s, node *varnode, int val)
if (!s2) break;
}
if (tree) {
node *args = tree->car;
if (args) {
st = n = gen_values(s, args, VAL, 14);
if (n < 0) {
st = 1; n = 15;
/* Handle callargs structure - direct casting like new_args() */
struct mrb_ast_callargs *callargs = (struct mrb_ast_callargs*)tree;
/* Regular arguments */
if (callargs->regular_args) {
st = n = gen_values(s, callargs->regular_args, VAL, 14);
if (n < 0) {
st = 1; n = 15;
push();
}
}
/* Keyword arguments */
if (callargs->keyword_args) {
nk = gen_hash(s, callargs->keyword_args->cdr, VAL, 14);
if (nk < 0) {st++; nk = 15;}
else st += nk*2;
n |= nk<<4;
}
/* Block arguments */
if (callargs->block_arg) {
codegen(s, callargs->block_arg, VAL);
}
else if (s2) gen_blkmove(s, s2->ainfo, lv);
else {
genop_1(s, OP_LOADNIL, cursp());
push();
}
}
/* keyword arguments */
if (tree->cdr->car) {
nk = gen_hash(s, tree->cdr->car->cdr, VAL, 14);
if (nk < 0) {st++; nk = 15;}
else st += nk*2;
n |= nk<<4;
}
/* block arguments */
if (tree->cdr->cdr) {
codegen(s, tree->cdr->cdr, VAL);
}
else if (s2) gen_blkmove(s, s2->ainfo, lv);
else {
genop_1(s, OP_LOADNIL, cursp());
push();
}
}
else {
if (s2) gen_blkmove(s, s2->ainfo, lv);
else {
@@ -5373,16 +5385,22 @@ gen_zsuper_var(codegen_scope *s, node *varnode, int val)
n |= CALL_MAXARGS<<4;
push();
}
/* block argument - tree here is args, so check tree->cdr->cdr */
if (tree && tree->cdr && tree->cdr->cdr) {
push();
codegen(s, tree->cdr->cdr, VAL);
/* block argument - tree here is args, so check for block */
if (tree) {
struct mrb_ast_callargs *callargs = (struct mrb_ast_callargs*)tree;
if (callargs->block_arg) {
push();
codegen(s, callargs->block_arg, VAL);
}
}
}
else {
/* block argument */
if (tree && tree->cdr && tree->cdr->cdr) {
codegen(s, tree->cdr->cdr, VAL);
if (tree) {
struct mrb_ast_callargs *callargs = (struct mrb_ast_callargs*)tree;
if (callargs->block_arg) {
codegen(s, callargs->block_arg, VAL);
}
}
else if (s2) {
gen_blkmove(s, 0, lv);
+13
View File
@@ -60,6 +60,7 @@ enum node_type {
NODE_XSTR,
NODE_REGX,
NODE_DREGX,
NODE_CALLARGS,
NODE_KW_ARG,
NODE_KW_REST_ARGS,
NODE_SPLAT,
@@ -620,9 +621,17 @@ struct mrb_ast_args {
mrb_sym block_arg; /* Block argument symbol (0 = none) */
};
/* Call arguments structure - replaces cons-based new_callargs */
struct mrb_ast_callargs {
struct mrb_ast_node *regular_args; /* Cons list of regular arguments (preserves splat compatibility) */
struct mrb_ast_node *keyword_args; /* Keyword arguments hash node */
struct mrb_ast_node *block_arg; /* Block argument node */
};
/* Advanced node casting macros */
#define rescue_node(n) ((struct mrb_ast_rescue_node*)(n))
#define block_node(n) ((struct mrb_ast_block_node*)(n))
#define callargs_node(n) ((struct mrb_ast_callargs*)(n))
/* Advanced node value access macros */
#define RESCUE_NODE_BODY(n) (rescue_node(n)->body)
@@ -643,6 +652,10 @@ struct mrb_ast_args {
#define ARGS_TAIL_NODE_KWREST(n) (args_tail_node(n)->kwrest)
#define ARGS_TAIL_NODE_BLOCK(n) (args_tail_node(n)->block)
#define CALLARGS_NODE_REGULAR(n) (callargs_node(n)->regular_args)
#define CALLARGS_NODE_KEYWORDS(n) (callargs_node(n)->keyword_args)
#define CALLARGS_NODE_BLOCK(n) (callargs_node(n)->block_arg)
// Group 8: Control Flow Statements
struct mrb_ast_break_node {
struct mrb_ast_var_header hdr;
+30 -16
View File
@@ -728,13 +728,10 @@ new_call(parser_state *p, node *receiver, mrb_sym method, node *args, int pass)
uint8_t has_block = 0;
if (args) {
/* Check for kwargs and block */
if (args->cdr) {
has_kwargs = (args->cdr->car != NULL);
if (args->cdr->cdr) {
has_block = (args->cdr->cdr != NULL);
}
}
/* Handle callargs structure - direct casting like new_args() */
struct mrb_ast_callargs *callargs = (struct mrb_ast_callargs*)args;
has_kwargs = (callargs->keyword_args != NULL);
has_block = (callargs->block_arg != NULL);
}
/* Calculate size needed (fixed size now) */
@@ -770,7 +767,16 @@ new_fcall(parser_state *p, mrb_sym b, node *c)
static node*
new_callargs(parser_state *p, node *a, node *b, node *c)
{
return cons_head(a, cons(b, c));
/* Allocate struct mrb_ast_callargs (fixed size, like new_args) */
struct mrb_ast_callargs *callargs = (struct mrb_ast_callargs*)parser_palloc(p, sizeof(struct mrb_ast_callargs));
/* Initialize members directly */
callargs->regular_args = a; /* Cons list of regular arguments (preserves splat compatibility) */
callargs->keyword_args = b; /* Keyword arguments hash node */
callargs->block_arg = c; /* Block argument node */
/* Return direct cast to node (like new_args) */
return (node*)callargs;
}
/* (:super . c) */
@@ -804,8 +810,12 @@ new_zsuper(parser_state *p)
static node*
new_yield(parser_state *p, node *c)
{
if (c && c->cdr && c->cdr->cdr) {
yyerror(NULL, p, "both block arg and actual block given");
/* Handle callargs structure - direct casting like new_args() */
if (c) {
struct mrb_ast_callargs *callargs = (struct mrb_ast_callargs*)c;
if (callargs->block_arg) {
yyerror(NULL, p, "both block arg and actual block given");
}
}
size_t total_size = sizeof(struct mrb_ast_yield_node);
@@ -1920,10 +1930,12 @@ static void
args_with_block(parser_state *p, node *a, node *b)
{
if (b) {
if (a->cdr && a->cdr->cdr) {
/* Handle callargs structure - direct casting like new_args() */
struct mrb_ast_callargs *callargs = (struct mrb_ast_callargs*)a;
if (callargs->block_arg) {
yyerror(NULL, p, "both block arg and actual block given");
}
a->cdr->cdr = b;
callargs->block_arg = b;
}
}
@@ -2044,13 +2056,15 @@ cond(node *n)
static node*
ret_args(parser_state *p, node *n)
{
if (n->cdr->cdr) {
/* Handle callargs structure - direct casting like new_args() */
struct mrb_ast_callargs *callargs = (struct mrb_ast_callargs*)n;
if (callargs->block_arg) {
yyerror(NULL, p, "block argument should not be given");
return NULL;
}
if (!n->car) return NULL;
if (!n->car->cdr) return n->car->car;
return new_array(p, n->car);
if (!callargs->regular_args) return NULL;
if (!callargs->regular_args->cdr) return callargs->regular_args->car;
return new_array(p, callargs->regular_args);
}
static void
File diff suppressed because it is too large Load Diff