1 /**********************************************************************
7 Copyright (C) 2004-2007 Koichi Sasada
9 **********************************************************************/
11 #include "ruby/ruby.h"
12 #include "ruby/node.h"
16 iseq_special_block(rb_iseq_t
*iseq
, void *builder
)
19 VALUE parent
= Qfalse
;
22 if (iseq
->argc
> 1 || iseq
->arg_simple
== 0) {
27 if (iseq
->cached_special_block_builder
) {
28 if (iseq
->cached_special_block_builder
== builder
) {
29 return iseq
->cached_special_block
;
36 iseq
->cached_special_block_builder
= (void *)1;
39 if (iseq
->parent_iseq
) {
40 parent
= iseq
->parent_iseq
->self
;
42 iseqval
= rb_iseq_new_with_bopt(iseq
->node
, iseq
->name
, iseq
->filename
,
44 GC_GUARDED_PTR(builder
));
46 printf("%s\n", RSTRING_PTR(ruby_iseq_disasm(iseqval
)));
48 iseq
->cached_special_block
= iseqval
;
49 iseq
->cached_special_block_builder
= builder
;
57 new_block(NODE
* head
, NODE
* tail
)
59 head
= NEW_BLOCK(head
);
60 tail
= NEW_BLOCK(tail
);
66 new_ary(NODE
* head
, NODE
* tail
)
68 head
= NEW_ARRAY(head
);
74 new_assign(NODE
* lnode
, NODE
* rhs
)
76 switch (nd_type(lnode
)) {
78 return NEW_NODE(NODE_LASGN
, lnode
->nd_vid
, rhs
, lnode
->nd_cnt
);
79 /* NEW_LASGN(lnode->nd_vid, rhs); */
82 return NEW_GASGN(lnode
->nd_vid
, rhs
);
85 return NEW_DASGN(lnode
->nd_vid
, rhs
);
90 args
= NEW_ARRAY(lnode
->nd_args
->nd_head
);
91 args
->nd_next
= NEW_ARRAY(rhs
);
95 args
= NEW_ARRAY(rhs
);
98 return NEW_ATTRASGN(lnode
->nd_recv
,
103 rb_bug("unimplemented (block inlining): %s", ruby_node_name(nd_type(lnode
)));
109 build_Integer_times_node(rb_iseq_t
*iseq
, NODE
* node
, NODE
* lnode
,
110 VALUE param_vars
, VALUE local_vars
)
112 /* Special Block for Integer#times
133 CONST_ID(_self
, "#_self");
134 if (iseq
->argc
== 0) {
137 rb_ary_push(param_vars
, ID2SYM(e
));
138 rb_ary_push(param_vars
, ID2SYM(_self
));
143 (NEW_DVAR(e
), idLT
, new_ary(NEW_DVAR(_self
), 0)),
144 new_block(NEW_OPTBLOCK(node
),
146 NEW_CALL(NEW_DVAR(e
), idSucc
, 0))),
151 ID e
= SYM2ID(rb_ary_entry(param_vars
, 0));
155 rb_ary_push(param_vars
, ID2SYM(_self
));
156 rb_ary_push(local_vars
, ID2SYM(_e
));
159 if (nd_type(lnode
) == NODE_DASGN_CURR
) {
160 assign
= NEW_DASGN(e
, NEW_DVAR(_e
));
163 assign
= new_assign(lnode
, NEW_DVAR(_e
));
167 new_block(NEW_DASGN(_e
, NEW_DVAR(e
)),
170 new_ary(NEW_DVAR(_self
), 0)),
172 new_block(NEW_OPTBLOCK(node
),
183 invoke_Integer_times_special_block(VALUE num
)
185 rb_thread_t
*th
= GET_THREAD();
186 rb_block_t
*orig_block
= GC_GUARDED_PTR_REF(th
->cfp
->lfp
[0]);
188 if (orig_block
&& BUILTIN_TYPE(orig_block
->iseq
) != T_NODE
) {
189 VALUE tsiseqval
= iseq_special_block(orig_block
->iseq
,
190 build_Integer_times_node
);
195 rb_block_t block
= *orig_block
;
196 GetISeqPtr(tsiseqval
, tsiseq
);
198 th
->cfp
->lfp
[0] = GC_GUARDED_PTR(&block
);
199 argv
[0] = INT2FIX(0);
201 val
= rb_yield_values(2, argv
);
214 build_Range_each_node(rb_iseq_t
*iseq
, NODE
* node
, NODE
* lnode
,
215 VALUE param_vars
, VALUE local_vars
, ID mid
)
217 /* Special Block for Range#each
237 CONST_ID(_last
, "#_last");
238 if (iseq
->argc
== 0) {
241 rb_ary_push(param_vars
, ID2SYM(e
));
242 rb_ary_push(param_vars
, ID2SYM(_last
));
246 NEW_WHILE(NEW_CALL(NEW_DVAR(e
), mid
, new_ary(NEW_DVAR(_last
), 0)),
247 new_block(NEW_OPTBLOCK(node
),
249 NEW_CALL(NEW_DVAR(e
), idSucc
, 0))),
254 ID e
= SYM2ID(rb_ary_entry(param_vars
, 0));
258 rb_ary_push(param_vars
, ID2SYM(_last
));
259 rb_ary_push(local_vars
, ID2SYM(_e
));
262 if (nd_type(lnode
) == NODE_DASGN_CURR
) {
263 assign
= NEW_DASGN(e
, NEW_DVAR(_e
));
266 assign
= new_assign(lnode
, NEW_DVAR(_e
));
270 new_block(NEW_DASGN(_e
, NEW_DVAR(e
)),
273 new_ary(NEW_DVAR(_last
), 0)),
275 new_block(NEW_OPTBLOCK(node
),
286 build_Range_each_node_LE(rb_iseq_t
*iseq
, NODE
* node
, NODE
* lnode
,
287 VALUE param_vars
, VALUE local_vars
)
289 return build_Range_each_node(iseq
, node
, lnode
,
290 param_vars
, local_vars
, idLE
);
294 build_Range_each_node_LT(rb_iseq_t
*iseq
, NODE
* node
, NODE
* lnode
,
295 VALUE param_vars
, VALUE local_vars
)
297 return build_Range_each_node(iseq
, node
, lnode
,
298 param_vars
, local_vars
, idLT
);
302 invoke_Range_each_special_block(VALUE range
,
303 VALUE beg
, VALUE end
, int excl
)
305 rb_thread_t
*th
= GET_THREAD();
306 rb_block_t
*orig_block
= GC_GUARDED_PTR_REF(th
->cfp
->lfp
[0]);
308 if (BUILTIN_TYPE(orig_block
->iseq
) != T_NODE
) {
310 excl
? build_Range_each_node_LT
: build_Range_each_node_LE
;
311 VALUE tsiseqval
= iseq_special_block(orig_block
->iseq
, builder
);
317 rb_block_t block
= *orig_block
;
318 GetISeqPtr(tsiseqval
, tsiseq
);
320 th
->cfp
->lfp
[0] = GC_GUARDED_PTR(&block
);
323 val
= rb_yield_values(2, argv
);
337 build_Array_each_node(rb_iseq_t
*iseq
, NODE
* node
, NODE
* lnode
,
338 VALUE param_vars
, VALUE local_vars
)
340 /* Special block for Array#each
347 while _i < _self.length
362 while _i < _self.length
373 CONST_ID(_self
, "#_self");
375 if (iseq
->argc
== 0) {
378 rb_ary_push(param_vars
, ID2SYM(_e
));
379 rb_ary_push(param_vars
, ID2SYM(_self
));
381 rb_ary_push(local_vars
, ID2SYM(_i
));
384 new_block(NEW_DASGN(_i
, NEW_LIT(INT2FIX(0))),
385 NEW_WHILE(NEW_CALL(NEW_DVAR(_i
), idLT
,
387 (NEW_DVAR(_self
), idLength
,
389 new_block(NEW_OPTBLOCK(node
),
391 NEW_CALL(NEW_DVAR(_i
),
396 ID e
= SYM2ID(rb_ary_entry(param_vars
, 0));
399 rb_ary_push(param_vars
, ID2SYM(_self
));
401 rb_ary_push(local_vars
, ID2SYM(_i
));
403 if (nd_type(lnode
) == NODE_DASGN_CURR
) {
404 assign
= NEW_DASGN(e
,
405 NEW_CALL(NEW_DVAR(_self
), idAREF
,
406 new_ary(NEW_DVAR(_i
), 0)));
409 assign
= new_assign(lnode
,
410 NEW_CALL(NEW_DVAR(_self
), idAREF
,
411 new_ary(NEW_DVAR(_i
), 0)));
415 new_block(NEW_DASGN(_i
, NEW_LIT(INT2FIX(0))),
416 NEW_WHILE(NEW_CALL(NEW_DVAR(_i
), idLT
,
418 (NEW_DVAR(_self
), idLength
,
419 0), 0)), new_block(assign
,
436 invoke_Array_each_special_block(VALUE ary
)
438 rb_thread_t
*th
= GET_THREAD();
439 rb_block_t
*orig_block
= GC_GUARDED_PTR_REF(th
->cfp
->lfp
[0]);
441 if (BUILTIN_TYPE(orig_block
->iseq
) != T_NODE
) {
442 VALUE tsiseqval
= iseq_special_block(orig_block
->iseq
,
443 build_Array_each_node
);
449 rb_block_t block
= *orig_block
;
450 GetISeqPtr(tsiseqval
, tsiseq
);
452 th
->cfp
->lfp
[0] = GC_GUARDED_PTR(&block
);
455 val
= rb_yield_values(2, argv
);