Project

General

Profile

Feature #12543 ยป then_return.patch

mame (Yusuke Endoh), 07/02/2016 05:23 PM

View differences:

compile.c
ADD_LABEL(ret, end_label);
}
static void
iseq_compile_call(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped, unsigned int flag)
{
enum node_type type = nd_type(node);
int line = (int)nd_line(node);
/*
call: obj.method(...)
fcall: func(...)
vcall: func
*/
DECL_ANCHOR(recv);
DECL_ANCHOR(args);
LABEL *lskip = 0;
ID mid = node->nd_mid;
VALUE argc;
struct rb_call_info_kw_arg *keywords = NULL;
const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
INIT_ANCHOR(recv);
INIT_ANCHOR(args);
/* receiver */
if (type == NODE_CALL || type == NODE_QCALL) {
COMPILE(recv, "recv", node->nd_recv);
if (type == NODE_QCALL) {
lskip = NEW_LABEL(line);
ADD_INSN(recv, line, dup);
ADD_INSNL(recv, line, branchnil, lskip);
}
}
else if (type == NODE_FCALL || type == NODE_VCALL) {
ADD_CALL_RECEIVER(recv, line);
}
/* args */
if (nd_type(node) != NODE_VCALL) {
argc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
}
else {
argc = INT2FIX(0);
}
ADD_SEQ(ret, recv);
ADD_SEQ(ret, args);
debugp_param("call args argc", argc);
debugp_param("call method", ID2SYM(mid));
switch (nd_type(node)) {
case NODE_VCALL:
flag |= VM_CALL_VCALL;
/* VCALL is funcall, so fall through */
case NODE_FCALL:
flag |= VM_CALL_FCALL;
}
ADD_SEND_R(ret, line, mid, argc, parent_block, INT2FIX(flag), keywords);
if (lskip) {
ADD_LABEL(ret, lskip);
}
if (poped) {
ADD_INSN(ret, line, pop);
}
}
/**
compile each node
......
case NODE_QCALL:
case NODE_FCALL:
case NODE_VCALL:{ /* VCALL: variable or call */
/*
call: obj.method(...)
fcall: func(...)
vcall: func
*/
DECL_ANCHOR(recv);
DECL_ANCHOR(args);
LABEL *lskip = 0;
ID mid = node->nd_mid;
VALUE argc;
unsigned int flag = 0;
struct rb_call_info_kw_arg *keywords = NULL;
const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
INIT_ANCHOR(recv);
INIT_ANCHOR(args);
#if SUPPORT_JOKE
if (nd_type(node) == NODE_VCALL) {
ID id_bitblt;
ID id_answer;
CONST_ID(id_bitblt, "bitblt");
CONST_ID(id_answer, "the_answer_to_life_the_universe_and_everything");
if (mid == id_bitblt) {
ADD_INSN(ret, line, bitblt);
break;
}
else if (mid == id_answer) {
ADD_INSN(ret, line, answer);
break;
}
}
/* only joke */
{
ID goto_id;
ID label_id;
CONST_ID(goto_id, "__goto__");
CONST_ID(label_id, "__label__");
if (nd_type(node) == NODE_FCALL &&
(mid == goto_id || mid == label_id)) {
LABEL *label;
st_data_t data;
st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
ID label_name;
if (!labels_table) {
labels_table = st_init_numtable();
ISEQ_COMPILE_DATA(iseq)->labels_table = labels_table;
}
if (nd_type(node->nd_args->nd_head) == NODE_LIT &&
SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
label_name = SYM2ID(node->nd_args->nd_head->nd_lit);
if (!st_lookup(labels_table, (st_data_t)label_name, &data)) {
label = NEW_LABEL(line);
label->position = line;
st_insert(labels_table, (st_data_t)label_name, (st_data_t)label);
}
else {
label = (LABEL *)data;
}
}
else {
COMPILE_ERROR(ERROR_ARGS "invalid goto/label format");
}
if (mid == goto_id) {
ADD_INSNL(ret, line, jump, label);
}
else {
ADD_LABEL(ret, label);
}
break;
}
}
#endif
/* receiver */
if (type == NODE_CALL || type == NODE_QCALL) {
COMPILE(recv, "recv", node->nd_recv);
if (type == NODE_QCALL) {
lskip = NEW_LABEL(line);
ADD_INSN(recv, line, dup);
ADD_INSNL(recv, line, branchnil, lskip);
}
}
else if (type == NODE_FCALL || type == NODE_VCALL) {
ADD_CALL_RECEIVER(recv, line);
}
/* args */
if (nd_type(node) != NODE_VCALL) {
argc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
}
else {
argc = INT2FIX(0);
}
ADD_SEQ(ret, recv);
ADD_SEQ(ret, args);
debugp_param("call args argc", argc);
debugp_param("call method", ID2SYM(mid));
switch (nd_type(node)) {
case NODE_VCALL:
flag |= VM_CALL_VCALL;
/* VCALL is funcall, so fall through */
case NODE_FCALL:
flag |= VM_CALL_FCALL;
}
ADD_SEND_R(ret, line, mid, argc, parent_block, INT2FIX(flag), keywords);
if (lskip) {
ADD_LABEL(ret, lskip);
}
if (poped) {
ADD_INSN(ret, line, pop);
}
iseq_compile_call(iseq, ret, node, poped, 0);
break;
}
case NODE_TAIL:{
iseq_compile_call(iseq, ret, node->nd_head, poped, VM_CALL_TAILCALL);
break;
}
case NODE_SUPER:
defs/keywords
return, {keyword_return, keyword_return}, EXPR_MID
self, {keyword_self, keyword_self}, EXPR_END
super, {keyword_super, keyword_super}, EXPR_ARG
then, {keyword_then, keyword_then}, EXPR_BEG
then, {keyword_then, modifier_then}, EXPR_BEG
true, {keyword_true, keyword_true}, EXPR_END
undef, {keyword_undef, keyword_undef}, EXPR_FNAME|EXPR_FITEM
unless, {keyword_unless, modifier_unless}, EXPR_VALUE
defs/lex.c.src
return, {keyword_return, keyword_return}, EXPR_MID
self, {keyword_self, keyword_self}, EXPR_END
super, {keyword_super, keyword_super}, EXPR_ARG
then, {keyword_then, keyword_then}, EXPR_BEG
then, {keyword_then, modifier_then}, EXPR_BEG
true, {keyword_true, keyword_true}, EXPR_END
undef, {keyword_undef, keyword_undef}, EXPR_FNAME|EXPR_FITEM
unless, {keyword_unless, modifier_unless}, EXPR_VALUE
lex.c.blt
#line 27 "defs/keywords"
{(int)offsetof(struct stringpool_t, stringpool_str12), {keyword_end, keyword_end}, EXPR_END},
#line 44 "defs/keywords"
{(int)offsetof(struct stringpool_t, stringpool_str13), {keyword_then, keyword_then}, EXPR_BEG},
{(int)offsetof(struct stringpool_t, stringpool_str13), {keyword_then, modifier_then}, EXPR_BEG},
#line 36 "defs/keywords"
{(int)offsetof(struct stringpool_t, stringpool_str14), {keyword_not, keyword_not}, EXPR_ARG},
#line 29 "defs/keywords"
node.h
#define NODE_VCALL NODE_VCALL
NODE_QCALL,
#define NODE_QCALL NODE_QCALL
NODE_TAIL,
#define NODE_TAIL NODE_TAIL
NODE_SUPER,
#define NODE_SUPER NODE_SUPER
NODE_ZSUPER,
......
#define NEW_CALL(r,m,a) NEW_NODE(NODE_CALL,r,m,a)
#define NEW_FCALL(m,a) NEW_NODE(NODE_FCALL,0,m,a)
#define NEW_VCALL(m) NEW_NODE(NODE_VCALL,0,m,0)
#define NEW_TAIL(m) NEW_NODE(NODE_TAIL,m,0,0)
#define NEW_SUPER(a) NEW_NODE(NODE_SUPER,0,0,a)
#define NEW_ZSUPER() NEW_NODE(NODE_ZSUPER,0,0,0)
#define NEW_ARGS_AUX(r,b) NEW_NODE(NODE_ARGS_AUX,r,b,0)
parse.y
modifier_while
modifier_until
modifier_rescue
modifier_then
keyword_alias
keyword_defined
keyword_BEGIN
......
%nonassoc tLOWEST
%nonassoc tLBRACE_ARG
%nonassoc modifier_if modifier_unless modifier_while modifier_until
%nonassoc modifier_if modifier_unless modifier_while modifier_until modifier_then
%left keyword_or keyword_and
%right keyword_not
%nonassoc keyword_defined
......
$$ = dispatch1(undef, $2);
%*/
}
| expr modifier_then keyword_return
{
/*%%%*/
$$ = NEW_TAIL($1);
/*%
$$ = dispatch1(tail, $1);
%*/
}
| stmt modifier_if expr_value
{
/*%%%*/
......
/*%c
{ $$ = Qnil; }
%*/
| modifier_then
| keyword_then
| term modifier_then
/*%c%*/
/*%c
{ $$ = $2; }
%*/
| term keyword_then
/*%c%*/
/*%c
......
{modifier_while, "while"},
{modifier_until, "until"},
{modifier_rescue, "rescue"},
{modifier_then, "then"},
{keyword_alias, "alias"},
{keyword_defined, "defined?"},
{keyword_BEGIN, "BEGIN"},
    (1-1/1)