fastruby 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,91 @@
1
+ =begin
2
+
3
+ This file is part of the fastruby project, http://github.com/tario/fastruby
4
+
5
+ Copyright (c) 2011 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ fastruby is free software: you can redistribute it and/or modify
8
+ it under the terms of the gnu general public license as published by
9
+ the free software foundation, either version 3 of the license, or
10
+ (at your option) any later version.
11
+
12
+ fastruby is distributed in the hope that it will be useful,
13
+ but without any warranty; without even the implied warranty of
14
+ merchantability or fitness for a particular purpose. see the
15
+ gnu general public license for more details.
16
+
17
+ you should have received a copy of the gnu general public license
18
+ along with fastruby. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ =end
21
+ module FastRuby
22
+ module FlowControlTranslator
23
+
24
+ register_translator_module self
25
+
26
+ def to_c_case(tree)
27
+
28
+ tmpvarname = "tmp" + rand(1000000).to_s;
29
+
30
+ code = tree[2..-2].map{|subtree|
31
+
32
+ # this subtree is a when
33
+ subtree[1][1..-1].map{|subsubtree|
34
+ c_calltree = s(:call, nil, :inline_c, s(:arglist, s(:str, tmpvarname), s(:false)))
35
+ calltree = s(:call, subsubtree, :===, s(:arglist, c_calltree))
36
+ "
37
+ if (RTEST(#{to_c_call(calltree, tmpvarname)})) {
38
+ return #{to_c(subtree[2])};
39
+ }
40
+
41
+ "
42
+ }.join("\n")
43
+
44
+ }.join("\n")
45
+
46
+ inline_block "
47
+
48
+ VALUE #{tmpvarname} = #{to_c tree[1]};
49
+
50
+ #{code};
51
+
52
+ return #{to_c tree[-1]};
53
+ "
54
+ end
55
+
56
+ def to_c_if(tree)
57
+ condition_tree = tree[1]
58
+ impl_tree = tree[2]
59
+ else_tree = tree[3]
60
+
61
+ inline_block "
62
+ if (RTEST(#{to_c condition_tree})) {
63
+ last_expression = #{to_c impl_tree};
64
+ }#{else_tree ?
65
+ " else {
66
+ last_expression = #{to_c else_tree};
67
+ }
68
+ " : ""
69
+ }
70
+
71
+ return last_expression;
72
+ "
73
+ end
74
+
75
+ def to_c_for(tree)
76
+ alter_tree = tree.dup
77
+ alter_tree[0] = :iter
78
+ alter_tree[1] = [:call, alter_tree[1], :each, [:arglist]]
79
+ to_c alter_tree
80
+ end
81
+
82
+ def to_c_while(tree)
83
+ inline_block("
84
+ while (#{to_c tree[1]}) {
85
+ #{to_c tree[2]};
86
+ }
87
+ return Qnil;
88
+ ")
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,584 @@
1
+ =begin
2
+
3
+ This file is part of the fastruby project, http://github.com/tario/fastruby
4
+
5
+ Copyright (c) 2011 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ fastruby is free software: you can redistribute it and/or modify
8
+ it under the terms of the gnu general public license as published by
9
+ the free software foundation, either version 3 of the license, or
10
+ (at your option) any later version.
11
+
12
+ fastruby is distributed in the hope that it will be useful,
13
+ but without any warranty; without even the implied warranty of
14
+ merchantability or fitness for a particular purpose. see the
15
+ gnu general public license for more details.
16
+
17
+ you should have received a copy of the gnu general public license
18
+ along with fastruby. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ =end
21
+ module FastRuby
22
+ module IterTranslator
23
+
24
+ register_translator_module IterTranslator
25
+
26
+ def to_c_iter(tree)
27
+
28
+ call_tree = tree[1]
29
+ args_tree = tree[2]
30
+ recv_tree = call_tree[1]
31
+
32
+ directive_code = directive(call_tree)
33
+ if directive_code
34
+ return directive_code
35
+ end
36
+
37
+ other_call_tree = call_tree.dup
38
+ other_call_tree[1] = s(:lvar, :arg)
39
+
40
+ mname = call_tree[2]
41
+
42
+ call_args_tree = call_tree[3]
43
+
44
+ caller_code = nil
45
+
46
+ recvtype = infer_type(recv_tree || s(:self))
47
+
48
+ address = nil
49
+ mobject = nil
50
+ len = nil
51
+
52
+ extra_inference = {}
53
+
54
+ if recvtype
55
+
56
+ inference_complete = true
57
+ signature = [recvtype]
58
+
59
+ call_args_tree[1..-1].each do |arg|
60
+ argtype = infer_type(arg)
61
+ if argtype
62
+ signature << argtype
63
+ else
64
+ inference_complete = false
65
+ end
66
+ end
67
+
68
+ if recvtype.respond_to? :fastruby_method and inference_complete
69
+ method_tree = nil
70
+ begin
71
+ method_tree = recvtype.instance_method(call_tree[2]).fastruby.tree
72
+ rescue NoMethodError
73
+ end
74
+
75
+ if method_tree
76
+ mobject = recvtype.build(signature, call_tree[2])
77
+ yield_signature = mobject.yield_signature
78
+
79
+ if not args_tree
80
+ elsif args_tree.first == :lasgn
81
+ if yield_signature[0]
82
+ extra_inference[args_tree.last] = yield_signature[0]
83
+ end
84
+ elsif args_tree.first == :masgn
85
+ yield_args = args_tree[1][1..-1].map(&:last)
86
+ (0...yield_signature.size-1).each do |i|
87
+ extra_inference[yield_args[i]] = yield_signature[i]
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ anonymous_impl = tree[3]
95
+
96
+ str_lvar_initialization = "#{@frame_struct} *pframe;
97
+ #{@locals_struct} *plocals;
98
+ pframe = (void*)param;
99
+ plocals = (void*)pframe->plocals;
100
+ "
101
+
102
+ str_arg_initialization = ""
103
+
104
+ str_impl = ""
105
+
106
+ with_extra_inference(extra_inference) do
107
+
108
+ on_block do
109
+ # if impl_tree is a block, implement the last node with a return
110
+ if anonymous_impl
111
+ if anonymous_impl[0] == :block
112
+ str_impl = anonymous_impl[1..-2].map{ |subtree|
113
+ to_c(subtree)
114
+ }.join(";")
115
+
116
+ if anonymous_impl[-1][0] != :return and anonymous_impl[-1][0] != :break and anonymous_impl[-1][0] != :next
117
+ str_impl = str_impl + ";last_expression = (#{to_c(anonymous_impl[-1])});"
118
+ else
119
+ str_impl = str_impl + ";#{to_c(anonymous_impl[-1])};"
120
+ end
121
+ else
122
+ if anonymous_impl[0] != :return and anonymous_impl[0] != :break and anonymous_impl[0] != :next
123
+ str_impl = str_impl + ";last_expression = (#{to_c(anonymous_impl)});"
124
+ else
125
+ str_impl = str_impl + ";#{to_c(anonymous_impl)};"
126
+ end
127
+ end
128
+ else
129
+ str_impl = "last_expression = Qnil;"
130
+ end
131
+ end
132
+ end
133
+
134
+
135
+ if not args_tree
136
+ str_arg_initialization = ""
137
+ elsif args_tree.first == :lasgn
138
+ str_arg_initialization = "plocals->#{args_tree[1]} = arg;"
139
+ elsif args_tree.first == :masgn
140
+ arguments = args_tree[1][1..-1].map(&:last)
141
+
142
+ (0..arguments.size-1).each do |i|
143
+ str_arg_initialization << "plocals->#{arguments[i]} = rb_ary_entry(arg,#{i});\n"
144
+ end
145
+ end
146
+ rb_funcall_caller_code = nil
147
+
148
+ if call_args_tree.size > 1
149
+
150
+ str_recv = "pframe->next_recv"
151
+
152
+ str_recv = "plocals->self" unless recv_tree
153
+ if call_args_tree.last[0] == :splat
154
+ rb_funcall_caller_code = proc { |name| "
155
+ static VALUE #{name}(VALUE param) {
156
+ // call to #{call_tree[2]}
157
+
158
+ #{str_lvar_initialization}
159
+
160
+ VALUE array = #{to_c call_args_tree.last[1]};
161
+
162
+ if (TYPE(array) != T_ARRAY) {
163
+ array = rb_ary_new4(1,&array);
164
+ }
165
+
166
+ int argc = #{call_args_tree.size-2};
167
+ VALUE argv[#{call_args_tree.size} + RARRAY(array)->len];
168
+
169
+ #{
170
+ i = -1
171
+ call_args_tree[1..-2].map {|arg|
172
+ i = i + 1
173
+ "argv[#{i}] = #{to_c arg}"
174
+ }.join(";\n")
175
+ };
176
+
177
+ int array_len = RARRAY(array)->len;
178
+
179
+ int i;
180
+ for (i=0; i<array_len;i++) {
181
+ argv[argc] = rb_ary_entry(array,i);
182
+ argc++;
183
+ }
184
+
185
+ return rb_funcall2(#{str_recv}, #{intern_num call_tree[2]}, argc, argv);
186
+ }
187
+ "
188
+ }
189
+ else
190
+ str_called_code_args = call_args_tree[1..-1].map{ |subtree| to_c subtree }.join(",")
191
+ rb_funcall_caller_code = proc { |name| "
192
+ static VALUE #{name}(VALUE param) {
193
+ // call to #{call_tree[2]}
194
+
195
+ #{str_lvar_initialization}
196
+ return rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, #{call_args_tree.size-1}, #{str_called_code_args});
197
+ }
198
+ "
199
+ }
200
+ end
201
+
202
+ rb_funcall_caller_code_with_lambda = rb_funcall_caller_code
203
+ else
204
+ str_recv = "pframe->next_recv"
205
+ str_recv = "plocals->self" unless recv_tree
206
+
207
+ rb_funcall_caller_code = proc { |name| "
208
+ static VALUE #{name}(VALUE param) {
209
+ // call to #{call_tree[2]}
210
+ #{str_lvar_initialization}
211
+ return rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);
212
+ }
213
+ "
214
+ }
215
+
216
+ rb_funcall_caller_code_with_lambda = proc { |name| "
217
+ static VALUE #{name}(VALUE param) {
218
+ // call to #{call_tree[2]}
219
+ #{str_lvar_initialization}
220
+ VALUE ret = rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, 0);
221
+
222
+ // freeze all stacks
223
+ struct FASTRUBYTHREADDATA* thread_data = rb_current_thread_data();
224
+
225
+ if (thread_data != 0) {
226
+ VALUE rb_stack_chunk = thread_data->rb_stack_chunk;
227
+
228
+ // add reference to stack chunk to lambda object
229
+ rb_ivar_set(ret,#{intern_num :_fastruby_stack_chunk},rb_stack_chunk);
230
+
231
+ // freeze the complete chain of stack chunks
232
+ while (rb_stack_chunk != Qnil) {
233
+ struct STACKCHUNK* stack_chunk;
234
+ Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
235
+
236
+ stack_chunk_freeze(stack_chunk);
237
+
238
+ rb_stack_chunk = rb_ivar_get(rb_stack_chunk,#{intern_num :_parent_stack_chunk});
239
+ }
240
+ }
241
+
242
+ return ret;
243
+ }
244
+ "
245
+ }
246
+
247
+ end
248
+
249
+ rb_funcall_block_code_with_lambda = proc { |name| "
250
+ static VALUE #{name}(VALUE arg, VALUE _plocals) {
251
+ // block for call to #{call_tree[2]}
252
+ VALUE last_expression = Qnil;
253
+
254
+ #{@frame_struct} frame;
255
+ #{@frame_struct} *pframe = (void*)&frame;
256
+ #{@locals_struct} *plocals = (void*)_plocals;
257
+
258
+ frame.plocals = plocals;
259
+ frame.parent_frame = 0;
260
+ frame.return_value = Qnil;
261
+ frame.rescue = 0;
262
+ frame.targetted = 0;
263
+ frame.thread_data = rb_current_thread_data();
264
+
265
+ // create a fake parent frame representing the lambda method frame and a fake locals scope
266
+ VALUE old_call_frame = ((typeof(plocals))(pframe->plocals))->call_frame;
267
+ ((typeof(plocals))(pframe->plocals))->call_frame = LONG2FIX(pframe);
268
+
269
+ int aux = setjmp(frame.jmp);
270
+ if (aux != 0) {
271
+ if (aux == FASTRUBY_TAG_BREAK) {
272
+ return frame.return_value;
273
+ } else if (aux == FASTRUBY_TAG_NEXT) {
274
+ return pframe->thread_data->accumulator;
275
+ } else if (aux == FASTRUBY_TAG_REDO) {
276
+ // do nothing and let execute the block again
277
+ } else if (aux == FASTRUBY_TAG_RAISE) {
278
+ rb_funcall(((typeof(plocals))(pframe->plocals))->self, #{intern_num :raise}, 1, frame.thread_data->exception);
279
+ return Qnil;
280
+ } else {
281
+ if (aux == FASTRUBY_TAG_RETURN) {
282
+ if (plocals->targetted == 1) {
283
+ ((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
284
+ return ((typeof(plocals))(pframe->plocals))->return_value;
285
+ } else {
286
+ rb_raise(rb_eLocalJumpError, \"unexpected return\");
287
+ }
288
+ } else {
289
+ rb_raise(rb_eLocalJumpError, \"unexpected return\");
290
+ }
291
+
292
+ ((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
293
+ return frame.return_value;
294
+
295
+ }
296
+ }
297
+
298
+ #{str_arg_initialization}
299
+ #{str_impl}
300
+
301
+ ((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
302
+ return last_expression;
303
+ }
304
+ "
305
+ }
306
+
307
+ rb_funcall_block_code_proc_new = proc { |name| "
308
+ static VALUE #{name}(VALUE arg, VALUE _plocals) {
309
+ // block for call to #{call_tree[2]}
310
+ VALUE last_expression = Qnil;
311
+
312
+ #{@frame_struct} frame;
313
+ #{@frame_struct} *pframe = (void*)&frame;
314
+ #{@locals_struct} *plocals = (void*)_plocals;
315
+
316
+ frame.plocals = plocals;
317
+ frame.parent_frame = 0;
318
+ frame.return_value = Qnil;
319
+ frame.rescue = 0;
320
+ frame.targetted = 0;
321
+ frame.thread_data = rb_current_thread_data();
322
+
323
+ // create a fake parent frame representing the lambda method frame and a fake locals scope
324
+ VALUE old_call_frame = ((typeof(plocals))(pframe->plocals))->call_frame;
325
+ ((typeof(plocals))(pframe->plocals))->call_frame = LONG2FIX(pframe);
326
+
327
+ int aux = setjmp(frame.jmp);
328
+ if (aux != 0) {
329
+ if (aux == FASTRUBY_TAG_NEXT) {
330
+ return pframe->thread_data->accumulator;
331
+ } else if (aux == FASTRUBY_TAG_REDO) {
332
+ // do nothing and let execute the block again
333
+ } else if (aux == FASTRUBY_TAG_RAISE) {
334
+ rb_funcall(((typeof(plocals))(pframe->plocals))->self, #{intern_num :raise}, 1, frame.thread_data->exception);
335
+ return Qnil;
336
+ } else {
337
+ if (plocals->targetted == 1) {
338
+ if (plocals->active == Qfalse) {
339
+ rb_raise(rb_eLocalJumpError,\"return from proc-closure\");
340
+ } else {
341
+ ((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
342
+ rb_jump_tag(aux);
343
+ }
344
+ } else {
345
+ rb_raise(rb_eLocalJumpError, \"unexpected return\");
346
+ }
347
+ }
348
+ }
349
+
350
+ #{str_arg_initialization}
351
+ #{str_impl}
352
+
353
+ ((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
354
+
355
+ return last_expression;
356
+ }
357
+ "
358
+ }
359
+
360
+
361
+ rb_funcall_block_code = proc { |name| "
362
+ static VALUE #{name}(VALUE arg, VALUE _plocals) {
363
+ // block for call to #{call_tree[2]}
364
+ VALUE last_expression = Qnil;
365
+
366
+ #{@frame_struct} frame;
367
+ #{@frame_struct} *pframe = (void*)&frame;
368
+ #{@locals_struct} *plocals = (void*)_plocals;
369
+
370
+ frame.plocals = plocals;
371
+ frame.parent_frame = 0;
372
+ frame.return_value = Qnil;
373
+ frame.rescue = 0;
374
+ frame.targetted = 0;
375
+ frame.thread_data = rb_current_thread_data();
376
+
377
+ int aux = setjmp(frame.jmp);
378
+ if (aux != 0) {
379
+
380
+ if (aux == FASTRUBY_TAG_NEXT) {
381
+ return pframe->thread_data->accumulator;
382
+ } else if (aux == FASTRUBY_TAG_REDO) {
383
+ // do nothing and let execute the block again
384
+ } else {
385
+ rb_jump_tag(aux);
386
+ return frame.return_value;
387
+ }
388
+ }
389
+
390
+
391
+ #{str_arg_initialization}
392
+ #{str_impl}
393
+
394
+ return last_expression;
395
+ }
396
+ "
397
+ }
398
+
399
+
400
+ fastruby_str_arg_initialization = ""
401
+
402
+ if not args_tree
403
+ fastruby_str_arg_initialization = ""
404
+ elsif args_tree.first == :lasgn
405
+ fastruby_str_arg_initialization = "plocals->#{args_tree[1]} = argv[0];"
406
+ elsif args_tree.first == :masgn
407
+ arguments = args_tree[1][1..-1].map(&:last)
408
+
409
+ (0..arguments.size-1).each do |i|
410
+ fastruby_str_arg_initialization << "plocals->#{arguments[i]} = #{i} < argc ? argv[#{i}] : Qnil;\n"
411
+ end
412
+ end
413
+
414
+ block_code = proc { |name| "
415
+ static VALUE #{name}(int argc, VALUE* argv, VALUE _locals, VALUE _parent_frame) {
416
+ // block for call to #{call_tree[2]}
417
+ VALUE last_expression = Qnil;
418
+ #{@frame_struct} frame;
419
+ #{@frame_struct} *pframe = (void*)&frame;
420
+ #{@frame_struct} *parent_frame = (void*)_parent_frame;
421
+ #{@locals_struct} *plocals;
422
+
423
+ frame.plocals = (void*)_locals;
424
+ frame.parent_frame = parent_frame;
425
+ frame.return_value = Qnil;
426
+ frame.rescue = 0;
427
+ frame.targetted = 0;
428
+ frame.thread_data = parent_frame->thread_data;
429
+ if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
430
+
431
+ plocals = frame.plocals;
432
+
433
+ int aux = setjmp(frame.jmp);
434
+ if (aux != 0) {
435
+ if (pframe->targetted == 0) {
436
+ if (aux == FASTRUBY_TAG_NEXT) {
437
+ return pframe->thread_data->accumulator;
438
+ } else if (aux == FASTRUBY_TAG_REDO) {
439
+ // do nothing and let execute the block again
440
+ } else {
441
+ longjmp(((typeof(pframe))_parent_frame)->jmp,aux);
442
+ }
443
+ }
444
+
445
+ }
446
+
447
+ #{fastruby_str_arg_initialization}
448
+ #{str_impl}
449
+
450
+ return last_expression;
451
+ }
452
+ "
453
+ }
454
+
455
+ str_recv = "plocals->self"
456
+
457
+ if recv_tree
458
+ str_recv = to_c recv_tree
459
+ end
460
+
461
+ caller_code = nil
462
+ convention_global_name = add_global_name("int",0)
463
+
464
+ call_frame_struct_code = "
465
+ #{@block_struct} block;
466
+ #{@locals_struct} *plocals = (void*)param;
467
+
468
+ block.block_function_address = (void*)#{anonymous_function(&block_code)};
469
+ block.block_function_param = (void*)param;
470
+
471
+ // create a call_frame
472
+ #{@frame_struct} call_frame;
473
+
474
+ call_frame.parent_frame = (void*)pframe;
475
+ call_frame.plocals = plocals;
476
+ call_frame.return_value = Qnil;
477
+ call_frame.targetted = 0;
478
+ call_frame.thread_data = rb_current_thread_data();
479
+
480
+ VALUE old_call_frame = plocals->call_frame;
481
+ plocals->call_frame = LONG2FIX(&call_frame);
482
+
483
+ int aux = setjmp(call_frame.jmp);
484
+ if (aux != 0) {
485
+ #{@frame_struct}* pframe_ = (void*)pframe;
486
+
487
+ if (aux == FASTRUBY_TAG_RETRY ) {
488
+ // do nothing and let the call execute again
489
+ } else {
490
+ if (call_frame.targetted == 0) {
491
+ longjmp(pframe_->jmp,aux);
492
+ }
493
+
494
+ plocals->call_frame = old_call_frame;
495
+ return call_frame.return_value;
496
+ }
497
+ }
498
+ "
499
+
500
+ funcall_call_code = "
501
+ return #{
502
+ frame_call(
503
+ protected_block(inline_block("
504
+
505
+ pframe->next_recv = #{recv_tree ? to_c(recv_tree) : "plocals->self"};
506
+
507
+ NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
508
+ void* caller_func;
509
+ void* block_func;
510
+
511
+ if (
512
+ node == #{@proc_node_gvar} ||
513
+ node == #{@lambda_node_gvar}
514
+ ) {
515
+
516
+ caller_func = #{anonymous_function(&rb_funcall_caller_code_with_lambda)};
517
+ block_func = #{anonymous_function(&rb_funcall_block_code_with_lambda)};
518
+ } else if (node == #{@procnew_node_gvar} && pframe->next_recv == rb_cProc) {
519
+ caller_func = #{anonymous_function(&rb_funcall_caller_code_with_lambda)};
520
+ block_func = #{anonymous_function(&rb_funcall_block_code_proc_new)};
521
+ } else {
522
+ caller_func = #{anonymous_function(&rb_funcall_caller_code)};
523
+ block_func = #{anonymous_function(&rb_funcall_block_code)};
524
+ }
525
+
526
+ return rb_iterate(
527
+ caller_func,
528
+ (VALUE)pframe,
529
+ block_func,
530
+ (VALUE)plocals);
531
+
532
+ "), true)
533
+ )
534
+ };
535
+ "
536
+
537
+ if call_args_tree.size > 1 ? call_args_tree.last[0] == :splat : false
538
+ inline_block "
539
+ #{funcall_call_code}
540
+ "
541
+ else
542
+
543
+ if call_args_tree.size > 1
544
+ value_cast = ( ["VALUE"]*(call_tree[3].size) ).join(",") + ", VALUE, VALUE"
545
+
546
+ str_called_code_args = call_tree[3][1..-1].map{|subtree| to_c subtree}.join(",")
547
+
548
+ caller_code = proc { |name| "
549
+ static VALUE #{name}(VALUE param, VALUE pframe) {
550
+ // call to #{call_tree[2]}
551
+ #{call_frame_struct_code}
552
+
553
+ VALUE ret = ((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name)})(#{str_recv}, (VALUE)&block, (VALUE)&call_frame, #{str_called_code_args});
554
+ plocals->call_frame = old_call_frame;
555
+ return ret;
556
+ }
557
+ "
558
+ }
559
+
560
+ else
561
+ caller_code = proc { |name| "
562
+ static VALUE #{name}(VALUE param, VALUE pframe) {
563
+ #{call_frame_struct_code}
564
+
565
+ // call to #{call_tree[2]}
566
+ VALUE ret = ((VALUE(*)(VALUE,VALUE,VALUE))#{encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name)})(#{str_recv}, (VALUE)&block, (VALUE)&call_frame);
567
+ plocals->call_frame = old_call_frame;
568
+ return ret;
569
+ }
570
+ "
571
+ }
572
+ end
573
+
574
+ inline_block "
575
+ if (#{convention_global_name}) {
576
+ return #{anonymous_function(&caller_code)}((VALUE)plocals, (VALUE)pframe);
577
+ } else {
578
+ #{funcall_call_code}
579
+ }
580
+ "
581
+ end
582
+ end
583
+ end
584
+ end