Project

General

Profile

Feature #12543 ยป then_return.patch

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

View differences:

compile.c
3826 3826
    ADD_LABEL(ret, end_label);
3827 3827
}
3828 3828

  
3829
static void
3830
iseq_compile_call(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped, unsigned int flag)
3831
{
3832
    enum node_type type = nd_type(node);
3833
    int line = (int)nd_line(node);
3834
    /*
3835
      call:  obj.method(...)
3836
      fcall: func(...)
3837
      vcall: func
3838
    */
3839
    DECL_ANCHOR(recv);
3840
    DECL_ANCHOR(args);
3841
    LABEL *lskip = 0;
3842
    ID mid = node->nd_mid;
3843
    VALUE argc;
3844
    struct rb_call_info_kw_arg *keywords = NULL;
3845
    const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
3846
    ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
3847

  
3848
    INIT_ANCHOR(recv);
3849
    INIT_ANCHOR(args);
3850
    /* receiver */
3851
    if (type == NODE_CALL || type == NODE_QCALL) {
3852
	COMPILE(recv, "recv", node->nd_recv);
3853
	if (type == NODE_QCALL) {
3854
	    lskip = NEW_LABEL(line);
3855
	    ADD_INSN(recv, line, dup);
3856
	    ADD_INSNL(recv, line, branchnil, lskip);
3857
	}
3858
    }
3859
    else if (type == NODE_FCALL || type == NODE_VCALL) {
3860
	ADD_CALL_RECEIVER(recv, line);
3861
    }
3862

  
3863
    /* args */
3864
    if (nd_type(node) != NODE_VCALL) {
3865
	argc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
3866
    }
3867
    else {
3868
	argc = INT2FIX(0);
3869
    }
3870

  
3871
    ADD_SEQ(ret, recv);
3872
    ADD_SEQ(ret, args);
3873

  
3874
    debugp_param("call args argc", argc);
3875
    debugp_param("call method", ID2SYM(mid));
3876

  
3877
    switch (nd_type(node)) {
3878
      case NODE_VCALL:
3879
	flag |= VM_CALL_VCALL;
3880
	/* VCALL is funcall, so fall through */
3881
      case NODE_FCALL:
3882
	flag |= VM_CALL_FCALL;
3883
    }
3884

  
3885
    ADD_SEND_R(ret, line, mid, argc, parent_block, INT2FIX(flag), keywords);
3886

  
3887
    if (lskip) {
3888
	ADD_LABEL(ret, lskip);
3889
    }
3890
    if (poped) {
3891
	ADD_INSN(ret, line, pop);
3892
    }
3893
}
3894

  
3829 3895
/**
3830 3896
  compile each node
3831 3897

  
......
5042 5108
      case NODE_QCALL:
5043 5109
      case NODE_FCALL:
5044 5110
      case NODE_VCALL:{		/* VCALL: variable or call */
5045
	/*
5046
	  call:  obj.method(...)
5047
	  fcall: func(...)
5048
	  vcall: func
5049
	*/
5050
	DECL_ANCHOR(recv);
5051
	DECL_ANCHOR(args);
5052
	LABEL *lskip = 0;
5053
	ID mid = node->nd_mid;
5054
	VALUE argc;
5055
	unsigned int flag = 0;
5056
	struct rb_call_info_kw_arg *keywords = NULL;
5057
	const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
5058
	ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
5059

  
5060
	INIT_ANCHOR(recv);
5061
	INIT_ANCHOR(args);
5062
#if SUPPORT_JOKE
5063
	if (nd_type(node) == NODE_VCALL) {
5064
	    ID id_bitblt;
5065
	    ID id_answer;
5066

  
5067
	    CONST_ID(id_bitblt, "bitblt");
5068
	    CONST_ID(id_answer, "the_answer_to_life_the_universe_and_everything");
5069

  
5070
	    if (mid == id_bitblt) {
5071
		ADD_INSN(ret, line, bitblt);
5072
		break;
5073
	    }
5074
	    else if (mid == id_answer) {
5075
		ADD_INSN(ret, line, answer);
5076
		break;
5077
	    }
5078
	}
5079
	/* only joke */
