mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-compiler: implement head-only location optimization for ast nodes
This implements a memory optimization for AST nodes that stores location information (lineno, filename_index) only in head nodes rather than in every node, reducing memory usage for structure nodes. Key changes: - Split node types: mrb_ast_node (structure nodes without location), mrb_ast_head_node (with location info). Sizes are platform-dependent: 8/12 bytes on 32-bit, 16/24 bytes on 64-bit platforms - Separate allocation: cons() creates structure nodes, cons_head() creates head nodes with location information - Node recycling: all nodes are recycled when freed, but only smaller structure nodes are reused from the free list to maintain type safety - Updated macro: added headn() for consistent head node casting - Removed NODE_LINENO macro: eliminated redundant location copying since head-only optimization already provides adequate location info - Fixed codegen to properly access location fields via head node casts This optimization reduces AST memory usage while preserving all debugging and location information functionality. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -4923,6 +4923,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
{
|
||||
int nt;
|
||||
int rlev = s->rlev;
|
||||
struct mrb_ast_head_node *head;
|
||||
|
||||
if (!tree) {
|
||||
if (val) {
|
||||
@@ -4932,23 +4933,26 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
return;
|
||||
}
|
||||
|
||||
head = (struct mrb_ast_head_node*)tree;
|
||||
s->rlev++;
|
||||
if (s->rlev > MRB_CODEGEN_LEVEL_MAX) {
|
||||
codegen_error(s, "too complex expression");
|
||||
}
|
||||
if (s->irep && s->filename_index != tree->filename_index) {
|
||||
if (s->irep && s->filename_index != head->filename_index) {
|
||||
mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
|
||||
const char *filename = mrb_sym_name_len(s->mrb, fname, NULL);
|
||||
|
||||
mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
|
||||
filename, s->lines, s->debug_start_pos, s->pc);
|
||||
if (filename) {
|
||||
mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
|
||||
filename, s->lines, s->debug_start_pos, s->pc);
|
||||
}
|
||||
s->debug_start_pos = s->pc;
|
||||
s->filename_index = tree->filename_index;
|
||||
s->filename_sym = mrb_parser_get_filename(s->parser, tree->filename_index);
|
||||
s->filename_index = head->filename_index;
|
||||
s->filename_sym = mrb_parser_get_filename(s->parser, head->filename_index);
|
||||
}
|
||||
|
||||
nt = nint(tree->car);
|
||||
s->lineno = tree->lineno;
|
||||
s->lineno = head->lineno;
|
||||
tree = tree->cdr;
|
||||
switch (nt) {
|
||||
case NODE_STMTS:
|
||||
|
||||
@@ -139,8 +139,16 @@ struct mrb_parser_heredoc_info {
|
||||
mrb_ast_node *doc;
|
||||
};
|
||||
|
||||
/* AST node structure */
|
||||
/* AST node structures - Head-only location optimization */
|
||||
|
||||
/* Structure nodes - only car/cdr, ignores location fields */
|
||||
struct mrb_ast_node {
|
||||
struct mrb_ast_node *car, *cdr;
|
||||
/* No location fields - saves 4 bytes per structure node */
|
||||
};
|
||||
|
||||
/* Head nodes - with location info, used by cons_head() */
|
||||
struct mrb_ast_head_node {
|
||||
struct mrb_ast_node *car, *cdr;
|
||||
uint16_t lineno, filename_index;
|
||||
};
|
||||
|
||||
@@ -62,17 +62,12 @@ typedef unsigned int stack_type;
|
||||
#define CMDARG_LEXPOP() BITSTACK_LEXPOP(p->cmdarg_stack)
|
||||
#define CMDARG_P() BITSTACK_SET_P(p->cmdarg_stack)
|
||||
|
||||
#define SET_LINENO(c,n) ((c)->lineno = (n))
|
||||
#define NODE_LINENO(c,n) do {\
|
||||
if (n) {\
|
||||
(c)->filename_index = (n)->filename_index;\
|
||||
(c)->lineno = (n)->lineno;\
|
||||
}\
|
||||
} while (0)
|
||||
#define SET_LINENO(c,n) (headn(c)->lineno = (n))
|
||||
|
||||
#define sym(x) ((mrb_sym)(intptr_t)(x))
|
||||
#define nsym(x) ((node*)(intptr_t)(x))
|
||||
#define nint(x) ((node*)(intptr_t)(x))
|
||||
#define headn(x) ((struct mrb_ast_head_node*)(x))
|
||||
#define intn(x) ((int)(intptr_t)(x))
|
||||
#define typen(x) ((enum node_type)(intptr_t)(x))
|
||||
|
||||
@@ -128,15 +123,29 @@ parser_palloc(parser_state *p, size_t size)
|
||||
static node*
|
||||
cons_gen(parser_state *p, node *car, node *cdr)
|
||||
{
|
||||
node *c;
|
||||
struct mrb_ast_node *c;
|
||||
|
||||
/* Try to reuse from free list first - only for 16-byte nodes */
|
||||
if (p->cells) {
|
||||
c = p->cells;
|
||||
c = (struct mrb_ast_node*)p->cells;
|
||||
p->cells = p->cells->cdr;
|
||||
}
|
||||
else {
|
||||
c = (node*)parser_palloc(p, sizeof(mrb_ast_node));
|
||||
c = (struct mrb_ast_node*)parser_palloc(p, sizeof(struct mrb_ast_node));
|
||||
}
|
||||
c->car = car;
|
||||
c->cdr = cdr;
|
||||
/* Don't initialize location fields for structure nodes - saves CPU */
|
||||
return (node*)c;
|
||||
}
|
||||
|
||||
static node*
|
||||
cons_head_gen(parser_state *p, node *car, node *cdr)
|
||||
{
|
||||
struct mrb_ast_head_node *c;
|
||||
|
||||
/* Always allocate new nodes for head nodes - they're 24 bytes */
|
||||
c = (struct mrb_ast_head_node*)parser_palloc(p, sizeof(struct mrb_ast_head_node));
|
||||
|
||||
c->car = car;
|
||||
c->cdr = cdr;
|
||||
@@ -146,49 +155,51 @@ cons_gen(parser_state *p, node *car, node *cdr)
|
||||
if (p->lineno == 0 && p->current_filename_index > 0) {
|
||||
c->filename_index--;
|
||||
}
|
||||
return c;
|
||||
return (node*)c;
|
||||
}
|
||||
#define cons(a,b) cons_gen(p,(a),(b))
|
||||
/* Head-only location optimization: separate functions for head vs structure nodes */
|
||||
#define cons(a,b) cons_gen(p,(a),(b)) /* Structure nodes - no location */
|
||||
#define cons_head(a,b) cons_head_gen(p,(a),(b)) /* Head nodes - with location */
|
||||
|
||||
static node*
|
||||
list1_gen(parser_state *p, node *a)
|
||||
{
|
||||
return cons(a, 0);
|
||||
return cons_head(a, 0);
|
||||
}
|
||||
#define list1(a) list1_gen(p, (a))
|
||||
|
||||
static node*
|
||||
list2_gen(parser_state *p, node *a, node *b)
|
||||
{
|
||||
return cons(a, cons(b,0));
|
||||
return cons_head(a, cons(b, 0));
|
||||
}
|
||||
#define list2(a,b) list2_gen(p, (a),(b))
|
||||
|
||||
static node*
|
||||
list3_gen(parser_state *p, node *a, node *b, node *c)
|
||||
{
|
||||
return cons(a, cons(b, cons(c,0)));
|
||||
return cons_head(a, cons(b, cons(c, 0)));
|
||||
}
|
||||
#define list3(a,b,c) list3_gen(p, (a),(b),(c))
|
||||
|
||||
static node*
|
||||
list4_gen(parser_state *p, node *a, node *b, node *c, node *d)
|
||||
{
|
||||
return cons(a, cons(b, cons(c, cons(d, 0))));
|
||||
return cons_head(a, cons(b, cons(c, cons(d, 0))));
|
||||
}
|
||||
#define list4(a,b,c,d) list4_gen(p, (a),(b),(c),(d))
|
||||
|
||||
static node*
|
||||
list5_gen(parser_state *p, node *a, node *b, node *c, node *d, node *e)
|
||||
{
|
||||
return cons(a, cons(b, cons(c, cons(d, cons(e, 0)))));
|
||||
return cons_head(a, cons(b, cons(c, cons(d, cons(e, 0)))));
|
||||
}
|
||||
#define list5(a,b,c,d,e) list5_gen(p, (a),(b),(c),(d),(e))
|
||||
|
||||
static node*
|
||||
list6_gen(parser_state *p, node *a, node *b, node *c, node *d, node *e, node *f)
|
||||
{
|
||||
return cons(a, cons(b, cons(c, cons(d, cons(e, cons(f, 0))))));
|
||||
return cons_head(a, cons(b, cons(c, cons(d, cons(e, cons(f, 0))))));
|
||||
}
|
||||
#define list6(a,b,c,d,e,f) list6_gen(p, (a),(b),(c),(d),(e),(f))
|
||||
|
||||
@@ -377,7 +388,7 @@ nvars_unnest(parser_state *p)
|
||||
static node*
|
||||
new_scope(parser_state *p, node *body)
|
||||
{
|
||||
return cons((node*)NODE_SCOPE, cons(locals_node(p), body));
|
||||
return cons_head((node*)NODE_SCOPE, cons(locals_node(p), body));
|
||||
}
|
||||
|
||||
/* (:begin prog...) */
|
||||
@@ -391,14 +402,14 @@ new_stmts(parser_state *p, node *body)
|
||||
}
|
||||
return list2((node*)NODE_STMTS, body);
|
||||
}
|
||||
return cons((node*)NODE_STMTS, 0);
|
||||
return cons_head((node*)NODE_STMTS, 0);
|
||||
}
|
||||
|
||||
/* (:begin body) */
|
||||
static node*
|
||||
new_begin(parser_state *p, node *body)
|
||||
{
|
||||
return cons((node*)NODE_BEGIN, body);
|
||||
return cons_head((node*)NODE_BEGIN, body);
|
||||
}
|
||||
|
||||
#define newline_node(n) (n)
|
||||
@@ -420,7 +431,7 @@ new_mod_rescue(parser_state *p, node *body, node *resq)
|
||||
static node*
|
||||
new_ensure(parser_state *p, node *a, node *b)
|
||||
{
|
||||
return cons((node*)NODE_ENSURE, cons(a, cons(0, b)));
|
||||
return cons_head((node*)NODE_ENSURE, cons(a, cons(0, b)));
|
||||
}
|
||||
|
||||
/* (:nil) */
|
||||
@@ -448,7 +459,7 @@ new_false(parser_state *p)
|
||||
static node*
|
||||
new_alias(parser_state *p, mrb_sym a, mrb_sym b)
|
||||
{
|
||||
return cons((node*)NODE_ALIAS, cons(nsym(a), nsym(b)));
|
||||
return cons_head((node*)NODE_ALIAS, cons(nsym(a), nsym(b)));
|
||||
}
|
||||
|
||||
/* (:if cond then else) */
|
||||
@@ -472,7 +483,7 @@ static node*
|
||||
new_while(parser_state *p, node *a, node *b)
|
||||
{
|
||||
void_expr_error(p, a);
|
||||
return cons((node*)NODE_WHILE, cons(a, b));
|
||||
return cons_head((node*)NODE_WHILE, cons(a, b));
|
||||
}
|
||||
|
||||
/* (:until cond body) */
|
||||
@@ -480,7 +491,7 @@ static node*
|
||||
new_until(parser_state *p, node *a, node *b)
|
||||
{
|
||||
void_expr_error(p, a);
|
||||
return cons((node*)NODE_UNTIL, cons(a, b));
|
||||
return cons_head((node*)NODE_UNTIL, cons(a, b));
|
||||
}
|
||||
|
||||
/* (:while_mod cond body) */
|
||||
@@ -488,7 +499,7 @@ static node*
|
||||
new_while_mod(parser_state *p, node *a, node *b)
|
||||
{
|
||||
void_expr_error(p, a);
|
||||
return cons((node*)NODE_WHILE_MOD, cons(a, b));
|
||||
return cons_head((node*)NODE_WHILE_MOD, cons(a, b));
|
||||
}
|
||||
|
||||
/* (:until_mod cond body) */
|
||||
@@ -496,7 +507,7 @@ static node*
|
||||
new_until_mod(parser_state *p, node *a, node *b)
|
||||
{
|
||||
void_expr_error(p, a);
|
||||
return cons((node*)NODE_UNTIL_MOD, cons(a, b));
|
||||
return cons_head((node*)NODE_UNTIL_MOD, cons(a, b));
|
||||
}
|
||||
|
||||
/* (:for var obj body) */
|
||||
@@ -526,7 +537,7 @@ new_case(parser_state *p, node *a, node *b)
|
||||
static node*
|
||||
new_postexe(parser_state *p, node *a)
|
||||
{
|
||||
return cons((node*)NODE_POSTEXE, a);
|
||||
return cons_head((node*)NODE_POSTEXE, a);
|
||||
}
|
||||
|
||||
/* (:self) */
|
||||
@@ -542,7 +553,6 @@ new_call(parser_state *p, node *a, mrb_sym b, node *c, int pass)
|
||||
{
|
||||
node *n = list4(nint(pass?NODE_CALL:NODE_SCALL), a, nsym(b), c);
|
||||
void_expr_error(p, a);
|
||||
NODE_LINENO(n, a);
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -551,7 +561,6 @@ static node*
|
||||
new_fcall(parser_state *p, mrb_sym b, node *c)
|
||||
{
|
||||
node *n = list4((node*)NODE_FCALL, 0, nsym(b), c);
|
||||
NODE_LINENO(n, c);
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -559,21 +568,21 @@ new_fcall(parser_state *p, mrb_sym b, node *c)
|
||||
static node*
|
||||
new_callargs(parser_state *p, node *a, node *b, node *c)
|
||||
{
|
||||
return cons(a, cons(b, c));
|
||||
return cons_head(a, cons(b, c));
|
||||
}
|
||||
|
||||
/* (:super . c) */
|
||||
static node*
|
||||
new_super(parser_state *p, node *c)
|
||||
{
|
||||
return cons((node*)NODE_SUPER, c);
|
||||
return cons_head((node*)NODE_SUPER, c);
|
||||
}
|
||||
|
||||
/* (:zsuper) */
|
||||
static node*
|
||||
new_zsuper(parser_state *p)
|
||||
{
|
||||
return cons((node*)NODE_ZSUPER, 0);
|
||||
return cons_head((node*)NODE_ZSUPER, 0);
|
||||
}
|
||||
|
||||
/* (:yield . c) */
|
||||
@@ -584,28 +593,28 @@ new_yield(parser_state *p, node *c)
|
||||
yyerror(NULL, p, "both block arg and actual block given");
|
||||
}
|
||||
|
||||
return cons((node*)NODE_YIELD, c);
|
||||
return cons_head((node*)NODE_YIELD, c);
|
||||
}
|
||||
|
||||
/* (:return . c) */
|
||||
static node*
|
||||
new_return(parser_state *p, node *c)
|
||||
{
|
||||
return cons((node*)NODE_RETURN, c);
|
||||
return cons_head((node*)NODE_RETURN, c);
|
||||
}
|
||||
|
||||
/* (:break . c) */
|
||||
static node*
|
||||
new_break(parser_state *p, node *c)
|
||||
{
|
||||
return cons((node*)NODE_BREAK, c);
|
||||
return cons_head((node*)NODE_BREAK, c);
|
||||
}
|
||||
|
||||
/* (:next . c) */
|
||||
static node*
|
||||
new_next(parser_state *p, node *c)
|
||||
{
|
||||
return cons((node*)NODE_NEXT, c);
|
||||
return cons_head((node*)NODE_NEXT, c);
|
||||
}
|
||||
|
||||
/* (:redo) */
|
||||
@@ -626,14 +635,14 @@ new_retry(parser_state *p)
|
||||
static node*
|
||||
new_dot2(parser_state *p, node *a, node *b)
|
||||
{
|
||||
return cons((node*)NODE_DOT2, cons(a, b));
|
||||
return cons_head((node*)NODE_DOT2, cons(a, b));
|
||||
}
|
||||
|
||||
/* (:dot3 a b) */
|
||||
static node*
|
||||
new_dot3(parser_state *p, node *a, node *b)
|
||||
{
|
||||
return cons((node*)NODE_DOT3, cons(a, b));
|
||||
return cons_head((node*)NODE_DOT3, cons(a, b));
|
||||
}
|
||||
|
||||
/* (:colon2 b c) */
|
||||
@@ -641,14 +650,14 @@ static node*
|
||||
new_colon2(parser_state *p, node *b, mrb_sym c)
|
||||
{
|
||||
void_expr_error(p, b);
|
||||
return cons((node*)NODE_COLON2, cons(b, nsym(c)));
|
||||
return cons_head((node*)NODE_COLON2, cons(b, nsym(c)));
|
||||
}
|
||||
|
||||
/* (:colon3 . c) */
|
||||
static node*
|
||||
new_colon3(parser_state *p, mrb_sym c)
|
||||
{
|
||||
return cons((node*)NODE_COLON3, nsym(c));
|
||||
return cons_head((node*)NODE_COLON3, nsym(c));
|
||||
}
|
||||
|
||||
/* (:and a b) */
|
||||
@@ -656,7 +665,7 @@ static node*
|
||||
new_and(parser_state *p, node *a, node *b)
|
||||
{
|
||||
void_expr_error(p, a);
|
||||
return cons((node*)NODE_AND, cons(a, b));
|
||||
return cons_head((node*)NODE_AND, cons(a, b));
|
||||
}
|
||||
|
||||
/* (:or a b) */
|
||||
@@ -664,14 +673,14 @@ static node*
|
||||
new_or(parser_state *p, node *a, node *b)
|
||||
{
|
||||
void_expr_error(p, a);
|
||||
return cons((node*)NODE_OR, cons(a, b));
|
||||
return cons_head((node*)NODE_OR, cons(a, b));
|
||||
}
|
||||
|
||||
/* (:array a...) */
|
||||
static node*
|
||||
new_array(parser_state *p, node *a)
|
||||
{
|
||||
return cons((node*)NODE_ARRAY, a);
|
||||
return cons_head((node*)NODE_ARRAY, a);
|
||||
}
|
||||
|
||||
/* (:splat . a) */
|
||||
@@ -679,28 +688,28 @@ static node*
|
||||
new_splat(parser_state *p, node *a)
|
||||
{
|
||||
void_expr_error(p, a);
|
||||
return cons((node*)NODE_SPLAT, a);
|
||||
return cons_head((node*)NODE_SPLAT, a);
|
||||
}
|
||||
|
||||
/* (:hash (k . v) (k . v)...) */
|
||||
static node*
|
||||
new_hash(parser_state *p, node *a)
|
||||
{
|
||||
return cons((node*)NODE_HASH, a);
|
||||
return cons_head((node*)NODE_HASH, a);
|
||||
}
|
||||
|
||||
/* (:kw_hash (k . v) (k . v)...) */
|
||||
static node*
|
||||
new_kw_hash(parser_state *p, node *a)
|
||||
{
|
||||
return cons((node*)NODE_KW_HASH, a);
|
||||
return cons_head((node*)NODE_KW_HASH, a);
|
||||
}
|
||||
|
||||
/* (:sym . a) */
|
||||
static node*
|
||||
new_sym(parser_state *p, mrb_sym sym)
|
||||
{
|
||||
return cons((node*)NODE_SYM, nsym(sym));
|
||||
return cons_head((node*)NODE_SYM, nsym(sym));
|
||||
}
|
||||
|
||||
static mrb_sym
|
||||
@@ -716,28 +725,28 @@ new_strsym(parser_state *p, node* str)
|
||||
static node*
|
||||
new_lvar(parser_state *p, mrb_sym sym)
|
||||
{
|
||||
return cons((node*)NODE_LVAR, nsym(sym));
|
||||
return cons_head((node*)NODE_LVAR, nsym(sym));
|
||||
}
|
||||
|
||||
/* (:gvar . a) */
|
||||
static node*
|
||||
new_gvar(parser_state *p, mrb_sym sym)
|
||||
{
|
||||
return cons((node*)NODE_GVAR, nsym(sym));
|
||||
return cons_head((node*)NODE_GVAR, nsym(sym));
|
||||
}
|
||||
|
||||
/* (:ivar . a) */
|
||||
static node*
|
||||
new_ivar(parser_state *p, mrb_sym sym)
|
||||
{
|
||||
return cons((node*)NODE_IVAR, nsym(sym));
|
||||
return cons_head((node*)NODE_IVAR, nsym(sym));
|
||||
}
|
||||
|
||||
/* (:cvar . a) */
|
||||
static node*
|
||||
new_cvar(parser_state *p, mrb_sym sym)
|
||||
{
|
||||
return cons((node*)NODE_CVAR, nsym(sym));
|
||||
return cons_head((node*)NODE_CVAR, nsym(sym));
|
||||
}
|
||||
|
||||
/* (:nvar . a) */
|
||||
@@ -763,14 +772,14 @@ new_nvar(parser_state *p, int num)
|
||||
else {
|
||||
p->nvars->car = nint(nvar > num ? nvar : num);
|
||||
}
|
||||
return cons((node*)NODE_NVAR, nint(num));
|
||||
return cons_head((node*)NODE_NVAR, nint(num));
|
||||
}
|
||||
|
||||
/* (:const . a) */
|
||||
static node*
|
||||
new_const(parser_state *p, mrb_sym sym)
|
||||
{
|
||||
return cons((node*)NODE_CONST, nsym(sym));
|
||||
return cons_head((node*)NODE_CONST, nsym(sym));
|
||||
}
|
||||
|
||||
/* (:undef a...) */
|
||||
@@ -846,7 +855,7 @@ defs_setup(parser_state *p, node *d, node *a, node *b)
|
||||
static node*
|
||||
new_arg(parser_state *p, mrb_sym sym)
|
||||
{
|
||||
return cons((node*)NODE_ARG, nsym(sym));
|
||||
return cons_head((node*)NODE_ARG, nsym(sym));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -945,7 +954,7 @@ new_kw_arg(parser_state *p, mrb_sym kw, node *def_arg)
|
||||
static node*
|
||||
new_kw_rest_args(parser_state *p, mrb_sym sym)
|
||||
{
|
||||
return cons((node*)NODE_KW_REST_ARGS, nsym(sym));
|
||||
return cons_head((node*)NODE_KW_REST_ARGS, nsym(sym));
|
||||
}
|
||||
|
||||
static node*
|
||||
@@ -963,7 +972,7 @@ new_args_dots(parser_state *p, node *m)
|
||||
static node*
|
||||
new_block_arg(parser_state *p, node *a)
|
||||
{
|
||||
return cons((node*)NODE_BLOCK_ARG, a);
|
||||
return cons_head((node*)NODE_BLOCK_ARG, a);
|
||||
}
|
||||
|
||||
static node*
|
||||
@@ -1017,7 +1026,7 @@ static node*
|
||||
new_asgn(parser_state *p, node *a, node *b)
|
||||
{
|
||||
void_expr_error(p, b);
|
||||
return cons((node*)NODE_ASGN, cons(a, b));
|
||||
return cons_head((node*)NODE_ASGN, cons(a, b));
|
||||
}
|
||||
|
||||
/* (:masgn mlhs=(pre rest post) mrhs) */
|
||||
@@ -1025,14 +1034,14 @@ static node*
|
||||
new_masgn(parser_state *p, node *a, node *b)
|
||||
{
|
||||
void_expr_error(p, b);
|
||||
return cons((node*)NODE_MASGN, cons(a, b));
|
||||
return cons_head((node*)NODE_MASGN, cons(a, b));
|
||||
}
|
||||
|
||||
/* (:masgn mlhs mrhs) no check */
|
||||
static node*
|
||||
new_masgn_param(parser_state *p, node *a, node *b)
|
||||
{
|
||||
return cons((node*)NODE_MASGN, cons(a, b));
|
||||
return cons_head((node*)NODE_MASGN, cons(a, b));
|
||||
}
|
||||
|
||||
/* (:asgn lhs rhs) */
|
||||
@@ -1090,14 +1099,14 @@ new_float(parser_state *p, const char *s, int suffix)
|
||||
static node*
|
||||
new_str(parser_state *p, const char *s, size_t len)
|
||||
{
|
||||
return cons((node*)NODE_STR, cons((node*)strndup(s, len), nint(len)));
|
||||
return cons_head((node*)NODE_STR, cons((node*)strndup(s, len), nint(len)));
|
||||
}
|
||||
|
||||
/* (:dstr . a) */
|
||||
static node*
|
||||
new_dstr(parser_state *p, node *a)
|
||||
{
|
||||
return cons((node*)NODE_DSTR, a);
|
||||
return cons_head((node*)NODE_DSTR, a);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1184,49 +1193,49 @@ concat_string(parser_state *p, node *a, node *b)
|
||||
static node*
|
||||
new_xstr(parser_state *p, const char *s, int len)
|
||||
{
|
||||
return cons((node*)NODE_XSTR, cons((node*)strndup(s, len), nint(len)));
|
||||
return cons_head((node*)NODE_XSTR, cons((node*)strndup(s, len), nint(len)));
|
||||
}
|
||||
|
||||
/* (:xstr . a) */
|
||||
static node*
|
||||
new_dxstr(parser_state *p, node *a)
|
||||
{
|
||||
return cons((node*)NODE_DXSTR, a);
|
||||
return cons_head((node*)NODE_DXSTR, a);
|
||||
}
|
||||
|
||||
/* (:dsym . a) */
|
||||
static node*
|
||||
new_dsym(parser_state *p, node *a)
|
||||
{
|
||||
return cons((node*)NODE_DSYM, a);
|
||||
return cons_head((node*)NODE_DSYM, a);
|
||||
}
|
||||
|
||||
/* (:regx . (s . (opt . enc))) */
|
||||
static node*
|
||||
new_regx(parser_state *p, const char *p1, const char* p2, const char* p3)
|
||||
{
|
||||
return cons((node*)NODE_REGX, cons((node*)p1, cons((node*)p2, (node*)p3)));
|
||||
return cons_head((node*)NODE_REGX, cons((node*)p1, cons((node*)p2, (node*)p3)));
|
||||
}
|
||||
|
||||
/* (:dregx . (a . b)) */
|
||||
static node*
|
||||
new_dregx(parser_state *p, node *a, node *b)
|
||||
{
|
||||
return cons((node*)NODE_DREGX, cons(a, b));
|
||||
return cons_head((node*)NODE_DREGX, cons(a, b));
|
||||
}
|
||||
|
||||
/* (:backref . n) */
|
||||
static node*
|
||||
new_back_ref(parser_state *p, int n)
|
||||
{
|
||||
return cons((node*)NODE_BACK_REF, nint(n));
|
||||
return cons_head((node*)NODE_BACK_REF, nint(n));
|
||||
}
|
||||
|
||||
/* (:nthref . n) */
|
||||
static node*
|
||||
new_nth_ref(parser_state *p, int n)
|
||||
{
|
||||
return cons((node*)NODE_NTH_REF, nint(n));
|
||||
return cons_head((node*)NODE_NTH_REF, nint(n));
|
||||
}
|
||||
|
||||
/* (:heredoc . a) */
|
||||
@@ -1234,7 +1243,7 @@ static node*
|
||||
new_heredoc(parser_state *p)
|
||||
{
|
||||
parser_heredoc_info *inf = (parser_heredoc_info*)parser_palloc(p, sizeof(parser_heredoc_info));
|
||||
return cons((node*)NODE_HEREDOC, (node*)inf);
|
||||
return cons_head((node*)NODE_HEREDOC, (node*)inf);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1245,21 +1254,21 @@ new_bv(parser_state *p, mrb_sym id)
|
||||
static node*
|
||||
new_literal_delim(parser_state *p)
|
||||
{
|
||||
return cons((node*)NODE_LITERAL_DELIM, 0);
|
||||
return cons_head((node*)NODE_LITERAL_DELIM, 0);
|
||||
}
|
||||
|
||||
/* (:words . a) */
|
||||
static node*
|
||||
new_words(parser_state *p, node *a)
|
||||
{
|
||||
return cons((node*)NODE_WORDS, a);
|
||||
return cons_head((node*)NODE_WORDS, a);
|
||||
}
|
||||
|
||||
/* (:symbols . a) */
|
||||
static node*
|
||||
new_symbols(parser_state *p, node *a)
|
||||
{
|
||||
return cons((node*)NODE_SYMBOLS, a);
|
||||
return cons_head((node*)NODE_SYMBOLS, a);
|
||||
}
|
||||
|
||||
/* xxx ----------------------------- */
|
||||
@@ -1338,7 +1347,7 @@ call_with_block(parser_state *p, node *a, node *b)
|
||||
static node*
|
||||
new_negate(parser_state *p, node *n)
|
||||
{
|
||||
return cons((node*)NODE_NEGATE, n);
|
||||
return cons_head((node*)NODE_NEGATE, n);
|
||||
}
|
||||
|
||||
static node*
|
||||
@@ -1696,7 +1705,6 @@ program : {
|
||||
top_compstmt
|
||||
{
|
||||
p->tree = new_scope(p, $2);
|
||||
NODE_LINENO(p->tree, $2);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -1713,7 +1721,6 @@ top_stmts : none
|
||||
| top_stmt
|
||||
{
|
||||
$$ = new_stmts(p, $1);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
| top_stmts terms top_stmt
|
||||
{
|
||||
@@ -1747,7 +1754,6 @@ bodystmt : compstmt
|
||||
{
|
||||
if ($2) {
|
||||
$$ = new_rescue(p, $1, $2, $3);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
else if ($3) {
|
||||
yywarning(p, "else without rescue is useless");
|
||||
@@ -1780,7 +1786,6 @@ stmts : none
|
||||
| stmt
|
||||
{
|
||||
$$ = new_stmts(p, $1);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
| stmts terms stmt
|
||||
{
|
||||
@@ -2569,7 +2574,6 @@ aref_args : none
|
||||
| args trailer
|
||||
{
|
||||
$$ = $1;
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
| args comma assocs trailer
|
||||
{
|
||||
@@ -2578,7 +2582,6 @@ aref_args : none
|
||||
| assocs trailer
|
||||
{
|
||||
$$ = cons(new_kw_hash(p, $1), 0);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -2632,17 +2635,14 @@ opt_call_args : none
|
||||
| args comma
|
||||
{
|
||||
$$ = new_callargs(p,$1,0,0);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
| args comma assocs comma
|
||||
{
|
||||
$$ = new_callargs(p,$1,new_kw_hash(p,$3),0);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
| assocs comma
|
||||
{
|
||||
$$ = new_callargs(p,0,new_kw_hash(p,$1),0);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -2650,27 +2650,22 @@ call_args : command
|
||||
{
|
||||
void_expr_error(p, $1);
|
||||
$$ = new_callargs(p, list1($1), 0, 0);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
| args opt_block_arg
|
||||
{
|
||||
$$ = new_callargs(p, $1, 0, $2);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
| assocs opt_block_arg
|
||||
{
|
||||
$$ = new_callargs(p, 0, new_kw_hash(p, $1), $2);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
| args comma assocs opt_block_arg
|
||||
{
|
||||
$$ = new_callargs(p, $1, new_kw_hash(p, $3), $4);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
| block_arg
|
||||
{
|
||||
$$ = new_callargs(p, 0, 0, $1);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -2712,7 +2707,6 @@ args : arg
|
||||
{
|
||||
void_expr_error(p, $1);
|
||||
$$ = list1($1);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
| tSTAR
|
||||
{
|
||||
@@ -2721,7 +2715,6 @@ args : arg
|
||||
| tSTAR arg
|
||||
{
|
||||
$$ = list1(new_splat(p, $2));
|
||||
NODE_LINENO($$, $2);
|
||||
}
|
||||
| args comma arg
|
||||
{
|
||||
@@ -2804,12 +2797,10 @@ primary : literal
|
||||
| tLBRACK aref_args ']'
|
||||
{
|
||||
$$ = new_array(p, $2);
|
||||
NODE_LINENO($$, $2);
|
||||
}
|
||||
| tLBRACE assoc_list '}'
|
||||
{
|
||||
$$ = new_hash(p, $2);
|
||||
NODE_LINENO($$, $2);
|
||||
}
|
||||
| keyword_return
|
||||
{
|
||||
@@ -4096,7 +4087,6 @@ assoc_list : none
|
||||
assocs : assoc
|
||||
{
|
||||
$$ = list1($1);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
| assocs comma assoc
|
||||
{
|
||||
@@ -7068,7 +7058,7 @@ mrb_load_string(mrb_state *mrb, const char *s)
|
||||
static void
|
||||
dump_prefix(node *tree, int offset)
|
||||
{
|
||||
printf("%05d ", tree->lineno);
|
||||
printf("%05d ", 0); /* location info not available in this context */
|
||||
while (offset--) {
|
||||
putc(' ', stdout);
|
||||
putc(' ', stdout);
|
||||
|
||||
+1145
-1153
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user