Feature #17768 ยป 2021aprilfool.patch
parse.y  

VALUE prevline;


VALUE lastline;


VALUE nextline;


st_table *new_nodes;


const char *pbeg;


const char *pcur;


const char *pend;


...  ...  
static NODE* node_newnode(struct parser_params *, enum node_type, VALUE, VALUE, VALUE, const rb_code_location_t*);


#define rb_node_newnode(type, a1, a2, a3, loc) node_newnode(p, (type), (a1), (a2), (a3), (loc))


static NODE *nd_set_loc(NODE *nd, const YYLTYPE *loc);


static NODE *nd_set_loc(struct parser_params *, NODE *nd, const YYLTYPE *loc);


static int


parser_get_node_id(struct parser_params *p)


...  ...  
static NODE *new_regexp(struct parser_params *, NODE *, int, const YYLTYPE *);


#define make_list(list, loc) ((list) ? (nd_set_loc(list, loc), list) : NEW_ZLIST(loc))


#define make_list(list, loc) ((list) ? (nd_set_loc(p, list, loc), list) : NEW_ZLIST(loc))


static NODE *new_xstring(struct parser_params *, NODE *, const YYLTYPE *loc);


...  ...  
{


/*%%%*/


$$ = heredoc_dedent(p, $2);


if ($$) nd_set_loc($$, &@$);


if ($$) nd_set_loc(p, $$, &@$);


/*% %*/


/*% ripper: string_literal!(heredoc_dedent(p, $2)) %*/


}


...  ...  
}


#endif


goto normal_newline;


case '^': {


const char *down = RSTRING_PTR(p>lex.lastline);


if (p>lex.prevline && !p>eofp) p>lex.lastline = p>lex.prevline;


int i = 0;


while (1) {


while (ISSPACE(down[i]) && down[i] != '\n') i++;


if (down[i] == '\n') break;


if (down[i] != '^') {


yyerror0("invalid syntax in down assignment line");


break;


}


int j = i;


while (down[j] == '^') j++;


int k = j;


while (down[k] != '^' && !ISSPACE(down[k]) && down[k] != '\n' && ISASCII(down[k])) k++;


rb_code_location_t loc = { { p>ruby_sourceline  1, i }, { p>ruby_sourceline  1, j } };


NODE *node;


if (p>lex.new_nodes && st_lookup(p>lex.new_nodes, (st_data_t)&loc, (st_data_t*)&node)) {


NODE *n = rb_ast_newnode(p>ast, nd_type(node));


rb_node_init(n, nd_type(node), node>u1.value, node>u2.value, node>u3.value);


nd_set_loc(p, n, &node>nd_loc);


n>node_id = node>node_id;


ID id = intern_cstr(down + j, k  j, p>enc);


NODE *tmp = assignable(p, id, n, &loc);


*node = *tmp;


node>node_id = 1;


}


else {


yyerror0("cannot identify node");


break;


}


i = k;


}


p>lex.pbeg = RSTRING_PTR(p>lex.lastline);


p>lex.pend = p>lex.pcur = p>lex.pbeg + RSTRING_LEN(p>lex.lastline);


pushback(p, 1); /* always pushback */


p>lex.ptok = p>lex.pcur;


goto normal_newline;


}


}


}


normal_newline:


if (p>lex.new_nodes) st_clear(p>lex.new_nodes);


p>command_start = TRUE;


SET_LEX_STATE(EXPR_BEG);


return '\n';


...  ...  
#define LVAR_USED ((ID)1 << (sizeof(ID) * CHAR_BIT  1))


int


st_loc_cmp(st_data_t x, st_data_t y)


{


const YYLTYPE *loc1 = (const YYLTYPE *)x;


const YYLTYPE *loc2 = (const YYLTYPE *)y;


return !(


loc1>beg_pos.lineno == loc2>beg_pos.lineno &&


loc1>beg_pos.column == loc2>beg_pos.column &&


loc1>end_pos.lineno == loc2>end_pos.lineno &&


loc1>end_pos.column == loc2>end_pos.column


);


}


st_index_t


st_loc_hash(st_data_t x)


{


const YYLTYPE *loc = (const YYLTYPE *)x;


return loc>beg_pos.lineno ^ loc>beg_pos.column ^ loc>end_pos.lineno ^ loc>end_pos.column;


}


static const struct st_hash_type st_hashtype_loc = {


st_loc_cmp,


st_loc_hash,


};


static NODE*


node_newnode(struct parser_params *p, enum node_type type, VALUE a0, VALUE a1, VALUE a2, const rb_code_location_t *loc)