5080
	{
5081
	    ID goto_id;
5082
	    ID label_id;
5083

  
5084
	    CONST_ID(goto_id, "__goto__");
5085
	    CONST_ID(label_id, "__label__");
5086

  
5087
	    if (nd_type(node) == NODE_FCALL &&
5088
		(mid == goto_id || mid == label_id)) {
5089
		LABEL *label;
5090
		st_data_t data;
5091
		st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
5092
		ID label_name;
5093

  
5094
		if (!labels_table) {
5095
		    labels_table = st_init_numtable();
5096
		    ISEQ_COMPILE_DATA(iseq)->labels_table = labels_table;
5097
		}
5098
		if (nd_type(node->nd_args->nd_head) == NODE_LIT &&
5099
		    SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
5100

  
5101
		    label_name = SYM2ID(node->nd_args->nd_head->nd_lit);
5102
		    if (!st_lookup(labels_table, (st_data_t)label_name, &data)) {
5103
			label = NEW_LABEL(line);
5104
			label->position = line;
5105
			st_insert(labels_table, (st_data_t)label_name, (st_data_t)label);
5106
		    }
5107
		    else {
5108
			label = (LABEL *)data;
5109
		    }
5110
		}
5111
		else {
5112
		    COMPILE_ERROR(ERROR_ARGS "invalid goto/label format");
5113
		}
5114

  
5115

  
5116
		if (mid == goto_id) {
5117
		    ADD_INSNL(ret, line, jump, label);
5118
		}
5119
		else {
5120
		    ADD_LABEL(ret, label);
5121
		}
5122
		break;
5123
	    }
5124
	}
5125
#endif
5126
	/* receiver */
5127
	if (type == NODE_CALL || type == NODE_QCALL) {
5128
	    COMPILE(recv, "recv", node->nd_recv);
5129
	    if (type == NODE_QCALL) {
5130
		lskip = NEW_LABEL(line);
5131
		ADD_INSN(recv, line, dup);
5132
		ADD_INSNL(recv, line, branchnil, lskip);
5133
	    }
5134
	}
5135
	else if (type == NODE_FCALL || type == NODE_VCALL) {
5136
	    ADD_CALL_RECEIVER(recv, line);
5137
	}
5138

  
5139
	/* args */
5140
	if (nd_type(node) != NODE_VCALL) {
5141
	    argc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
5142
	}
5143
	else {
5144
	    argc = INT2FIX(0);
5145
	}
5146

  
5147
	ADD_SEQ(ret, recv);
5148
	ADD_SEQ(ret, args);
5149

  
5150
	debugp_param("call args argc", argc);
5151
	debugp_param("call method", ID2SYM(mid));
5152

  
5153
	switch (nd_type(node)) {
5154
	  case NODE_VCALL:
5155
	    flag |= VM_CALL_VCALL;
5156
	    /* VCALL is funcall, so fall through */
5157
	  case NODE_FCALL:
5158
	    flag |= VM_CALL_FCALL;
5159
	}
5160

  
5161
	ADD_SEND_R(ret, line, mid, argc, parent_block, INT2FIX(flag), keywords);
5162

  
5163
	if (lskip) {
5164
	    ADD_LABEL(ret, lskip);
5165
	}
5166
	if (poped) {
5167
	    ADD_INSN(ret, line, pop);
5168
	}
5111
	iseq_compile_call(iseq, ret, node, poped, 0);
5112
	break;
5113
      }
5114
      case NODE_TAIL:{
5115
	iseq_compile_call(iseq, ret, node->nd_head, poped, VM_CALL_TAILCALL);
5169 5116
	break;
5170 5117
      }
5171 5118
      case NODE_SUPER:
defs/keywords
41 41
return, {keyword_return, keyword_return}, EXPR_MID
42 42
self, {keyword_self, keyword_self}, EXPR_END
43 43
super, {keyword_super, keyword_super}, EXPR_ARG
44
then, {keyword_then, keyword_then}, EXPR_BEG
44
then, {keyword_then, modifier_then}, EXPR_BEG
45 45
true, {keyword_true, keyword_true}, EXPR_END
46 46
undef, {keyword_undef, keyword_undef}, EXPR_FNAME|EXPR_FITEM
47 47
unless, {keyword_unless, modifier_unless}, EXPR_VALUE
defs/lex.c.src
41 41
return, {keyword_return, keyword_return}, EXPR_MID
42 42
self, {keyword_self, keyword_self}, EXPR_END
43 43
super, {keyword_super, keyword_super}, EXPR_ARG
44
then, {keyword_then, keyword_then}, EXPR_BEG
44
then, {keyword_then, modifier_then}, EXPR_BEG
45 45
true, {keyword_true, keyword_true}, EXPR_END
46 46
undef, {keyword_undef, keyword_undef}, EXPR_FNAME|EXPR_FITEM
47 47
unless, {keyword_unless, modifier_unless}, EXPR_VALUE
lex.c.blt
213 213
#line 27 "defs/keywords"
214 214
      {(int)offsetof(struct stringpool_t, stringpool_str12), {keyword_end, keyword_end}, EXPR_END},
