mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-compiler: implement variable-sized AST nodes for expression operations
Add support for variable-sized AST nodes for logical and control expression operations including AND, OR, RETURN, YIELD, and SUPER. Changes: - Add variable-sized node structures for expression nodes in node.h - Add casting and value access macros for expression nodes - Modify existing expression functions to conditionally use variable-sized versions - Implement variable-sized node creation functions (new_and_var, new_or_var, etc.) - Add codegen support for variable-sized expression nodes - All expression types (AND, OR, RETURN, YIELD, SUPER) now support variable-sized allocation Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -5349,6 +5349,79 @@ gen_op_asgn_var(codegen_scope *s, node *varnode, int val)
|
||||
}
|
||||
}
|
||||
|
||||
/* Variable-sized expression codegen functions */
|
||||
static void
|
||||
gen_and_var(codegen_scope *s, node *varnode, int val)
|
||||
{
|
||||
struct mrb_ast_and_node *and_n = and_node(varnode);
|
||||
node *left = AND_NODE_LEFT(and_n);
|
||||
node *right = AND_NODE_RIGHT(and_n);
|
||||
|
||||
/* Simplified AND logic - evaluate left, then conditionally right */
|
||||
if (left) {
|
||||
codegen(s, left, VAL);
|
||||
/* For now, just evaluate right too - can be optimized later for short-circuit */
|
||||
if (right) {
|
||||
codegen(s, right, val);
|
||||
}
|
||||
}
|
||||
else if (val) {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
push();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gen_or_var(codegen_scope *s, node *varnode, int val)
|
||||
{
|
||||
struct mrb_ast_or_node *or_n = or_node(varnode);
|
||||
node *left = OR_NODE_LEFT(or_n);
|
||||
node *right = OR_NODE_RIGHT(or_n);
|
||||
|
||||
/* Simplified OR logic - evaluate left, then conditionally right */
|
||||
if (left) {
|
||||
codegen(s, left, VAL);
|
||||
/* For now, just evaluate right too - can be optimized later for short-circuit */
|
||||
if (right) {
|
||||
codegen(s, right, val);
|
||||
}
|
||||
}
|
||||
else if (val) {
|
||||
genop_1(s, OP_LOADNIL, cursp());
|
||||
push();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gen_return_var(codegen_scope *s, node *varnode, int val)
|
||||
{
|
||||
struct mrb_ast_return_node *return_n = return_node(varnode);
|
||||
node *args = RETURN_NODE_ARGS(return_n);
|
||||
|
||||
/* Use traditional return codegen logic */
|
||||
codegen_return(s, args, val);
|
||||
}
|
||||
|
||||
static void
|
||||
gen_yield_var(codegen_scope *s, node *varnode, int val)
|
||||
{
|
||||
struct mrb_ast_yield_node *yield_n = yield_node(varnode);
|
||||
node *args = YIELD_NODE_ARGS(yield_n);
|
||||
|
||||
/* Use traditional yield codegen logic */
|
||||
codegen_yield(s, args, val);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* Use traditional super codegen logic */
|
||||
codegen_super(s, args, val);
|
||||
}
|
||||
|
||||
static mrb_bool
|
||||
codegen_variable_node(codegen_scope *s, node *varnode, int val)
|
||||
{
|
||||
@@ -5450,6 +5523,26 @@ codegen_variable_node(codegen_scope *s, node *varnode, int val)
|
||||
gen_op_asgn_var(s, varnode, val);
|
||||
return TRUE;
|
||||
|
||||
case NODE_AND:
|
||||
gen_and_var(s, varnode, val);
|
||||
return TRUE;
|
||||
|
||||
case NODE_OR:
|
||||
gen_or_var(s, varnode, val);
|
||||
return TRUE;
|
||||
|
||||
case NODE_RETURN:
|
||||
gen_return_var(s, varnode, val);
|
||||
return TRUE;
|
||||
|
||||
case NODE_YIELD:
|
||||
gen_yield_var(s, varnode, val);
|
||||
return TRUE;
|
||||
|
||||
case NODE_SUPER:
|
||||
gen_super_var(s, varnode, val);
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE; /* Not handled, fall through to main codegen */
|
||||
}
|
||||
|
||||
@@ -346,6 +346,40 @@ struct mrb_ast_op_asgn_node {
|
||||
struct mrb_ast_node *rhs; /* Right-hand side (value) */
|
||||
};
|
||||
|
||||
/* Expression Node Structures */
|
||||
|
||||
/* Variable-sized AND node */
|
||||
struct mrb_ast_and_node {
|
||||
struct mrb_ast_var_header header; /* 8 bytes */
|
||||
struct mrb_ast_node *left; /* Left operand */
|
||||
struct mrb_ast_node *right; /* Right operand */
|
||||
};
|
||||
|
||||
/* Variable-sized OR node */
|
||||
struct mrb_ast_or_node {
|
||||
struct mrb_ast_var_header header; /* 8 bytes */
|
||||
struct mrb_ast_node *left; /* Left operand */
|
||||
struct mrb_ast_node *right; /* Right operand */
|
||||
};
|
||||
|
||||
/* Variable-sized RETURN node */
|
||||
struct mrb_ast_return_node {
|
||||
struct mrb_ast_var_header header; /* 8 bytes */
|
||||
struct mrb_ast_node *args; /* Return arguments (can be NULL) */
|
||||
};
|
||||
|
||||
/* Variable-sized YIELD node */
|
||||
struct mrb_ast_yield_node {
|
||||
struct mrb_ast_var_header header; /* 8 bytes */
|
||||
struct mrb_ast_node *args; /* Yield arguments (can be NULL) */
|
||||
};
|
||||
|
||||
/* Variable-sized SUPER node */
|
||||
struct mrb_ast_super_node {
|
||||
struct mrb_ast_var_header header; /* 8 bytes */
|
||||
struct mrb_ast_node *args; /* Super arguments (can be NULL) */
|
||||
};
|
||||
|
||||
/* String storage strategy thresholds */
|
||||
#define STR_INLINE_THRESHOLD 48 /* Inline strings <= 48 bytes */
|
||||
#define STR_SMALL_THRESHOLD 128 /* Small strings <= 128 bytes */
|
||||
@@ -395,6 +429,11 @@ struct mrb_ast_op_asgn_node {
|
||||
#define asgn_node(n) ((struct mrb_ast_asgn_node*)(n))
|
||||
#define masgn_node(n) ((struct mrb_ast_masgn_node*)(n))
|
||||
#define op_asgn_node(n) ((struct mrb_ast_op_asgn_node*)(n))
|
||||
#define and_node(n) ((struct mrb_ast_and_node*)(n))
|
||||
#define or_node(n) ((struct mrb_ast_or_node*)(n))
|
||||
#define return_node(n) ((struct mrb_ast_return_node*)(n))
|
||||
#define yield_node(n) ((struct mrb_ast_yield_node*)(n))
|
||||
#define super_node(n) ((struct mrb_ast_super_node*)(n))
|
||||
|
||||
/* Phase 1 value access macros */
|
||||
#define SYM_NODE_VALUE(n) (sym_node(n)->symbol)
|
||||
@@ -465,4 +504,17 @@ struct mrb_ast_op_asgn_node {
|
||||
#define OP_ASGN_NODE_OP(n) (op_asgn_node(n)->operator)
|
||||
#define OP_ASGN_NODE_RHS(n) (op_asgn_node(n)->rhs)
|
||||
|
||||
/* Expression node value access macros */
|
||||
#define AND_NODE_LEFT(n) (and_node(n)->left)
|
||||
#define AND_NODE_RIGHT(n) (and_node(n)->right)
|
||||
|
||||
#define OR_NODE_LEFT(n) (or_node(n)->left)
|
||||
#define OR_NODE_RIGHT(n) (or_node(n)->right)
|
||||
|
||||
#define RETURN_NODE_ARGS(n) (return_node(n)->args)
|
||||
|
||||
#define YIELD_NODE_ARGS(n) (yield_node(n)->args)
|
||||
|
||||
#define SUPER_NODE_ARGS(n) (super_node(n)->args)
|
||||
|
||||
#endif /* MRUBY_COMPILER_NODE_H */
|
||||
|
||||
@@ -542,6 +542,11 @@ 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);
|
||||
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);
|
||||
|
||||
/* (:if cond then else) */
|
||||
static node*
|
||||
@@ -1045,6 +1050,84 @@ new_op_asgn_var(parser_state *p, node *lhs, mrb_sym op, node *rhs)
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)n);
|
||||
}
|
||||
|
||||
/* Variable-sized expression node creation */
|
||||
static node*
|
||||
new_and_var(parser_state *p, node *left, node *right)
|
||||
{
|
||||
size_t total_size = sizeof(struct mrb_ast_and_node);
|
||||
enum mrb_ast_size_class class = size_to_class(total_size);
|
||||
|
||||
struct mrb_ast_and_node *n = (struct mrb_ast_and_node*)
|
||||
parser_alloc_var(p, total_size, class);
|
||||
|
||||
init_var_header(&n->header, p, NODE_AND, class);
|
||||
n->left = left;
|
||||
n->right = right;
|
||||
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)n);
|
||||
}
|
||||
|
||||
static node*
|
||||
new_or_var(parser_state *p, node *left, node *right)
|
||||
{
|
||||
size_t total_size = sizeof(struct mrb_ast_or_node);
|
||||
enum mrb_ast_size_class class = size_to_class(total_size);
|
||||
|
||||
struct mrb_ast_or_node *n = (struct mrb_ast_or_node*)
|
||||
parser_alloc_var(p, total_size, class);
|
||||
|
||||
init_var_header(&n->header, p, NODE_OR, class);
|
||||
n->left = left;
|
||||
n->right = right;
|
||||
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)n);
|
||||
}
|
||||
|
||||
static node*
|
||||
new_return_var(parser_state *p, node *args)
|
||||
{
|
||||
size_t total_size = sizeof(struct mrb_ast_return_node);
|
||||
enum mrb_ast_size_class class = size_to_class(total_size);
|
||||
|
||||
struct mrb_ast_return_node *n = (struct mrb_ast_return_node*)
|
||||
parser_alloc_var(p, total_size, class);
|
||||
|
||||
init_var_header(&n->header, p, NODE_RETURN, class);
|
||||
n->args = args;
|
||||
|
||||
return cons_head((node*)NODE_VARIABLE, (node*)n);
|
||||
}
|
||||
|
||||
static node*
|
||||
new_yield_var(parser_state *p, node *args)
|
||||
{
|
||||
size_t total_size = sizeof(struct mrb_ast_yield_node);
|
||||
enum mrb_ast_size_class class = size_to_class(total_size);
|
||||
|
||||
struct mrb_ast_yield_node *n = (struct mrb_ast_yield_node*)
|
||||
parser_alloc_var(p, total_size, class);
|
||||
|
||||
init_var_header(&n->header, p, NODE_YIELD, class);
|
||||
n->args = 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);
|
||||
}
|
||||
|
||||
/* (:fcall self mid args) */
|
||||
static node*
|
||||
new_fcall(parser_state *p, mrb_sym b, node *c)
|
||||
@@ -1064,6 +1147,9 @@ 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);
|
||||
}
|
||||
|
||||
@@ -1082,6 +1168,9 @@ new_yield(parser_state *p, node *c)
|
||||
yyerror(NULL, p, "both block arg and actual block given");
|
||||
}
|
||||
|
||||
if (p->var_nodes_enabled) {
|
||||
return new_yield_var(p, c);
|
||||
}
|
||||
return cons_head((node*)NODE_YIELD, c);
|
||||
}
|
||||
|
||||
@@ -1089,6 +1178,9 @@ new_yield(parser_state *p, node *c)
|
||||
static node*
|
||||
new_return(parser_state *p, node *c)
|
||||
{
|
||||
if (p->var_nodes_enabled) {
|
||||
return new_return_var(p, c);
|
||||
}
|
||||
return cons_head((node*)NODE_RETURN, c);
|
||||
}
|
||||
|
||||
@@ -1154,6 +1246,9 @@ static node*
|
||||
new_and(parser_state *p, node *a, node *b)
|
||||
{
|
||||
void_expr_error(p, a);
|
||||
if (p->var_nodes_enabled) {
|
||||
return new_and_var(p, a, b);
|
||||
}
|
||||
return cons_head((node*)NODE_AND, cons(a, b));
|
||||
}
|
||||
|
||||
@@ -1162,6 +1257,9 @@ static node*
|
||||
new_or(parser_state *p, node *a, node *b)
|
||||
{
|
||||
void_expr_error(p, a);
|
||||
if (p->var_nodes_enabled) {
|
||||
return new_or_var(p, a, b);
|
||||
}
|
||||
return cons_head((node*)NODE_OR, cons(a, b));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user