{


...  ...  
rb_node_init(n, type, a0, a1, a2);


nd_set_loc(n, loc);


nd_set_loc(p, n, loc);


nd_set_node_id(n, parser_get_node_id(p));


return n;


}


static NODE *


nd_set_loc(NODE *nd, const YYLTYPE *loc)


nd_set_loc(struct parser_params *p, NODE *nd, const YYLTYPE *loc)


{


if (!p>lex.new_nodes) p>lex.new_nodes = st_init_table(&st_hashtype_loc);


nd>nd_loc = *loc;


if (!st_lookup(p>lex.new_nodes, (st_data_t)&nd>nd_loc, NULL)) {


st_insert(p>lex.new_nodes, (st_data_t)&nd>nd_loc, (st_data_t)nd);


}


nd_set_line(nd, loc>beg_pos.lineno);


return nd;


}


...  ...  
{


VALUE src = node>nd_lit;


nd_set_type(node, NODE_LIT);


nd_set_loc(node, loc);


nd_set_loc(p, node, loc);


RB_OBJ_WRITTEN(p>ast, Qnil, node>nd_lit = reg_compile(p, src, options));


}


break;


...  ...  
/* fall through */


case NODE_DSTR:


nd_set_type(node, NODE_DREGX);


nd_set_loc(node, loc);


nd_set_loc(p, node, loc);


node>nd_cflag = options & RE_OPTION_MASK;


if (!NIL_P(node>nd_lit)) reg_fragment_check(p, node>nd_lit, options);


for (list = (prev = node)>nd_next; list; list = list>nd_next) {


...  ...  
switch (nd_type(node)) {


case NODE_STR:


nd_set_type(node, NODE_XSTR);


nd_set_loc(node, loc);


nd_set_loc(p, node, loc);


break;


case NODE_DSTR:


nd_set_type(node, NODE_DXSTR);


nd_set_loc(node, loc);


nd_set_loc(p, node, loc);


break;


default:


node = NEW_NODE(NODE_DXSTR, Qnil, 1, NEW_LIST(node, loc), loc);


...  ...  
case NODE_MASGN:


case NODE_CVASGN:


lhs>nd_value = rhs;


nd_set_loc(lhs, loc);


nd_set_loc(p, lhs, loc);


break;


case NODE_ATTRASGN:


lhs>nd_args = arg_append(p, lhs>nd_args, rhs, loc);


nd_set_loc(lhs, loc);


nd_set_loc(p, lhs, loc);


break;


default:


...  ...  
args>ruby2_keywords = rest_arg == idFWD_REST;


p>ruby_sourceline = saved_line;


nd_set_loc(tail, loc);


nd_set_loc(p, tail, loc);


return tail;


}


...  ...  
if (!args) {


YYLTYPE loc = RUBY_INIT_YYLLOC();


args = new_args_tail(p, 0, 0, 0, 0);


nd_set_loc(args, &loc);


nd_set_loc(p, args, &loc);


}


args>nd_ainfo>pre_args_num = max_numparam;


}


...  ...  
switch (nd_type(node)) {


case NODE_DSTR:


nd_set_type(node, NODE_DSYM);


nd_set_loc(node, loc);


nd_set_loc(p, node, loc);


break;


case NODE_STR:


lit = node>nd_lit;


RB_OBJ_WRITTEN(p>ast, Qnil, node>nd_lit = ID2SYM(rb_intern_str(lit)));


nd_set_type(node, NODE_LIT);


nd_set_loc(node, loc);


nd_set_loc(p, node, loc);


break;


default:


node = NEW_NODE(NODE_DSYM, Qnil, 1, NEW_LIST(node, loc), loc);


...  ...  
if (op == tOROP) {


rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs>nd_loc);


lhs>nd_value = rhs;


nd_set_loc(lhs, loc);


nd_set_loc(p, lhs, loc);


asgn = NEW_OP_ASGN_OR(gettable(p, vid, &lhs_loc), lhs, loc);


if (is_notop_id(vid)) {


switch (id_type(vid)) {


...  ...  
rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs>nd_loc);


}


lhs>nd_value = rhs;


nd_set_loc(lhs, loc);


nd_set_loc(p, lhs, loc);


asgn = NEW_OP_ASGN_AND(gettable(p, vid, &lhs_loc), lhs, loc);


}


else {


...  ...  
rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs>nd_loc);


}


asgn>nd_value = rhs;


nd_set_loc(asgn, loc);


nd_set_loc(p, asgn, loc);


}


}


else {
