mruby-compiler: refactor class/module/singleton class generation using helper functions

Unified gen_class_var, gen_module_var, and gen_sclass_var functions by extracting
common patterns into two helper functions:
- gen_class_body() handles body generation for all three types
- gen_namespace() handles namespace/parent setup for class and module

This refactoring eliminates approximately 40 lines of duplicated code while
maintaining identical functionality and bytecode generation patterns.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-09-09 10:09:55 +09:00
parent 6e68e9f5e2
commit 5e130f5381
+96 -102
View File
@@ -4947,112 +4947,12 @@ gen_def_var(codegen_scope *s, node *varnode, int val)
}
}
/* Helper function for generating class/module/singleton class body */
static void
gen_class_var(codegen_scope *s, node *varnode, int val)
gen_class_body(codegen_scope *s, node *body, 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;
/* Handle class namespace - same logic as codegen_class */
if (name->car == (node*)0) {
gen_load_nil(s, 1);
}
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;
/* 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;
/* 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;
@@ -5072,6 +4972,100 @@ gen_sclass_var(codegen_scope *s, node *varnode, int val)
/* No body - load nil */
genop_1(s, OP_LOADNIL, cursp());
}
}
/* Helper function for generating namespace/parent for class/module */
static void
gen_namespace(codegen_scope *s, node *name)
{
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);
}
}
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;
/* Handle class namespace */
gen_namespace(s, name);
/* 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 */
gen_class_body(s, body, val);
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;
/* Handle module namespace */
gen_namespace(s, name);
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 */
gen_class_body(s, body, val);
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);
/* Generate code for the singleton object */
codegen(s, obj, VAL);
pop();
/* Enter singleton class scope */
genop_1(s, OP_SCLASS, cursp());
/* Generate singleton class body */
gen_class_body(s, body, val);
if (val) {
push();