215 215
#line 44 "defs/keywords"
216
      {(int)offsetof(struct stringpool_t, stringpool_str13), {keyword_then, keyword_then}, EXPR_BEG},
216
      {(int)offsetof(struct stringpool_t, stringpool_str13), {keyword_then, modifier_then}, EXPR_BEG},
217 217
#line 36 "defs/keywords"
218 218
      {(int)offsetof(struct stringpool_t, stringpool_str14), {keyword_not, keyword_not}, EXPR_ARG},
219 219
#line 29 "defs/keywords"
node.h
98 98
#define NODE_VCALL       NODE_VCALL
99 99
    NODE_QCALL,
100 100
#define NODE_QCALL       NODE_QCALL
101
    NODE_TAIL,
102
#define NODE_TAIL        NODE_TAIL
101 103
    NODE_SUPER,
102 104
#define NODE_SUPER       NODE_SUPER
103 105
    NODE_ZSUPER,
......
420 422
#define NEW_CALL(r,m,a) NEW_NODE(NODE_CALL,r,m,a)
421 423
#define NEW_FCALL(m,a) NEW_NODE(NODE_FCALL,0,m,a)
422 424
#define NEW_VCALL(m) NEW_NODE(NODE_VCALL,0,m,0)
425
#define NEW_TAIL(m) NEW_NODE(NODE_TAIL,m,0,0)
423 426
#define NEW_SUPER(a) NEW_NODE(NODE_SUPER,0,0,a)
424 427
#define NEW_ZSUPER() NEW_NODE(NODE_ZSUPER,0,0,0)
425 428
#define NEW_ARGS_AUX(r,b) NEW_NODE(NODE_ARGS_AUX,r,b,0)
parse.y
836 836
	modifier_while
837 837
	modifier_until
838 838
	modifier_rescue
839
	modifier_then
839 840
	keyword_alias
840 841
	keyword_defined
841 842
	keyword_BEGIN
......
922 923
%nonassoc tLOWEST
923 924
%nonassoc tLBRACE_ARG
924 925

  
925
%nonassoc  modifier_if modifier_unless modifier_while modifier_until
926
%nonassoc  modifier_if modifier_unless modifier_while modifier_until modifier_then
926 927
%left  keyword_or keyword_and
927 928
%right keyword_not
928 929
%nonassoc keyword_defined
......
1187 1188
			$$ = dispatch1(undef, $2);
1188 1189
		    %*/
1189 1190
		    }
1191
		| expr modifier_then keyword_return
1192
		    {
1193
		    /*%%%*/
1194
			$$ = NEW_TAIL($1);
1195
		    /*%
1196
			$$ = dispatch1(tail, $1);
1197
		    %*/
1198
		    }
1190 1199
		| stmt modifier_if expr_value
1191 1200
		    {
1192 1201
		    /*%%%*/
......
3206 3215
		    /*%c
3207 3216
		    { $$ = Qnil; }
3208 3217
		    %*/
3218
		| modifier_then
3209 3219
		| keyword_then
3220
		| term modifier_then
3221
		    /*%c%*/
3222
		    /*%c
3223
		    { $$ = $2; }
3224
		    %*/
3210 3225
		| term keyword_then
3211 3226
		    /*%c%*/
3212 3227
		    /*%c
......
11239 11254
    {modifier_while,	"while"},
11240 11255
    {modifier_until,	"until"},
11241 11256
    {modifier_rescue,	"rescue"},
11257
    {modifier_then,	"then"},
11242 11258
    {keyword_alias,	"alias"},
11243 11259
    {keyword_defined,	"defined?"},
11244 11260
    {keyword_BEGIN,	"BEGIN"},