From c40c28c2abc0cc408f7844596ddf8571aebb8978 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 27 Aug 2025 18:37:36 +0900 Subject: [PATCH] mruby-compiler: add variable-sized literal node support add variable-sized node structures for literal nodes (dstr, regx, dot2/dot3 ranges, float) with conditional usage based on var_nodes_enabled. includes casting macros, value access macros, creation functions, and codegen support that maintains compatibility with existing traditional codegen functions. Co-authored-by: Claude --- mrbgems/mruby-compiler/core/codegen.c | 90 ++++++++++++++++++++++ mrbgems/mruby-compiler/core/node.h | 52 +++++++++++++ mrbgems/mruby-compiler/core/parse.y | 105 +++++++++++++++++++++++++- 3 files changed, 246 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 7c37a87b9..3fd4d96dc 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -5422,6 +5422,76 @@ gen_super_var(codegen_scope *s, node *varnode, int val) codegen_super(s, args, val); } +/* Variable-sized literal node generation functions */ +static void +gen_dstr_var(codegen_scope *s, node *varnode, int val) +{ + struct mrb_ast_dstr_node *dstr_n = dstr_node(varnode->car); + node *list = DSTR_NODE_LIST(dstr_n); + + /* Use traditional dstr codegen logic */ + codegen_heredoc_dstr(s, list, val); +} + +static void +gen_regx_var(codegen_scope *s, node *varnode, int val) +{ + struct mrb_ast_regx_node *regx_n = regx_node(varnode->car); + const char *pattern = REGX_NODE_PATTERN(regx_n); + const char *flags = REGX_NODE_FLAGS(regx_n); + const char *encoding = REGX_NODE_ENCODING(regx_n); + + /* Create simple list structure like traditional node */ + node list_node; + node flags_node; + list_node.car = (node*)pattern; + list_node.cdr = &flags_node; + flags_node.car = (node*)flags; + flags_node.cdr = (node*)encoding; + + codegen_regx(s, &list_node, val); +} + +static void +gen_dot2_var(codegen_scope *s, node *varnode, int val) +{ + struct mrb_ast_dot2_node *dot2_n = dot2_node(varnode->car); + node *left = DOT2_NODE_LEFT(dot2_n); + node *right = DOT2_NODE_RIGHT(dot2_n); + + /* Create simple cons structure like traditional node */ + node range_node; + range_node.car = left; + range_node.cdr = right; + + codegen_dot2(s, &range_node, val); +} + +static void +gen_dot3_var(codegen_scope *s, node *varnode, int val) +{ + struct mrb_ast_dot3_node *dot3_n = dot3_node(varnode->car); + node *left = DOT3_NODE_LEFT(dot3_n); + node *right = DOT3_NODE_RIGHT(dot3_n); + + /* Create simple cons structure like traditional node */ + node range_node; + range_node.car = left; + range_node.cdr = right; + + codegen_dot3(s, &range_node, val); +} + +static void +gen_float_var(codegen_scope *s, node *varnode, int val) +{ + struct mrb_ast_float_node *float_n = float_node(varnode->car); + const char *value = FLOAT_NODE_VALUE(float_n); + + /* Use traditional float codegen logic directly */ + codegen_float(s, (node*)value, val); +} + static mrb_bool codegen_variable_node(codegen_scope *s, node *varnode, int val) { @@ -5543,6 +5613,26 @@ codegen_variable_node(codegen_scope *s, node *varnode, int val) gen_super_var(s, varnode, val); return TRUE; + case NODE_DSTR: + gen_dstr_var(s, varnode, val); + return TRUE; + + case NODE_REGX: + gen_regx_var(s, varnode, val); + return TRUE; + + case NODE_DOT2: + gen_dot2_var(s, varnode, val); + return TRUE; + + case NODE_DOT3: + gen_dot3_var(s, varnode, val); + return TRUE; + + case NODE_FLOAT: + gen_float_var(s, varnode, val); + return TRUE; + default: return FALSE; /* Not handled, fall through to main codegen */ } diff --git a/mrbgems/mruby-compiler/core/node.h b/mrbgems/mruby-compiler/core/node.h index 1665a45b6..753319182 100644 --- a/mrbgems/mruby-compiler/core/node.h +++ b/mrbgems/mruby-compiler/core/node.h @@ -517,4 +517,56 @@ struct mrb_ast_super_node { #define SUPER_NODE_ARGS(n) (super_node(n)->args) +/* Variable-sized literal node structures */ +struct mrb_ast_dstr_node { + struct mrb_ast_var_header hdr; + struct mrb_ast_node *list; +}; + +struct mrb_ast_regx_node { + struct mrb_ast_var_header hdr; + const char *pattern; + const char *flags; + const char *encoding; +}; + +struct mrb_ast_dot2_node { + struct mrb_ast_var_header hdr; + struct mrb_ast_node *left; + struct mrb_ast_node *right; +}; + +struct mrb_ast_dot3_node { + struct mrb_ast_var_header hdr; + struct mrb_ast_node *left; + struct mrb_ast_node *right; +}; + +struct mrb_ast_float_node { + struct mrb_ast_var_header hdr; + const char *value; +}; + +/* Literal node casting macros */ +#define dstr_node(n) ((struct mrb_ast_dstr_node*)(n)) +#define regx_node(n) ((struct mrb_ast_regx_node*)(n)) +#define dot2_node(n) ((struct mrb_ast_dot2_node*)(n)) +#define dot3_node(n) ((struct mrb_ast_dot3_node*)(n)) +#define float_node(n) ((struct mrb_ast_float_node*)(n)) + +/* Literal node value access macros */ +#define DSTR_NODE_LIST(n) (dstr_node(n)->list) + +#define REGX_NODE_PATTERN(n) (regx_node(n)->pattern) +#define REGX_NODE_FLAGS(n) (regx_node(n)->flags) +#define REGX_NODE_ENCODING(n) (regx_node(n)->encoding) + +#define DOT2_NODE_LEFT(n) (dot2_node(n)->left) +#define DOT2_NODE_RIGHT(n) (dot2_node(n)->right) + +#define DOT3_NODE_LEFT(n) (dot3_node(n)->left) +#define DOT3_NODE_RIGHT(n) (dot3_node(n)->right) + +#define FLOAT_NODE_VALUE(n) (float_node(n)->value) + #endif /* MRUBY_COMPILER_NODE_H */ diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index a549ac827..6cb864330 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -547,6 +547,11 @@ 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_dstr_var(parser_state *p, node *list); +static node* new_regx_var(parser_state *p, const char *pattern, const char *flags, const char *encoding); +static node* new_dot2_var(parser_state *p, node *left, node *right); +static node* new_dot3_var(parser_state *p, node *left, node *right); +static node* new_float_var(parser_state *p, const char *value); /* (:if cond then else) */ static node* @@ -1128,6 +1133,86 @@ new_super_var(parser_state *p, node *args) return cons_head((node*)NODE_VARIABLE, (node*)n); } +/* Variable-sized literal node creation functions */ +static node* +new_dstr_var(parser_state *p, node *list) +{ + size_t total_size = sizeof(struct mrb_ast_dstr_node); + enum mrb_ast_size_class class = size_to_class(total_size); + + struct mrb_ast_dstr_node *n = (struct mrb_ast_dstr_node*) + parser_alloc_var(p, total_size, class); + + init_var_header(&n->hdr, p, NODE_DSTR, class); + n->list = list; + + return cons_head((node*)NODE_VARIABLE, (node*)n); +} + +static node* +new_regx_var(parser_state *p, const char *pattern, const char *flags, const char *encoding) +{ + size_t total_size = sizeof(struct mrb_ast_regx_node); + enum mrb_ast_size_class class = size_to_class(total_size); + + struct mrb_ast_regx_node *n = (struct mrb_ast_regx_node*) + parser_alloc_var(p, total_size, class); + + init_var_header(&n->hdr, p, NODE_REGX, class); + n->pattern = pattern; + n->flags = flags; + n->encoding = encoding; + + return cons_head((node*)NODE_VARIABLE, (node*)n); +} + +static node* +new_dot2_var(parser_state *p, node *left, node *right) +{ + size_t total_size = sizeof(struct mrb_ast_dot2_node); + enum mrb_ast_size_class class = size_to_class(total_size); + + struct mrb_ast_dot2_node *n = (struct mrb_ast_dot2_node*) + parser_alloc_var(p, total_size, class); + + init_var_header(&n->hdr, p, NODE_DOT2, class); + n->left = left; + n->right = right; + + return cons_head((node*)NODE_VARIABLE, (node*)n); +} + +static node* +new_dot3_var(parser_state *p, node *left, node *right) +{ + size_t total_size = sizeof(struct mrb_ast_dot3_node); + enum mrb_ast_size_class class = size_to_class(total_size); + + struct mrb_ast_dot3_node *n = (struct mrb_ast_dot3_node*) + parser_alloc_var(p, total_size, class); + + init_var_header(&n->hdr, p, NODE_DOT3, class); + n->left = left; + n->right = right; + + return cons_head((node*)NODE_VARIABLE, (node*)n); +} + +static node* +new_float_var(parser_state *p, const char *value) +{ + size_t total_size = sizeof(struct mrb_ast_float_node); + enum mrb_ast_size_class class = size_to_class(total_size); + + struct mrb_ast_float_node *n = (struct mrb_ast_float_node*) + parser_alloc_var(p, total_size, class); + + init_var_header(&n->hdr, p, NODE_FLOAT, class); + n->value = strdup(value); + + return cons_head((node*)NODE_VARIABLE, (node*)n); +} + /* (:fcall self mid args) */ static node* new_fcall(parser_state *p, mrb_sym b, node *c) @@ -1216,6 +1301,9 @@ new_retry(parser_state *p) static node* new_dot2(parser_state *p, node *a, node *b) { + if (p->var_nodes_enabled) { + return new_dot2_var(p, a, b); + } return cons_head((node*)NODE_DOT2, cons(a, b)); } @@ -1223,6 +1311,9 @@ new_dot2(parser_state *p, node *a, node *b) static node* new_dot3(parser_state *p, node *a, node *b) { + if (p->var_nodes_enabled) { + return new_dot3_var(p, a, b); + } return cons_head((node*)NODE_DOT3, cons(a, b)); } @@ -1791,7 +1882,13 @@ new_int(parser_state *p, const char *s, int base, int suffix) static node* new_float(parser_state *p, const char *s, int suffix) { - node* result = cons((node*)NODE_FLOAT, (node*)strdup(s)); + node* result; + if (p->var_nodes_enabled) { + result = new_float_var(p, s); + } + else { + result = cons((node*)NODE_FLOAT, (node*)strdup(s)); + } if (suffix & NUM_SUFFIX_R) { result = new_rational(p, result); } @@ -1853,6 +1950,9 @@ new_str(parser_state *p, const char *s, size_t len) static node* new_dstr(parser_state *p, node *a) { + if (p->var_nodes_enabled) { + return new_dstr_var(p, a); + } return cons_head((node*)NODE_DSTR, a); } @@ -1961,6 +2061,9 @@ new_dsym(parser_state *p, node *a) static node* new_regx(parser_state *p, const char *p1, const char* p2, const char* p3) { + if (p->var_nodes_enabled) { + return new_regx_var(p, p1, p2, p3); + } return cons_head((node*)NODE_REGX, cons((node*)p1, cons((node*)p2, (node*)p3))); }