mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-compiler: complete NODE_CLASS, NODE_MODULE, and NODE_SCLASS migration to variable-sized nodes exclusively
- Implement complete variable-sized node generation for all class/module types - gen_class_var(): full class definition with namespace and superclass support - gen_module_var(): complete module definition with proper scope handling - gen_sclass_var(): singleton class with object evaluation and OP_SCLASS - All use scope_body() for proper locals and body management - Update parser to always create variable-sized nodes - Inline helper function logic directly into new_class(), new_module(), new_sclass() - Remove conditional var_nodes_enabled checks for consistency - Eliminate separate _var helper functions - Remove obsolete traditional node handling - Delete codegen_class(), codegen_module(), codegen_sclass() functions - Remove NODE_CLASS, NODE_MODULE, NODE_SCLASS cases from main codegen() switch - Clean up unused function declarations - All 1730 tests pass, class/module/singleton functionality verified Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -4164,98 +4164,6 @@ codegen_postexe(codegen_scope *s, node *tree, int val)
|
||||
codegen(s, tree, NOVAL);
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_class(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
int idx;
|
||||
node *body;
|
||||
|
||||
if (tree->car->car == (node*)0) {
|
||||
gen_load_nil(s, 1);
|
||||
}
|
||||
else if (tree->car->car == (node*)1) {
|
||||
genop_1(s, OP_OCLASS, cursp());
|
||||
push();
|
||||
}
|
||||
else {
|
||||
codegen(s, tree->car->car, VAL);
|
||||
}
|
||||
if (tree->cdr->car) {
|
||||
codegen(s, tree->cdr->car, VAL);
|
||||
}
|
||||
else {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
push();
|
||||
}
|
||||
pop(); pop();
|
||||
idx = new_sym(s, node_to_sym(tree->car->cdr));
|
||||
genop_2(s, OP_CLASS, cursp(), idx);
|
||||
body = tree->cdr->cdr->car;
|
||||
if (node_to_int(body->cdr->car) == NODE_STMTS && body->cdr->cdr == NULL) {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
}
|
||||
else {
|
||||
idx = scope_body(s, body->car, body->cdr, val);
|
||||
genop_2(s, OP_EXEC, cursp(), idx);
|
||||
}
|
||||
if (val) {
|
||||
push();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_module(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (tree->car->car == (node*)0) {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
push();
|
||||
}
|
||||
else if (tree->car->car == (node*)1) {
|
||||
genop_1(s, OP_OCLASS, cursp());
|
||||
push();
|
||||
}
|
||||
else {
|
||||
codegen(s, tree->car->car, VAL);
|
||||
}
|
||||
pop();
|
||||
idx = new_sym(s, node_to_sym(tree->car->cdr));
|
||||
genop_2(s, OP_MODULE, cursp(), idx);
|
||||
if (node_to_int(tree->cdr->car->cdr->car) == NODE_STMTS &&
|
||||
tree->cdr->car->cdr->cdr == NULL) {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
}
|
||||
else {
|
||||
idx = scope_body(s, tree->cdr->car->car, tree->cdr->car->cdr, val);
|
||||
genop_2(s, OP_EXEC, cursp(), idx);
|
||||
}
|
||||
if (val) {
|
||||
push();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_sclass(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
int idx;
|
||||
|
||||
codegen(s, tree->car, VAL);
|
||||
pop();
|
||||
genop_1(s, OP_SCLASS, cursp());
|
||||
if (node_to_int(tree->cdr->car->cdr->car) == NODE_STMTS &&
|
||||
tree->cdr->car->cdr->cdr == NULL) {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
}
|
||||
else {
|
||||
idx = scope_body(s, tree->cdr->car->car, tree->cdr->car->cdr, val);
|
||||
genop_2(s, OP_EXEC, cursp(), idx);
|
||||
}
|
||||
if (val) {
|
||||
push();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
codegen_undef(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
@@ -5043,46 +4951,129 @@ static void
|
||||
gen_class_var(codegen_scope *s, node *varnode, int val)
|
||||
{
|
||||
struct mrb_ast_class_node *class_n = class_node(varnode);
|
||||
node *name = CLASS_NODE_NAME(class_n);
|
||||
node *superclass = CLASS_NODE_SUPERCLASS(class_n);
|
||||
node *body = CLASS_NODE_BODY(class_n);
|
||||
int idx;
|
||||
|
||||
/* For now, generate simple class definition - this can be optimized later */
|
||||
if (body) {
|
||||
codegen(s, body, val);
|
||||
/* Handle class namespace - same logic as codegen_class */
|
||||
if (name->car == (node*)0) {
|
||||
gen_load_nil(s, 1);
|
||||
}
|
||||
else if (val) {
|
||||
else if (name->car == (node*)1) {
|
||||
genop_1(s, OP_OCLASS, cursp());
|
||||
push();
|
||||
}
|
||||
else {
|
||||
codegen(s, name->car, VAL);
|
||||
}
|
||||
|
||||
/* Handle superclass */
|
||||
if (superclass) {
|
||||
codegen(s, superclass, VAL);
|
||||
}
|
||||
else {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
push();
|
||||
}
|
||||
|
||||
pop(); pop();
|
||||
|
||||
/* Create class with name symbol */
|
||||
idx = new_sym(s, node_to_sym(name->cdr));
|
||||
genop_2(s, OP_CLASS, cursp(), idx);
|
||||
|
||||
/* Generate class body - body is scope with locals+body structure */
|
||||
if (node_to_int(body->cdr->car) == NODE_STMTS && body->cdr->cdr == NULL) {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
}
|
||||
else {
|
||||
idx = scope_body(s, body->car, body->cdr, val);
|
||||
genop_2(s, OP_EXEC, cursp(), idx);
|
||||
}
|
||||
|
||||
if (val) {
|
||||
push();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gen_module_var(codegen_scope *s, node *varnode, int val)
|
||||
{
|
||||
struct mrb_ast_module_node *module_n = module_node(varnode);
|
||||
node *name = MODULE_NODE_NAME(module_n);
|
||||
node *body = MODULE_NODE_BODY(module_n);
|
||||
int idx;
|
||||
|
||||
/* For now, generate simple module definition - this can be optimized later */
|
||||
if (body) {
|
||||
codegen(s, body, val);
|
||||
}
|
||||
else if (val) {
|
||||
/* Handle module namespace - same logic as codegen_module */
|
||||
if (name->car == (node*)0) {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
push();
|
||||
}
|
||||
else if (name->car == (node*)1) {
|
||||
genop_1(s, OP_OCLASS, cursp());
|
||||
push();
|
||||
}
|
||||
else {
|
||||
codegen(s, name->car, VAL);
|
||||
}
|
||||
pop();
|
||||
|
||||
/* Create module with name symbol */
|
||||
idx = new_sym(s, node_to_sym(name->cdr));
|
||||
genop_2(s, OP_MODULE, cursp(), idx);
|
||||
|
||||
/* Generate module body - body is scope with locals+body structure */
|
||||
if (node_to_int(body->cdr->car) == NODE_STMTS && body->cdr->cdr == NULL) {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
}
|
||||
else {
|
||||
idx = scope_body(s, body->car, body->cdr, val);
|
||||
genop_2(s, OP_EXEC, cursp(), idx);
|
||||
}
|
||||
|
||||
if (val) {
|
||||
push();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gen_sclass_var(codegen_scope *s, node *varnode, int val)
|
||||
{
|
||||
struct mrb_ast_sclass_node *sclass_n = sclass_node(varnode);
|
||||
node *obj = SCLASS_NODE_OBJ(sclass_n);
|
||||
node *body = SCLASS_NODE_BODY(sclass_n);
|
||||
int idx;
|
||||
|
||||
/* For now, generate simple singleton class definition - this can be optimized later */
|
||||
if (body) {
|
||||
codegen(s, body, val);
|
||||
/* Generate code for the singleton object */
|
||||
codegen(s, obj, VAL);
|
||||
pop();
|
||||
|
||||
/* Enter singleton class scope */
|
||||
genop_1(s, OP_SCLASS, cursp());
|
||||
|
||||
/* Handle singleton class body */
|
||||
if (body && body->cdr) {
|
||||
/* Extract locals and body from the cons structure: (locals . body) */
|
||||
node *locals = body->car;
|
||||
node *body_stmts = body->cdr;
|
||||
|
||||
/* Check for empty body case */
|
||||
if (node_to_int(body_stmts->car) == NODE_STMTS && body_stmts->cdr == NULL) {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
}
|
||||
else {
|
||||
/* Generate proper scope with locals and body */
|
||||
idx = scope_body(s, locals, body_stmts, val);
|
||||
genop_2(s, OP_EXEC, cursp(), idx);
|
||||
}
|
||||
}
|
||||
else if (val) {
|
||||
else {
|
||||
/* No body - load nil */
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
}
|
||||
|
||||
if (val) {
|
||||
push();
|
||||
}
|
||||
}
|
||||
@@ -6502,18 +6493,6 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
codegen_undef(s, tree, val);
|
||||
break;
|
||||
|
||||
case NODE_CLASS:
|
||||
codegen_class(s, tree, val);
|
||||
break;
|
||||
|
||||
case NODE_MODULE:
|
||||
codegen_module(s, tree, val);
|
||||
break;
|
||||
|
||||
case NODE_SCLASS:
|
||||
codegen_sclass(s, tree, val);
|
||||
break;
|
||||
|
||||
case NODE_DEF:
|
||||
codegen_def(s, tree, val);
|
||||
break;
|
||||
|
||||
@@ -609,9 +609,6 @@ new_alias(parser_state *p, mrb_sym a, mrb_sym b)
|
||||
|
||||
/* Forward declarations for variable-sized AST node creation functions */
|
||||
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);
|
||||
static node* new_sclass_var(parser_state *p, node *obj, node *body);
|
||||
static node* new_asgn_var(parser_state *p, node *lhs, node *rhs);
|
||||
static node* new_masgn_var(parser_state *p, node *lhs, node *rhs);
|
||||
static node* new_op_asgn_var(parser_state *p, node *lhs, mrb_sym op, node *rhs);
|
||||
@@ -878,54 +875,8 @@ new_def_var(parser_state *p, mrb_sym name, node *args, node *body)
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)n);
|
||||
}
|
||||
|
||||
/* Variable-sized class definition node creation */
|
||||
static node*
|
||||
new_class_var(parser_state *p, node *name, node *superclass, node *body)
|
||||
{
|
||||
size_t total_size = sizeof(struct mrb_ast_class_node);
|
||||
enum mrb_ast_size_class class = size_to_class(total_size);
|
||||
|
||||
struct mrb_ast_class_node *n = (struct mrb_ast_class_node*)parser_alloc_var(p, total_size, class);
|
||||
|
||||
init_var_header(&n->header, p, NODE_CLASS, class);
|
||||
n->name = name;
|
||||
n->superclass = superclass;
|
||||
n->body = body;
|
||||
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)n);
|
||||
}
|
||||
|
||||
/* Variable-sized module definition node creation */
|
||||
static node*
|
||||
new_module_var(parser_state *p, node *name, node *body)
|
||||
{
|
||||
size_t total_size = sizeof(struct mrb_ast_module_node);
|
||||
enum mrb_ast_size_class class = size_to_class(total_size);
|
||||
|
||||
struct mrb_ast_module_node *n = (struct mrb_ast_module_node*)parser_alloc_var(p, total_size, class);
|
||||
|
||||
init_var_header(&n->header, p, NODE_MODULE, class);
|
||||
n->name = name;
|
||||
n->body = body;
|
||||
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)n);
|
||||
}
|
||||
|
||||
/* Variable-sized singleton class definition node creation */
|
||||
static node*
|
||||
new_sclass_var(parser_state *p, node *obj, node *body)
|
||||
{
|
||||
size_t total_size = sizeof(struct mrb_ast_sclass_node);
|
||||
enum mrb_ast_size_class class = size_to_class(total_size);
|
||||
|
||||
struct mrb_ast_sclass_node *n = (struct mrb_ast_sclass_node*)parser_alloc_var(p, total_size, class);
|
||||
|
||||
init_var_header(&n->header, p, NODE_SCLASS, class);
|
||||
n->obj = obj;
|
||||
n->body = body;
|
||||
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)n);
|
||||
}
|
||||
|
||||
/* Variable-sized assignment node creation */
|
||||
static node*
|
||||
@@ -1504,10 +1455,18 @@ static node*
|
||||
new_class(parser_state *p, node *c, node *s, node *b)
|
||||
{
|
||||
void_expr_error(p, s);
|
||||
if (p->var_nodes_enabled) {
|
||||
return new_class_var(p, c, s, cons(locals_node(p), b));
|
||||
}
|
||||
return list4((node*)NODE_CLASS, c, s, cons(locals_node(p), b));
|
||||
|
||||
size_t total_size = sizeof(struct mrb_ast_class_node);
|
||||
enum mrb_ast_size_class class = size_to_class(total_size);
|
||||
|
||||
struct mrb_ast_class_node *n = (struct mrb_ast_class_node*)parser_alloc_var(p, total_size, class);
|
||||
|
||||
init_var_header(&n->header, p, NODE_CLASS, class);
|
||||
n->name = c;
|
||||
n->superclass = s;
|
||||
n->body = cons(locals_node(p), b);
|
||||
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)n);
|
||||
}
|
||||
|
||||
/* (:sclass obj body) */
|
||||
@@ -1515,20 +1474,32 @@ static node*
|
||||
new_sclass(parser_state *p, node *o, node *b)
|
||||
{
|
||||
void_expr_error(p, o);
|
||||
if (p->var_nodes_enabled) {
|
||||
return new_sclass_var(p, o, cons(locals_node(p), b));
|
||||
}
|
||||
return list3((node*)NODE_SCLASS, o, cons(locals_node(p), b));
|
||||
|
||||
size_t total_size = sizeof(struct mrb_ast_sclass_node);
|
||||
enum mrb_ast_size_class class = size_to_class(total_size);
|
||||
struct mrb_ast_sclass_node *n = (struct mrb_ast_sclass_node*)parser_alloc_var(p, total_size, class);
|
||||
|
||||
init_var_header(&n->header, p, NODE_SCLASS, class);
|
||||
n->obj = o;
|
||||
n->body = cons(locals_node(p), b);
|
||||
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)n);
|
||||
}
|
||||
|
||||
/* (:module module body) */
|
||||
static node*
|
||||
new_module(parser_state *p, node *m, node *b)
|
||||
{
|
||||
if (p->var_nodes_enabled) {
|
||||
return new_module_var(p, m, cons(locals_node(p), b));
|
||||
}
|
||||
return list3((node*)NODE_MODULE, m, cons(locals_node(p), b));
|
||||
size_t total_size = sizeof(struct mrb_ast_module_node);
|
||||
enum mrb_ast_size_class class = size_to_class(total_size);
|
||||
|
||||
struct mrb_ast_module_node *n = (struct mrb_ast_module_node*)parser_alloc_var(p, total_size, class);
|
||||
|
||||
init_var_header(&n->header, p, NODE_MODULE, class);
|
||||
n->name = m;
|
||||
n->body = cons(locals_node(p), b);
|
||||
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)n);
|
||||
}
|
||||
|
||||
/* (:def m lv (arg . body)) */
|
||||
|
||||
+1184
-1213
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user