mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-compiler: convert NODE_SUPER and NODE_ZSUPER to always use variable-sized nodes
- update NODE_ZSUPER to use mrb_ast_super_node instead of empty mrb_ast_zsuper_node - convert new_super and new_zsuper to always create variable-sized nodes - update call_with_block to handle NODE_SUPER/NODE_ZSUPER wrapped in NODE_VARIABLE - inline codegen_super and codegen_zsuper into their gen_*_var functions - remove traditional NODE_SUPER and NODE_ZSUPER cases from codegen Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -4791,110 +4791,6 @@ codegen_block_arg(codegen_scope *s, node *tree, int val)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
codegen_super(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
codegen_scope *s2 = s;
|
||||
int lv = 0;
|
||||
int n = 0, nk = 0, st = 0;
|
||||
|
||||
push();
|
||||
while (!s2->mscope) {
|
||||
lv++;
|
||||
s2 = s2->prev;
|
||||
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;
|
||||
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 {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
push();
|
||||
}
|
||||
}
|
||||
st++;
|
||||
pop_n(st+1);
|
||||
genop_2(s, OP_SUPER, cursp(), n);
|
||||
if (val) push();
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_zsuper(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
codegen_scope *s2 = s;
|
||||
int lv = 0;
|
||||
uint16_t ainfo = 0;
|
||||
int n = CALL_MAXARGS;
|
||||
int sp = cursp();
|
||||
|
||||
push(); /* room for receiver */
|
||||
while (!s2->mscope) {
|
||||
lv++;
|
||||
s2 = s2->prev;
|
||||
if (!s2) break;
|
||||
}
|
||||
if (s2 && s2->ainfo > 0) {
|
||||
ainfo = s2->ainfo;
|
||||
}
|
||||
if (lv > 0xf) codegen_error(s, "too deep nesting");
|
||||
if (ainfo > 0) {
|
||||
genop_2S(s, OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf));
|
||||
push(); push(); push(); /* ARGARY pushes 3 values at most */
|
||||
pop(); pop(); pop();
|
||||
/* keyword arguments */
|
||||
if (ainfo & 0x1) {
|
||||
n |= CALL_MAXARGS<<4;
|
||||
push();
|
||||
}
|
||||
/* block argument */
|
||||
if (tree && tree->cdr && tree->cdr->cdr) {
|
||||
push();
|
||||
codegen(s, tree->cdr->cdr, VAL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* block argument */
|
||||
if (tree && tree->cdr && tree->cdr->cdr) {
|
||||
codegen(s, tree->cdr->cdr, VAL);
|
||||
}
|
||||
else if (s2) {
|
||||
gen_blkmove(s, 0, lv);
|
||||
}
|
||||
else {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
}
|
||||
n = 0;
|
||||
}
|
||||
s->sp = sp;
|
||||
genop_2(s, OP_SUPER, cursp(), n);
|
||||
if (val) push();
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_yield(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
@@ -5330,11 +5226,8 @@ gen_asgn_var(codegen_scope *s, node *varnode, int val)
|
||||
static void
|
||||
gen_masgn_var(codegen_scope *s, node *varnode, int val)
|
||||
{
|
||||
struct mrb_ast_masgn_node *masgn_n = masgn_node(varnode);
|
||||
node *rhs = MASGN_NODE_RHS(masgn_n);
|
||||
|
||||
/* Simplified multiple assignment codegen */
|
||||
/* For now, just generate RHS value and then handle LHS assignment */
|
||||
node *rhs = MASGN_NODE_RHS(varnode);
|
||||
if (rhs) {
|
||||
codegen(s, rhs, VAL);
|
||||
}
|
||||
@@ -5433,10 +5326,55 @@ static void
|
||||
gen_super_var(codegen_scope *s, node *varnode, int val)
|
||||
{
|
||||
struct mrb_ast_super_node *super_n = super_node(varnode);
|
||||
node *args = SUPER_NODE_ARGS(super_n);
|
||||
node *tree = SUPER_NODE_ARGS(super_n);
|
||||
|
||||
/* Use traditional super codegen logic */
|
||||
codegen_super(s, args, val);
|
||||
codegen_scope *s2 = s;
|
||||
int lv = 0;
|
||||
int n = 0, nk = 0, st = 0;
|
||||
|
||||
push();
|
||||
while (!s2->mscope) {
|
||||
lv++;
|
||||
s2 = s2->prev;
|
||||
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;
|
||||
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 {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
push();
|
||||
}
|
||||
}
|
||||
st++;
|
||||
pop_n(st+1);
|
||||
genop_2(s, OP_SUPER, cursp(), n);
|
||||
if (val) push();
|
||||
}
|
||||
|
||||
/* Variable-sized literal node generation functions */
|
||||
@@ -5852,12 +5790,57 @@ gen_fcall_var(codegen_scope *s, node *varnode, int val)
|
||||
static void
|
||||
gen_zsuper_var(codegen_scope *s, node *varnode, int val)
|
||||
{
|
||||
(void)varnode; // suppress unused warning
|
||||
// Create a simple stack structure
|
||||
struct mrb_ast_node stack_node;
|
||||
stack_node.car = (node*)NODE_ZSUPER;
|
||||
stack_node.cdr = NULL;
|
||||
codegen_zsuper(s, &stack_node, val);
|
||||
/* NODE_ZSUPER now uses mrb_ast_super_node, which may have args */
|
||||
struct mrb_ast_super_node *zsuper_n = super_node(varnode);
|
||||
node *tree = zsuper_n->args; /* May be NULL or args added by call_with_block */
|
||||
|
||||
codegen_scope *s2 = s;
|
||||
int lv = 0;
|
||||
uint16_t ainfo = 0;
|
||||
int n = CALL_MAXARGS;
|
||||
int sp = cursp();
|
||||
|
||||
push(); /* room for receiver */
|
||||
while (!s2->mscope) {
|
||||
lv++;
|
||||
s2 = s2->prev;
|
||||
if (!s2) break;
|
||||
}
|
||||
if (s2 && s2->ainfo > 0) {
|
||||
ainfo = s2->ainfo;
|
||||
}
|
||||
if (lv > 0xf) codegen_error(s, "too deep nesting");
|
||||
if (ainfo > 0) {
|
||||
genop_2S(s, OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf));
|
||||
push(); push(); push(); /* ARGARY pushes 3 values at most */
|
||||
pop(); pop(); pop();
|
||||
/* keyword arguments */
|
||||
if (ainfo & 0x1) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* block argument */
|
||||
if (tree && tree->cdr && tree->cdr->cdr) {
|
||||
codegen(s, tree->cdr->cdr, VAL);
|
||||
}
|
||||
else if (s2) {
|
||||
gen_blkmove(s, 0, lv);
|
||||
}
|
||||
else {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
}
|
||||
n = 0;
|
||||
}
|
||||
s->sp = sp;
|
||||
genop_2(s, OP_SUPER, cursp(), n);
|
||||
if (val) push();
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -6490,13 +6473,6 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
codegen_op_asgn(s, tree, val);
|
||||
break;
|
||||
|
||||
case NODE_SUPER:
|
||||
codegen_super(s, tree, val);
|
||||
break;
|
||||
|
||||
case NODE_ZSUPER:
|
||||
codegen_zsuper(s, tree, val);
|
||||
break;
|
||||
|
||||
case NODE_RETURN:
|
||||
codegen_return(s, tree, val);
|
||||
|
||||
@@ -804,9 +804,6 @@ struct mrb_ast_fcall_node {
|
||||
struct mrb_ast_node *args;
|
||||
};
|
||||
|
||||
struct mrb_ast_zsuper_node {
|
||||
struct mrb_ast_var_header hdr;
|
||||
};
|
||||
|
||||
struct mrb_ast_lambda_node {
|
||||
struct mrb_ast_var_header hdr;
|
||||
@@ -920,7 +917,7 @@ struct mrb_ast_sdef_node {
|
||||
};
|
||||
|
||||
#define fcall_node(n) ((struct mrb_ast_fcall_node*)(n))
|
||||
#define zsuper_node(n) ((struct mrb_ast_zsuper_node*)(n))
|
||||
#define zsuper_node(n) ((struct mrb_ast_super_node*)(n))
|
||||
#define lambda_node(n) ((struct mrb_ast_lambda_node*)(n))
|
||||
#define zarray_node(n) ((struct mrb_ast_zarray_node*)(n))
|
||||
#define kw_hash_node(n) ((struct mrb_ast_kw_hash_node*)(n))
|
||||
|
||||
@@ -612,7 +612,6 @@ static node* new_and_var(parser_state *p, node *left, node *right);
|
||||
static node* new_or_var(parser_state *p, node *left, node *right);
|
||||
static node* new_return_var(parser_state *p, node *args);
|
||||
static node* new_yield_var(parser_state *p, node *args);
|
||||
static node* new_super_var(parser_state *p, node *args);
|
||||
static node* new_float_var(parser_state *p, const char *value);
|
||||
|
||||
/* (:if cond then else) */
|
||||
@@ -1181,20 +1180,6 @@ new_yield_var(parser_state *p, node *args)
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)n);
|
||||
}
|
||||
|
||||
static node*
|
||||
new_super_var(parser_state *p, node *args)
|
||||
{
|
||||
size_t total_size = sizeof(struct mrb_ast_super_node);
|
||||
enum mrb_ast_size_class class = size_to_class(total_size);
|
||||
|
||||
struct mrb_ast_super_node *n = (struct mrb_ast_super_node*)parser_alloc_var(p, total_size, class);
|
||||
|
||||
init_var_header(&n->header, p, NODE_SUPER, class);
|
||||
n->args = args;
|
||||
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)n);
|
||||
}
|
||||
|
||||
/* Variable-sized literal node creation functions */
|
||||
|
||||
|
||||
@@ -1335,21 +1320,27 @@ new_callargs(parser_state *p, node *a, node *b, node *c)
|
||||
static node*
|
||||
new_super(parser_state *p, node *c)
|
||||
{
|
||||
if (p->var_nodes_enabled) {
|
||||
return new_super_var(p, c);
|
||||
}
|
||||
return cons_head((node*)NODE_SUPER, c);
|
||||
size_t total_size = sizeof(struct mrb_ast_super_node);
|
||||
enum mrb_ast_size_class class = size_to_class(total_size);
|
||||
|
||||
struct mrb_ast_super_node *n = (struct mrb_ast_super_node*)parser_alloc_var(p, total_size, class);
|
||||
|
||||
init_var_header(&n->header, p, NODE_SUPER, class);
|
||||
n->args = c;
|
||||
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)n);
|
||||
}
|
||||
|
||||
/* (:zsuper) */
|
||||
static node*
|
||||
new_zsuper(parser_state *p)
|
||||
{
|
||||
size_t total_size = sizeof(struct mrb_ast_zsuper_node);
|
||||
size_t total_size = sizeof(struct mrb_ast_super_node);
|
||||
enum mrb_ast_size_class class = size_to_class(total_size);
|
||||
struct mrb_ast_zsuper_node *zsuper_node = (struct mrb_ast_zsuper_node*)parser_alloc_var(p, total_size, class);
|
||||
init_var_header(&zsuper_node->hdr, p, NODE_ZSUPER, class);
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)zsuper_node);
|
||||
struct mrb_ast_super_node *n = (struct mrb_ast_super_node*)parser_alloc_var(p, total_size, class);
|
||||
init_var_header(&n->header, p, NODE_ZSUPER, class);
|
||||
n->args = NULL; /* zsuper initially has no args, but may be added by call_with_block */
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)n);
|
||||
}
|
||||
|
||||
/* (:yield . c) */
|
||||
@@ -2317,10 +2308,23 @@ call_with_block(parser_state *p, node *a, node *b)
|
||||
node *n;
|
||||
|
||||
switch (node_to_type(a->car)) {
|
||||
case NODE_SUPER:
|
||||
case NODE_ZSUPER:
|
||||
if (!a->cdr) a->cdr = new_callargs(p, 0, 0, b);
|
||||
else args_with_block(p, a->cdr, b);
|
||||
case NODE_VARIABLE:
|
||||
/* Handle variable-sized nodes wrapped in NODE_VARIABLE */
|
||||
{
|
||||
enum node_type var_type = VAR_NODE_TYPE(a->cdr);
|
||||
if (var_type == NODE_SUPER || var_type == NODE_ZSUPER) {
|
||||
/* For variable-sized super/zsuper nodes, we need to update the args field directly */
|
||||
struct mrb_ast_super_node *super_n = super_node(a->cdr);
|
||||
if (!super_n->args) {
|
||||
super_n->args = new_callargs(p, 0, 0, b);
|
||||
}
|
||||
else {
|
||||
args_with_block(p, super_n->args, b);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* For other variable-sized nodes, fall through to default */
|
||||
break;
|
||||
case NODE_CALL:
|
||||
case NODE_FCALL:
|
||||
|
||||
+1111
-1107
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user