fastruby 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +21 -0
- data/README +1 -2
- data/Rakefile +2 -2
- data/TODO +0 -2
- data/lib/fastruby/builder.rb +19 -1
- data/lib/fastruby/custom_require.rb +48 -0
- data/lib/fastruby/object.rb +73 -10
- data/lib/fastruby/translator.rb +637 -131
- data/lib/fastruby.rb +4 -0
- data/spec/base_spec.rb +37 -0
- data/spec/block/break_spec.rb +190 -0
- data/spec/block/next_spec.rb +85 -0
- data/spec/exception_spec.rb +440 -0
- data/spec/module_spec.rb +36 -0
- data/spec/return_spec.rb +99 -0
- data/spec/singleton_spec.rb +76 -0
- data/spec/sugar_spec.rb +2 -2
- data/spec/variable_spec.rb +64 -0
- metadata +12 -4
data/lib/fastruby/translator.rb
CHANGED
@@ -26,6 +26,14 @@ require "fastruby/method_extension"
|
|
26
26
|
module FastRuby
|
27
27
|
class Context
|
28
28
|
|
29
|
+
class UnwindFastrubyFrame < Exception
|
30
|
+
def initialize(ex,target_frame,return_value)
|
31
|
+
@ex = ex
|
32
|
+
@target_frame = target_frame
|
33
|
+
@return_value = return_value
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
29
37
|
attr_accessor :infer_lvar_map
|
30
38
|
attr_accessor :alt_method_name
|
31
39
|
attr_accessor :locals
|
@@ -34,32 +42,48 @@ module FastRuby
|
|
34
42
|
attr_reader :extra_code
|
35
43
|
attr_reader :yield_signature
|
36
44
|
|
37
|
-
def initialize
|
45
|
+
def initialize(common_func = true)
|
38
46
|
@infer_lvar_map = Hash.new
|
39
47
|
@extra_code = ""
|
40
48
|
@options = {}
|
49
|
+
@frame_struct = "struct {
|
50
|
+
void* parent_frame;
|
51
|
+
void* target_frame;
|
52
|
+
void* plocals;
|
53
|
+
jmp_buf jmp;
|
54
|
+
VALUE return_value;
|
55
|
+
VALUE exception;
|
56
|
+
int rescue;
|
57
|
+
VALUE last_error;
|
58
|
+
}"
|
59
|
+
|
60
|
+
@block_struct = "struct {
|
61
|
+
void* block_function_address;
|
62
|
+
void* block_function_param;
|
63
|
+
}"
|
41
64
|
|
42
65
|
extra_code << '#include "node.h"
|
43
66
|
'
|
44
67
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
extra_code << "static VALUE _rb_ivar_set(VALUE recv,ID idvar, VALUE value) {
|
52
|
-
rb_ivar_set(recv,idvar,value);
|
53
|
-
return value;
|
54
|
-
}
|
55
|
-
"
|
68
|
+
if common_func
|
69
|
+
extra_code << "static VALUE _rb_gvar_set(void* ge,VALUE value) {
|
70
|
+
rb_gvar_set((struct global_entry*)ge,value);
|
71
|
+
return value;
|
72
|
+
}
|
73
|
+
"
|
56
74
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
75
|
+
extra_code << "static VALUE _rb_ivar_set(VALUE recv,ID idvar, VALUE value) {
|
76
|
+
rb_ivar_set(recv,idvar,value);
|
77
|
+
return value;
|
78
|
+
}
|
79
|
+
"
|
62
80
|
|
81
|
+
extra_code << "static VALUE _lvar_assing(VALUE* destination,VALUE value) {
|
82
|
+
*destination = value;
|
83
|
+
return value;
|
84
|
+
}
|
85
|
+
"
|
86
|
+
end
|
63
87
|
end
|
64
88
|
|
65
89
|
def on_block
|
@@ -71,10 +95,10 @@ module FastRuby
|
|
71
95
|
send("to_c_" + tree[0].to_s, tree);
|
72
96
|
end
|
73
97
|
|
74
|
-
def anonymous_function
|
98
|
+
def anonymous_function
|
75
99
|
|
76
100
|
name = "anonymous" + rand(10000000).to_s
|
77
|
-
extra_code <<
|
101
|
+
extra_code << yield(name)
|
78
102
|
|
79
103
|
name
|
80
104
|
end
|
@@ -105,9 +129,6 @@ module FastRuby
|
|
105
129
|
|
106
130
|
caller_code = nil
|
107
131
|
|
108
|
-
str_lvar_initialization = @locals_struct + " *plocals;
|
109
|
-
plocals = (void*)param;"
|
110
|
-
|
111
132
|
recvtype = infer_type(recv_tree || s(:self))
|
112
133
|
|
113
134
|
address = nil
|
@@ -179,14 +200,19 @@ module FastRuby
|
|
179
200
|
|
180
201
|
anonymous_impl = tree[3]
|
181
202
|
|
182
|
-
str_lvar_initialization = @
|
183
|
-
|
203
|
+
str_lvar_initialization = "#{@frame_struct} *pframe;
|
204
|
+
#{@locals_struct} *plocals;
|
205
|
+
pframe = (void*)param;
|
206
|
+
plocals = (void*)pframe->plocals;
|
207
|
+
"
|
184
208
|
|
185
209
|
str_arg_initialization = ""
|
186
210
|
|
187
211
|
str_impl = ""
|
188
212
|
|
189
213
|
with_extra_inference(extra_inference) do
|
214
|
+
|
215
|
+
on_block do
|
190
216
|
# if impl_tree is a block, implement the last node with a return
|
191
217
|
if anonymous_impl
|
192
218
|
if anonymous_impl[0] == :block
|
@@ -209,7 +235,7 @@ module FastRuby
|
|
209
235
|
else
|
210
236
|
str_impl = "last_expression = Qnil;"
|
211
237
|
end
|
212
|
-
|
238
|
+
end
|
213
239
|
end
|
214
240
|
|
215
241
|
if convention == :ruby or convention == :cruby
|
@@ -260,11 +286,44 @@ module FastRuby
|
|
260
286
|
str_arg_initialization
|
261
287
|
|
262
288
|
block_code = proc { |name| "
|
263
|
-
static VALUE #{name}(VALUE arg, VALUE
|
289
|
+
static VALUE #{name}(VALUE arg, VALUE _parent_frame) {
|
264
290
|
// block for call to #{call_tree[2]}
|
265
291
|
VALUE last_expression = Qnil;
|
266
292
|
|
267
|
-
#{
|
293
|
+
#{@frame_struct} frame;
|
294
|
+
#{@frame_struct} *pframe = (void*)&frame;
|
295
|
+
#{@frame_struct} *parent_frame = (void*)_parent_frame;
|
296
|
+
#{@locals_struct} *plocals;
|
297
|
+
|
298
|
+
frame.plocals = parent_frame->plocals;
|
299
|
+
frame.parent_frame = parent_frame;
|
300
|
+
frame.return_value = Qnil;
|
301
|
+
frame.target_frame = &frame;
|
302
|
+
frame.exception = Qnil;
|
303
|
+
frame.rescue = 0;
|
304
|
+
|
305
|
+
plocals = frame.plocals;
|
306
|
+
|
307
|
+
if (setjmp(frame.jmp) != 0) {
|
308
|
+
if (pframe->target_frame != pframe) {
|
309
|
+
if (pframe->target_frame == (void*)-3) {
|
310
|
+
return pframe->return_value;
|
311
|
+
}
|
312
|
+
|
313
|
+
VALUE ex = rb_funcall(
|
314
|
+
(VALUE)#{UnwindFastrubyFrame.internal_value},
|
315
|
+
#{:new.to_i},
|
316
|
+
3,
|
317
|
+
pframe->exception,
|
318
|
+
LONG2FIX(pframe->target_frame),
|
319
|
+
pframe->return_value
|
320
|
+
);
|
321
|
+
rb_funcall(plocals->self, #{:raise.to_i}, 1, ex);
|
322
|
+
}
|
323
|
+
return frame.return_value;
|
324
|
+
}
|
325
|
+
|
326
|
+
|
268
327
|
#{str_arg_initialization}
|
269
328
|
#{str_impl}
|
270
329
|
|
@@ -273,7 +332,8 @@ module FastRuby
|
|
273
332
|
"
|
274
333
|
}
|
275
334
|
|
276
|
-
"rb_iterate(#{anonymous_function(caller_code)}, (VALUE)
|
335
|
+
protected_block("rb_iterate(#{anonymous_function(&caller_code)}, (VALUE)pframe, #{anonymous_function(&block_code)}, (VALUE)pframe)", true)
|
336
|
+
|
277
337
|
elsif convention == :fastruby
|
278
338
|
|
279
339
|
str_arg_initialization = ""
|
@@ -291,11 +351,37 @@ module FastRuby
|
|
291
351
|
end
|
292
352
|
|
293
353
|
block_code = proc { |name| "
|
294
|
-
static VALUE #{name}(int argc, VALUE* argv, VALUE
|
354
|
+
static VALUE #{name}(int argc, VALUE* argv, VALUE _locals, VALUE _parent_frame) {
|
295
355
|
// block for call to #{call_tree[2]}
|
296
356
|
VALUE last_expression = Qnil;
|
357
|
+
#{@frame_struct} frame;
|
358
|
+
#{@frame_struct} *pframe = (void*)&frame;
|
359
|
+
#{@frame_struct} *parent_frame = (void*)_parent_frame;
|
360
|
+
#{@locals_struct} *plocals;
|
361
|
+
|
362
|
+
frame.plocals = (void*)_locals;
|
363
|
+
frame.parent_frame = parent_frame;
|
364
|
+
frame.return_value = Qnil;
|
365
|
+
frame.target_frame = &frame;
|
366
|
+
frame.exception = Qnil;
|
367
|
+
frame.rescue = 0;
|
368
|
+
|
369
|
+
plocals = frame.plocals;
|
370
|
+
|
371
|
+
if (setjmp(frame.jmp) != 0) {
|
372
|
+
if (pframe->target_frame != pframe) {
|
373
|
+
if (pframe->target_frame == (void*)-3) {
|
374
|
+
return pframe->return_value;
|
375
|
+
}
|
376
|
+
// raise exception
|
377
|
+
((typeof(pframe))_parent_frame)->exception = pframe->exception;
|
378
|
+
((typeof(pframe))_parent_frame)->target_frame = pframe->target_frame;
|
379
|
+
((typeof(pframe))_parent_frame)->return_value = pframe->return_value;
|
380
|
+
longjmp(((typeof(pframe))_parent_frame)->jmp,1);
|
381
|
+
}
|
382
|
+
|
383
|
+
}
|
297
384
|
|
298
|
-
#{str_lvar_initialization};
|
299
385
|
#{str_arg_initialization}
|
300
386
|
#{str_impl}
|
301
387
|
|
@@ -313,59 +399,60 @@ module FastRuby
|
|
313
399
|
|
314
400
|
if call_args_tree.size > 1
|
315
401
|
value_cast = ( ["VALUE"]*(call_tree[3].size) ).join(",")
|
316
|
-
value_cast = value_cast + ", VALUE" if convention == :fastruby
|
402
|
+
value_cast = value_cast + ", VALUE, VALUE" if convention == :fastruby
|
317
403
|
|
318
404
|
str_called_code_args = call_tree[3][1..-1].map{|subtree| to_c subtree}.join(",")
|
319
405
|
|
320
406
|
caller_code = proc { |name| "
|
321
|
-
static VALUE #{name}(VALUE param) {
|
407
|
+
static VALUE #{name}(VALUE param, VALUE pframe) {
|
322
408
|
#{@block_struct} block;
|
409
|
+
#{@locals_struct} *plocals = (void*)param;
|
323
410
|
|
324
|
-
block.block_function_address = (void*)#{anonymous_function(block_code)};
|
411
|
+
block.block_function_address = (void*)#{anonymous_function(&block_code)};
|
325
412
|
block.block_function_param = (void*)param;
|
326
413
|
|
327
414
|
// call to #{call_tree[2]}
|
328
415
|
|
329
|
-
#{
|
330
|
-
|
331
|
-
return ((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{str_recv}, (VALUE)&block, #{str_called_code_args});
|
416
|
+
return ((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{str_recv}, (VALUE)&block, (VALUE)pframe, #{str_called_code_args});
|
332
417
|
}
|
333
418
|
"
|
334
419
|
}
|
335
420
|
|
336
421
|
else
|
337
422
|
caller_code = proc { |name| "
|
338
|
-
static VALUE #{name}(VALUE param) {
|
423
|
+
static VALUE #{name}(VALUE param, VALUE pframe) {
|
339
424
|
#{@block_struct} block;
|
425
|
+
#{@locals_struct} *plocals = (void*)param;
|
340
426
|
|
341
|
-
block.block_function_address = (void*)#{anonymous_function(block_code)};
|
427
|
+
block.block_function_address = (void*)#{anonymous_function(&block_code)};
|
342
428
|
block.block_function_param = (void*)param;
|
343
429
|
|
344
430
|
// call to #{call_tree[2]}
|
345
|
-
#{str_lvar_initialization}
|
346
431
|
|
347
|
-
return ((VALUE(*)(VALUE,VALUE))0x#{address.to_s(16)})(#{str_recv}, (VALUE)&block);
|
432
|
+
return ((VALUE(*)(VALUE,VALUE,VALUE))0x#{address.to_s(16)})(#{str_recv}, (VALUE)&block, (VALUE)pframe);
|
348
433
|
}
|
349
434
|
"
|
350
435
|
}
|
351
436
|
end
|
352
437
|
|
353
|
-
"#{anonymous_function(caller_code)}((VALUE)
|
438
|
+
"#{anonymous_function(&caller_code)}((VALUE)plocals, (VALUE)pframe)"
|
354
439
|
end
|
355
440
|
end
|
356
441
|
|
357
442
|
def to_c_yield(tree)
|
358
443
|
|
359
444
|
block_code = proc { |name| "
|
360
|
-
static VALUE #{name}(VALUE
|
445
|
+
static VALUE #{name}(VALUE frame_param, VALUE* block_args) {
|
361
446
|
|
362
447
|
#{@locals_struct} *plocals;
|
363
|
-
|
448
|
+
#{@frame_struct} *pframe;
|
449
|
+
pframe = (void*)frame_param;
|
450
|
+
plocals = (void*)pframe->plocals;
|
364
451
|
|
365
452
|
if (plocals->block_function_address == 0) {
|
366
453
|
rb_raise(rb_eLocalJumpError, \"no block given\");
|
367
454
|
} else {
|
368
|
-
return ((VALUE(*)(int,VALUE*,VALUE))plocals->block_function_address)(#{tree.size-1}, block_args, plocals->block_function_param);
|
455
|
+
return ((VALUE(*)(int,VALUE*,VALUE,VALUE))plocals->block_function_address)(#{tree.size-1}, block_args, plocals->block_function_param, (VALUE)pframe);
|
369
456
|
}
|
370
457
|
}
|
371
458
|
"
|
@@ -388,9 +475,9 @@ module FastRuby
|
|
388
475
|
end
|
389
476
|
|
390
477
|
if tree.size > 1
|
391
|
-
anonymous_function(block_code)+"((VALUE)
|
478
|
+
anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){#{tree[1..-1].map{|subtree| to_c subtree}.join(",")}})"
|
392
479
|
else
|
393
|
-
anonymous_function(block_code)+"((VALUE)
|
480
|
+
anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){})"
|
394
481
|
end
|
395
482
|
end
|
396
483
|
|
@@ -416,7 +503,41 @@ module FastRuby
|
|
416
503
|
end
|
417
504
|
|
418
505
|
def to_c_return(tree)
|
419
|
-
"
|
506
|
+
"pframe->target_frame = ((typeof(pframe))plocals->pframe); plocals->return_value = #{to_c(tree[1])}; longjmp(pframe->jmp, 1);\n"
|
507
|
+
end
|
508
|
+
|
509
|
+
def to_c_break(tree)
|
510
|
+
if @on_block
|
511
|
+
inline_block(
|
512
|
+
"
|
513
|
+
pframe->target_frame = (void*)-2;
|
514
|
+
pframe->return_value = #{tree[1] ? to_c(tree[1]) : "Qnil"};
|
515
|
+
pframe->exception = Qnil;
|
516
|
+
longjmp(pframe->jmp,1);"
|
517
|
+
)
|
518
|
+
else
|
519
|
+
inline_block("
|
520
|
+
pframe->target_frame = (void*)-1;
|
521
|
+
pframe->exception = (VALUE)#{LocalJumpError.exception.internal_value};
|
522
|
+
longjmp(pframe->jmp,1);
|
523
|
+
return Qnil;
|
524
|
+
")
|
525
|
+
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
def to_c_next(tree)
|
530
|
+
if @on_block
|
531
|
+
"Qnil; pframe->target_frame = (void*)-3; pframe->return_value = #{tree[1] ? to_c(tree[1]) : "Qnil"}; longjmp(pframe->jmp,1)"
|
532
|
+
else
|
533
|
+
inline_block("
|
534
|
+
pframe->target_frame = (void*)-1;
|
535
|
+
pframe->exception = (VALUE)#{LocalJumpError.exception.internal_value};
|
536
|
+
longjmp(pframe->jmp,1);
|
537
|
+
return Qnil;
|
538
|
+
")
|
539
|
+
|
540
|
+
end
|
420
541
|
end
|
421
542
|
|
422
543
|
def to_c_lit(tree)
|
@@ -440,16 +561,18 @@ module FastRuby
|
|
440
561
|
hash_aset_code << "rb_hash_aset(hash, #{strkey}, #{strvalue});"
|
441
562
|
end
|
442
563
|
|
443
|
-
|
564
|
+
anonymous_function{ |name| "
|
444
565
|
static VALUE #{name}(VALUE value_params) {
|
445
|
-
#{@
|
566
|
+
#{@frame_struct} *pframe;
|
567
|
+
#{@locals_struct} *plocals;
|
568
|
+
pframe = (void*)value_params;
|
569
|
+
plocals = (void*)pframe->plocals;
|
570
|
+
|
446
571
|
VALUE hash = rb_hash_new();
|
447
572
|
#{hash_aset_code}
|
448
573
|
return hash;
|
449
574
|
}
|
450
|
-
" }
|
451
|
-
|
452
|
-
anonymous_function(wrapper_func) + "((VALUE)#{locals_pointer})"
|
575
|
+
" } + "((VALUE)pframe)"
|
453
576
|
end
|
454
577
|
|
455
578
|
def to_c_array(tree)
|
@@ -506,54 +629,178 @@ module FastRuby
|
|
506
629
|
"rb_funcall(plocals->self,#{:fastruby.to_i},1,(VALUE)#{tree.internal_value})"
|
507
630
|
end
|
508
631
|
|
509
|
-
def
|
510
|
-
|
511
|
-
args_tree = tree[2]
|
632
|
+
def to_c_defs(tree)
|
633
|
+
args_tree = tree[3];
|
512
634
|
|
513
|
-
|
635
|
+
tmp = FastRuby.build_defs(tree)
|
636
|
+
|
637
|
+
extra_code << tmp[0]
|
514
638
|
|
639
|
+
inline_block "
|
640
|
+
rb_define_singleton_method(#{to_c tree[1]}, \"#{tree[2].to_s}\", (void*)#{tmp[1]}, #{args_tree.size-1});
|
641
|
+
return Qnil;
|
642
|
+
"
|
643
|
+
end
|
644
|
+
|
645
|
+
def to_c_defined(tree)
|
646
|
+
nt = tree[1].node_type
|
647
|
+
|
648
|
+
if nt == :self
|
649
|
+
'rb_str_new2("self")'
|
650
|
+
elsif nt == :true
|
651
|
+
'rb_str_new2("true")'
|
652
|
+
elsif nt == :false
|
653
|
+
'rb_str_new2("false")'
|
654
|
+
elsif nt == :nil
|
655
|
+
'rb_str_new2("nil")'
|
656
|
+
elsif nt == :lvar
|
657
|
+
'rb_str_new2("local-variable")'
|
658
|
+
elsif nt == :gvar
|
659
|
+
"rb_gvar_defined((struct global_entry*)0x#{global_entry(tree[1][1]).to_s(16)}) ? #{"global-variable".internal_value} : Qnil"
|
660
|
+
elsif nt == :const
|
661
|
+
"rb_const_defined(rb_cObject, #{tree[1][1].to_i}) ? #{"constant".internal_value} : Qnil"
|
662
|
+
elsif nt == :call
|
663
|
+
"rb_method_node(CLASS_OF(#{to_c tree[1][1]}), #{tree[1][2].to_i}) ? #{"method".internal_value} : Qnil"
|
664
|
+
elsif nt == :yield
|
665
|
+
"rb_block_given_p() ? #{"yield".internal_value} : Qnil"
|
666
|
+
elsif nt == :ivar
|
667
|
+
"rb_ivar_defined(plocals->self,#{tree[1][1].to_i}) ? #{"instance-variable".internal_value} : Qnil"
|
668
|
+
elsif nt == :attrset or
|
669
|
+
nt == :op_asgn1 or
|
670
|
+
nt == :op_asgn2 or
|
671
|
+
nt == :op_asgn_or or
|
672
|
+
nt == :op_asgn_and or
|
673
|
+
nt == :op_asgn_masgn or
|
674
|
+
nt == :masgn or
|
675
|
+
nt == :lasgn or
|
676
|
+
nt == :dasgn or
|
677
|
+
nt == :dasgn_curr or
|
678
|
+
nt == :gasgn or
|
679
|
+
nt == :iasgn or
|
680
|
+
nt == :cdecl or
|
681
|
+
nt == :cvdecl or
|
682
|
+
nt == :cvasgn
|
683
|
+
"assignment".internal_value
|
684
|
+
else
|
685
|
+
"expression".internal_value
|
686
|
+
end
|
687
|
+
end
|
688
|
+
|
689
|
+
def initialize_method_structs(args_tree)
|
515
690
|
@locals_struct = "struct {
|
516
|
-
#{@locals.map{|l| "VALUE #{l};\n"}.join}
|
517
|
-
#{args_tree[1..-1].map{|arg| "VALUE #{arg};\n"}.join};
|
518
691
|
void* block_function_address;
|
519
692
|
VALUE block_function_param;
|
693
|
+
jmp_buf jmp;
|
694
|
+
VALUE return_value;
|
695
|
+
void* pframe;
|
696
|
+
#{@locals.map{|l| "VALUE #{l};\n"}.join}
|
697
|
+
#{args_tree[1..-1].map{|arg| "VALUE #{arg};\n"}.join};
|
520
698
|
}"
|
699
|
+
end
|
521
700
|
|
522
|
-
|
523
|
-
|
524
|
-
|
701
|
+
def to_c_method_defs(tree)
|
702
|
+
|
703
|
+
method_name = tree[2]
|
704
|
+
args_tree = tree[3]
|
705
|
+
|
706
|
+
impl_tree = tree[4][1]
|
707
|
+
|
708
|
+
initialize_method_structs(args_tree)
|
709
|
+
|
710
|
+
strargs = if args_tree.size > 1
|
711
|
+
"VALUE self, void* block_address, VALUE block_param, void* _parent_frame, #{args_tree[1..-1].map{|arg| "VALUE #{arg}" }.join(",") }"
|
712
|
+
else
|
713
|
+
"VALUE self, void* block_address, VALUE block_param, void* _parent_frame"
|
714
|
+
end
|
715
|
+
|
716
|
+
extra_code << "static VALUE #{@alt_method_name + "_real"}(#{strargs}) {
|
717
|
+
#{func_frame}
|
718
|
+
|
719
|
+
#{args_tree[1..-1].map { |arg|
|
720
|
+
"locals.#{arg} = #{arg};\n"
|
721
|
+
}.join("") }
|
722
|
+
|
723
|
+
locals.block_function_address = block_address;
|
724
|
+
locals.block_function_param = block_param;
|
725
|
+
|
726
|
+
return #{to_c impl_tree};
|
525
727
|
}"
|
526
728
|
|
527
|
-
|
528
|
-
|
529
|
-
if impl_tree[0] == :block
|
530
|
-
str_impl = to_c impl_tree
|
729
|
+
strargs2 = if args_tree.size > 1
|
730
|
+
"VALUE self, #{args_tree[1..-1].map{|arg| "VALUE #{arg}" }.join(",") }"
|
531
731
|
else
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
732
|
+
"VALUE self"
|
733
|
+
end
|
734
|
+
|
735
|
+
value_cast = ( ["VALUE"]*(args_tree.size+1) ).join(",")
|
736
|
+
strmethodargs = ""
|
737
|
+
|
738
|
+
if args_tree.size > 1
|
739
|
+
strmethodargs = "self,block_address,block_param,&frame,#{args_tree[1..-1].map(&:to_s).join(",") }"
|
740
|
+
else
|
741
|
+
strmethodargs = "self,block_address,block_param,&frame"
|
537
742
|
end
|
538
743
|
|
744
|
+
"
|
745
|
+
VALUE #{@alt_method_name}(#{strargs2}) {
|
746
|
+
#{@frame_struct} frame;
|
747
|
+
int argc = #{args_tree.size};
|
748
|
+
void* block_address = 0;
|
749
|
+
VALUE block_param = Qnil;
|
750
|
+
|
751
|
+
|
752
|
+
frame.plocals = 0;
|
753
|
+
frame.parent_frame = 0;
|
754
|
+
frame.return_value = Qnil;
|
755
|
+
frame.target_frame = &frame;
|
756
|
+
frame.exception = Qnil;
|
757
|
+
frame.rescue = 0;
|
758
|
+
|
759
|
+
if (rb_block_given_p()) {
|
760
|
+
block_address = #{
|
761
|
+
anonymous_function{|name|
|
762
|
+
"static VALUE #{name}(int argc, VALUE* argv, VALUE param) {
|
763
|
+
return rb_yield_splat(rb_ary_new4(argc,argv));
|
764
|
+
}"
|
765
|
+
}
|
766
|
+
};
|
767
|
+
|
768
|
+
block_param = 0;
|
769
|
+
}
|
770
|
+
|
771
|
+
int aux = setjmp(frame.jmp);
|
772
|
+
if (aux != 0) {
|
773
|
+
rb_funcall(self, #{:raise.to_i}, 1, frame.exception);
|
774
|
+
}
|
775
|
+
|
776
|
+
|
777
|
+
return #{@alt_method_name + "_real"}(#{strmethodargs});
|
778
|
+
}
|
779
|
+
"
|
780
|
+
end
|
781
|
+
|
782
|
+
def to_c_method(tree)
|
783
|
+
method_name = tree[1]
|
784
|
+
args_tree = tree[2]
|
785
|
+
|
786
|
+
impl_tree = tree[3][1]
|
787
|
+
|
788
|
+
initialize_method_structs(args_tree)
|
789
|
+
|
539
790
|
strargs = if args_tree.size > 1
|
540
|
-
"VALUE block, #{args_tree[1..-1].map{|arg| "VALUE #{arg}" }.join(",") }"
|
791
|
+
"VALUE block, VALUE _parent_frame, #{args_tree[1..-1].map{|arg| "VALUE #{arg}" }.join(",") }"
|
541
792
|
else
|
542
|
-
"VALUE block"
|
793
|
+
"VALUE block, VALUE _parent_frame"
|
543
794
|
end
|
544
795
|
|
545
796
|
"VALUE #{@alt_method_name || method_name}(#{strargs}) {
|
546
|
-
|
547
|
-
#{
|
548
|
-
#{@block_struct} *pblock;
|
549
|
-
VALUE last_expression = Qnil;
|
797
|
+
|
798
|
+
#{func_frame}
|
550
799
|
|
551
800
|
#{args_tree[1..-1].map { |arg|
|
552
801
|
"locals.#{arg} = #{arg};\n"
|
553
802
|
}.join("") }
|
554
803
|
|
555
|
-
locals.self = self;
|
556
|
-
|
557
804
|
pblock = (void*)block;
|
558
805
|
if (pblock) {
|
559
806
|
locals.block_function_address = pblock->block_function_address;
|
@@ -563,7 +810,7 @@ module FastRuby
|
|
563
810
|
locals.block_function_param = Qnil;
|
564
811
|
}
|
565
812
|
|
566
|
-
return #{
|
813
|
+
return #{to_c impl_tree};
|
567
814
|
}"
|
568
815
|
end
|
569
816
|
|
@@ -571,10 +818,6 @@ module FastRuby
|
|
571
818
|
"plocals->"
|
572
819
|
end
|
573
820
|
|
574
|
-
def locals_pointer
|
575
|
-
"plocals"
|
576
|
-
end
|
577
|
-
|
578
821
|
def to_c_gvar(tree)
|
579
822
|
"rb_gvar_get((struct global_entry*)0x#{global_entry(tree[1]).to_s(16)})"
|
580
823
|
end
|
@@ -632,7 +875,7 @@ module FastRuby
|
|
632
875
|
}
|
633
876
|
|
634
877
|
|
635
|
-
"_lvar_assing(&#{locals_accessor}#{tree[1]}, #{anonymous_function(verify_type_function)}(#{to_c tree[2]}))"
|
878
|
+
"_lvar_assing(&#{locals_accessor}#{tree[1]}, #{anonymous_function(&verify_type_function)}(#{to_c tree[2]}))"
|
636
879
|
else
|
637
880
|
"_lvar_assing(&#{locals_accessor}#{tree[1]},#{to_c tree[2]})"
|
638
881
|
end
|
@@ -688,16 +931,67 @@ module FastRuby
|
|
688
931
|
"
|
689
932
|
end
|
690
933
|
|
691
|
-
def
|
692
|
-
|
693
|
-
|
694
|
-
|
934
|
+
def to_c_rescue(tree)
|
935
|
+
if tree[1][0] == :resbody
|
936
|
+
else_tree = tree[2]
|
937
|
+
|
938
|
+
if else_tree
|
939
|
+
to_c else_tree
|
940
|
+
else
|
941
|
+
"Qnil"
|
942
|
+
end
|
943
|
+
else
|
944
|
+
resbody_tree = tree[2]
|
945
|
+
else_tree = tree[3]
|
946
|
+
|
947
|
+
frame(to_c(tree[1])+";","
|
948
|
+
if (CLASS_OF(frame.exception) == #{to_c(resbody_tree[1][1])})
|
949
|
+
{
|
950
|
+
// trap exception
|
951
|
+
;original_frame->target_frame = &frame;
|
952
|
+
#{to_c(resbody_tree[2])};
|
953
|
+
}
|
954
|
+
", else_tree ? to_c(else_tree) : nil, 1)
|
955
|
+
end
|
956
|
+
end
|
957
|
+
|
958
|
+
def to_c_ensure(tree)
|
959
|
+
if tree.size == 2
|
960
|
+
to_c tree[1]
|
961
|
+
else
|
962
|
+
ensured_code = to_c tree[2]
|
963
|
+
inline_block "
|
964
|
+
#{frame(to_c(tree[1]),ensured_code,ensured_code,1)};
|
965
|
+
"
|
966
|
+
end
|
967
|
+
end
|
695
968
|
|
969
|
+
def to_c_call(tree)
|
696
970
|
directive_code = directive(tree)
|
697
971
|
if directive_code
|
698
972
|
return directive_code
|
699
973
|
end
|
700
974
|
|
975
|
+
if tree[2] == :require
|
976
|
+
tree[2] = :fastruby_require
|
977
|
+
elsif tree[2] == :raise
|
978
|
+
# raise code
|
979
|
+
args = tree[3]
|
980
|
+
|
981
|
+
return inline_block("
|
982
|
+
pframe->target_frame = (void*)-1;
|
983
|
+
pframe->exception = rb_funcall(#{to_c args[1]}, #{:exception.to_i},0);
|
984
|
+
longjmp(pframe->jmp, 1);
|
985
|
+
return Qnil;
|
986
|
+
")
|
987
|
+
end
|
988
|
+
|
989
|
+
recv = tree[1]
|
990
|
+
mname = tree[2]
|
991
|
+
args = tree[3]
|
992
|
+
|
993
|
+
mname = :require_fastruby if mname == :require
|
994
|
+
|
701
995
|
strargs = args[1..-1].map{|arg| to_c arg}.join(",")
|
702
996
|
|
703
997
|
argnum = args.size - 1
|
@@ -745,8 +1039,12 @@ module FastRuby
|
|
745
1039
|
convention = :cruby
|
746
1040
|
end
|
747
1041
|
|
748
|
-
address =
|
749
|
-
len =
|
1042
|
+
address = nil
|
1043
|
+
len = 0
|
1044
|
+
if mobject
|
1045
|
+
address = getaddress(mobject)
|
1046
|
+
len = getlen(mobject)
|
1047
|
+
end
|
750
1048
|
|
751
1049
|
extraargs = ""
|
752
1050
|
extraargs = ", Qfalse" if convention == :fastruby
|
@@ -754,10 +1052,10 @@ module FastRuby
|
|
754
1052
|
if address then
|
755
1053
|
if argnum == 0
|
756
1054
|
value_cast = "VALUE"
|
757
|
-
value_cast = value_cast + ", VALUE" if convention == :fastruby
|
1055
|
+
value_cast = value_cast + ", VALUE,VALUE" if convention == :fastruby
|
758
1056
|
|
759
1057
|
if convention == :fastruby
|
760
|
-
"((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{to_c recv}, Qfalse)"
|
1058
|
+
"((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{to_c recv}, Qfalse, (VALUE)pframe)"
|
761
1059
|
else
|
762
1060
|
|
763
1061
|
str_incall_args = nil
|
@@ -771,28 +1069,28 @@ module FastRuby
|
|
771
1069
|
str_incall_args = "recv"
|
772
1070
|
end
|
773
1071
|
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
//
|
779
|
-
|
780
|
-
|
781
|
-
|
1072
|
+
protected_block(
|
1073
|
+
|
1074
|
+
anonymous_function{ |name| "
|
1075
|
+
static VALUE #{name}(VALUE recv) {
|
1076
|
+
// call to #{recvtype}##{mname}
|
1077
|
+
if (rb_block_given_p()) {
|
1078
|
+
// no passing block, recall
|
1079
|
+
return rb_funcall(recv, #{tree[2].to_i}, 0);
|
1080
|
+
} else {
|
1081
|
+
return ((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{str_incall_args});
|
1082
|
+
}
|
782
1083
|
}
|
783
|
-
}
|
784
|
-
|
785
|
-
|
786
|
-
anonymous_function(wrapper_func) + "(#{to_c(recv)})"
|
787
|
-
|
1084
|
+
" } + "(#{to_c(recv)})"
|
1085
|
+
)
|
788
1086
|
end
|
789
1087
|
else
|
790
1088
|
value_cast = ( ["VALUE"]*(args.size) ).join(",")
|
791
|
-
value_cast = value_cast + ", VALUE" if convention == :fastruby
|
1089
|
+
value_cast = value_cast + ", VALUE, VALUE" if convention == :fastruby
|
792
1090
|
|
793
1091
|
wrapper_func = nil
|
794
1092
|
if convention == :fastruby
|
795
|
-
"((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{to_c recv}, Qfalse, #{strargs})"
|
1093
|
+
"((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{to_c recv}, Qfalse, (VALUE)pframe, #{strargs})"
|
796
1094
|
else
|
797
1095
|
|
798
1096
|
str_incall_args = nil
|
@@ -806,35 +1104,36 @@ module FastRuby
|
|
806
1104
|
str_incall_args = "recv, #{ (1..argnum).map{|x| "_arg"+x.to_s }.join(",")}"
|
807
1105
|
end
|
808
1106
|
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
//
|
814
|
-
|
815
|
-
|
816
|
-
|
1107
|
+
protected_block(
|
1108
|
+
|
1109
|
+
anonymous_function{ |name| "
|
1110
|
+
static VALUE #{name}(VALUE recv, #{ (1..argnum).map{|x| "VALUE _arg"+x.to_s }.join(",")} ) {
|
1111
|
+
// call to #{recvtype}##{mname}
|
1112
|
+
if (rb_block_given_p()) {
|
1113
|
+
// no passing block, recall
|
1114
|
+
return rb_funcall(recv, #{tree[2].to_i}, #{argnum}, #{ (1..argnum).map{|x| "_arg"+x.to_s }.join(",")});
|
1115
|
+
} else {
|
1116
|
+
return ((VALUE(*)(#{value_cast}))0x#{address.to_s(16)})(#{str_incall_args});
|
1117
|
+
}
|
817
1118
|
}
|
818
|
-
}
|
819
|
-
|
820
|
-
|
821
|
-
anonymous_function(wrapper_func) + "(#{to_c(recv)}, #{strargs})"
|
1119
|
+
" } + "(#{to_c(recv)}, #{strargs})"
|
1120
|
+
)
|
822
1121
|
end
|
823
1122
|
end
|
824
1123
|
else
|
825
1124
|
|
826
1125
|
if argnum == 0
|
827
|
-
"rb_funcall(#{to_c recv}, #{tree[2].to_i}, 0)"
|
1126
|
+
protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, 0)")
|
828
1127
|
else
|
829
|
-
"rb_funcall(#{to_c recv}, #{tree[2].to_i}, #{argnum}, #{strargs} )"
|
1128
|
+
protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, #{argnum}, #{strargs} )")
|
830
1129
|
end
|
831
1130
|
end
|
832
1131
|
|
833
1132
|
else
|
834
1133
|
if argnum == 0
|
835
|
-
"rb_funcall(#{to_c recv}, #{tree[2].to_i}, 0)"
|
1134
|
+
protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, 0)")
|
836
1135
|
else
|
837
|
-
"rb_funcall(#{to_c recv}, #{tree[2].to_i}, #{argnum}, #{strargs} )"
|
1136
|
+
protected_block("rb_funcall(#{to_c recv}, #{tree[2].to_i}, #{argnum}, #{strargs} )")
|
838
1137
|
end
|
839
1138
|
end
|
840
1139
|
end
|
@@ -847,6 +1146,13 @@ module FastRuby
|
|
847
1146
|
|
848
1147
|
end
|
849
1148
|
|
1149
|
+
def to_c_module(tree)
|
1150
|
+
inline_block("
|
1151
|
+
rb_funcall(plocals->self,#{:fastruby.to_i},1,(VALUE)#{tree.internal_value});
|
1152
|
+
return Qnil;
|
1153
|
+
")
|
1154
|
+
end
|
1155
|
+
|
850
1156
|
def to_c_while(tree)
|
851
1157
|
inline_block("
|
852
1158
|
while (#{to_c tree[1]}) {
|
@@ -872,6 +1178,14 @@ module FastRuby
|
|
872
1178
|
end
|
873
1179
|
end
|
874
1180
|
|
1181
|
+
def on_block
|
1182
|
+
old_on_block = @on_block
|
1183
|
+
@on_block = true
|
1184
|
+
return yield
|
1185
|
+
ensure
|
1186
|
+
@on_block = old_on_block
|
1187
|
+
end
|
1188
|
+
|
875
1189
|
def with_extra_inference(extra_inference)
|
876
1190
|
previous_infer_lvar_map = @infer_lvar_map
|
877
1191
|
begin
|
@@ -900,33 +1214,225 @@ module FastRuby
|
|
900
1214
|
elsif mname == :inline_c
|
901
1215
|
code = args[1][1]
|
902
1216
|
|
903
|
-
|
1217
|
+
return anonymous_function{ |name| "
|
904
1218
|
static VALUE #{name}(VALUE param) {
|
905
1219
|
#{@locals_struct} *plocals = (void*)param;
|
906
1220
|
#{code};
|
907
1221
|
return Qnil;
|
908
1222
|
}
|
909
1223
|
"
|
910
|
-
}
|
911
|
-
|
912
|
-
return anonymous_function(caller_code)+"((VALUE)plocals)"
|
1224
|
+
}+"((VALUE)plocals)"
|
913
1225
|
else
|
914
1226
|
nil
|
915
1227
|
end
|
916
1228
|
end
|
917
1229
|
|
1230
|
+
def inline_block_reference(arg)
|
1231
|
+
code = nil
|
1232
|
+
|
1233
|
+
if arg.instance_of? Sexp
|
1234
|
+
code = to_c(arg);
|
1235
|
+
else
|
1236
|
+
code = arg
|
1237
|
+
end
|
1238
|
+
|
1239
|
+
anonymous_function{ |name| "
|
1240
|
+
static VALUE #{name}(VALUE param) {
|
1241
|
+
#{@frame_struct} *pframe = (void*)param;
|
1242
|
+
#{@locals_struct} *plocals = (void*)pframe->plocals;
|
1243
|
+
VALUE last_expression = Qnil;
|
1244
|
+
|
1245
|
+
#{code};
|
1246
|
+
return last_expression;
|
1247
|
+
}
|
1248
|
+
"
|
1249
|
+
}
|
1250
|
+
end
|
1251
|
+
|
918
1252
|
def inline_block(code)
|
919
|
-
|
1253
|
+
anonymous_function{ |name| "
|
920
1254
|
static VALUE #{name}(VALUE param) {
|
921
|
-
#{@
|
1255
|
+
#{@frame_struct} *pframe = (void*)param;
|
1256
|
+
#{@locals_struct} *plocals = (void*)pframe->plocals;
|
922
1257
|
VALUE last_expression = Qnil;
|
923
1258
|
|
924
1259
|
#{code}
|
925
1260
|
}
|
926
1261
|
"
|
927
|
-
}
|
1262
|
+
} + "((VALUE)pframe)"
|
1263
|
+
end
|
1264
|
+
|
1265
|
+
def inline_ruby(proced, parameter)
|
1266
|
+
"rb_funcall(#{proced.internal_value}, #{:call.to_i}, 1, #{parameter})"
|
1267
|
+
end
|
1268
|
+
|
1269
|
+
def wrapped_break_block(inner_code)
|
1270
|
+
frame("return " + inner_code, "
|
1271
|
+
if (original_frame->target_frame == (void*)-2) {
|
1272
|
+
return pframe->return_value;
|
1273
|
+
}
|
1274
|
+
")
|
1275
|
+
end
|
928
1276
|
|
929
|
-
|
1277
|
+
def protected_block(inner_code, always_rescue = false)
|
1278
|
+
wrapper_code = "
|
1279
|
+
if (pframe->last_error != Qnil) {
|
1280
|
+
if (CLASS_OF(pframe->last_error)==(VALUE)#{UnwindFastrubyFrame.internal_value}) {
|
1281
|
+
#{@frame_struct} *pframe = (void*)param;
|
1282
|
+
|
1283
|
+
pframe->target_frame = (void*)FIX2LONG(rb_ivar_get(pframe->last_error, #{:@target_frame.to_i}));
|
1284
|
+
pframe->exception = rb_ivar_get(pframe->last_error, #{:@ex.to_i});
|
1285
|
+
pframe->return_value = rb_ivar_get(pframe->last_error, #{:@return_value.to_i});
|
1286
|
+
|
1287
|
+
if (pframe->target_frame == (void*)-2) {
|
1288
|
+
return pframe->return_value;
|
1289
|
+
}
|
1290
|
+
|
1291
|
+
longjmp(pframe->jmp, 1);
|
1292
|
+
return Qnil;
|
1293
|
+
|
1294
|
+
} else {
|
1295
|
+
// raise emulation
|
1296
|
+
#{@frame_struct} *pframe = (void*)param;
|
1297
|
+
pframe->target_frame = (void*)-1;
|
1298
|
+
pframe->exception = pframe->last_error;
|
1299
|
+
longjmp(pframe->jmp, 1);
|
1300
|
+
return Qnil;
|
1301
|
+
}
|
1302
|
+
|
1303
|
+
}
|
1304
|
+
"
|
1305
|
+
rescue_code = "rb_rescue2(#{inline_block_reference "return #{inner_code};"},(VALUE)pframe,#{anonymous_function{|name| "
|
1306
|
+
static VALUE #{name}(VALUE param, VALUE error) {
|
1307
|
+
#{@frame_struct} *pframe = (void*)param;
|
1308
|
+
pframe->last_error = error;
|
1309
|
+
}
|
1310
|
+
"}}
|
1311
|
+
,(VALUE)pframe, rb_eException,(VALUE)0)"
|
1312
|
+
|
1313
|
+
if always_rescue
|
1314
|
+
inline_block "
|
1315
|
+
pframe->last_error = Qnil;
|
1316
|
+
VALUE result = #{rescue_code};
|
1317
|
+
|
1318
|
+
#{wrapper_code}
|
1319
|
+
|
1320
|
+
return result;
|
1321
|
+
"
|
1322
|
+
else
|
1323
|
+
inline_block "
|
1324
|
+
VALUE result;
|
1325
|
+
pframe->last_error = Qnil;
|
1326
|
+
|
1327
|
+
if (pframe->rescue) {
|
1328
|
+
result = #{rescue_code};
|
1329
|
+
} else {
|
1330
|
+
return #{inner_code};
|
1331
|
+
}
|
1332
|
+
|
1333
|
+
#{wrapper_code}
|
1334
|
+
|
1335
|
+
return result;
|
1336
|
+
"
|
1337
|
+
end
|
1338
|
+
|
1339
|
+
end
|
1340
|
+
|
1341
|
+
|
1342
|
+
def func_frame
|
1343
|
+
"
|
1344
|
+
#{@locals_struct} locals;
|
1345
|
+
#{@locals_struct} *plocals = (void*)&locals;
|
1346
|
+
#{@frame_struct} frame;
|
1347
|
+
#{@frame_struct} *pframe;
|
1348
|
+
|
1349
|
+
frame.plocals = plocals;
|
1350
|
+
frame.parent_frame = (void*)_parent_frame;
|
1351
|
+
frame.return_value = Qnil;
|
1352
|
+
frame.target_frame = &frame;
|
1353
|
+
frame.exception = Qnil;
|
1354
|
+
frame.rescue = 0;
|
1355
|
+
|
1356
|
+
locals.pframe = &frame;
|
1357
|
+
|
1358
|
+
pframe = (void*)&frame;
|
1359
|
+
|
1360
|
+
#{@block_struct} *pblock;
|
1361
|
+
VALUE last_expression = Qnil;
|
1362
|
+
|
1363
|
+
int aux = setjmp(pframe->jmp);
|
1364
|
+
if (aux != 0) {
|
1365
|
+
|
1366
|
+
if (pframe->target_frame == (void*)-2) {
|
1367
|
+
return pframe->return_value;
|
1368
|
+
}
|
1369
|
+
|
1370
|
+
if (pframe->target_frame != pframe) {
|
1371
|
+
// raise exception
|
1372
|
+
((typeof(pframe))_parent_frame)->exception = pframe->exception;
|
1373
|
+
((typeof(pframe))_parent_frame)->target_frame = pframe->target_frame;
|
1374
|
+
((typeof(pframe))_parent_frame)->return_value = pframe->return_value;
|
1375
|
+
longjmp(((typeof(pframe))_parent_frame)->jmp,1);
|
1376
|
+
}
|
1377
|
+
|
1378
|
+
return plocals->return_value;
|
1379
|
+
}
|
1380
|
+
|
1381
|
+
locals.self = self;
|
1382
|
+
"
|
1383
|
+
end
|
1384
|
+
|
1385
|
+
def frame(code, jmp_code, not_jmp_code = "", rescued = nil)
|
1386
|
+
|
1387
|
+
anonymous_function{ |name| "
|
1388
|
+
static VALUE #{name}(VALUE param) {
|
1389
|
+
VALUE last_expression;
|
1390
|
+
#{@frame_struct} frame, *pframe, *parent_frame;
|
1391
|
+
#{@locals_struct} *plocals;
|
1392
|
+
|
1393
|
+
parent_frame = (void*)param;
|
1394
|
+
|
1395
|
+
frame.parent_frame = (void*)param;
|
1396
|
+
frame.plocals = parent_frame->plocals;
|
1397
|
+
frame.target_frame = &frame;
|
1398
|
+
frame.rescue = #{rescued ? rescued : "parent_frame->rescue"};
|
1399
|
+
|
1400
|
+
plocals = frame.plocals;
|
1401
|
+
pframe = &frame;
|
1402
|
+
|
1403
|
+
int aux = setjmp(frame.jmp);
|
1404
|
+
if (aux != 0) {
|
1405
|
+
last_expression = pframe->return_value;
|
1406
|
+
|
1407
|
+
// restore previous frame
|
1408
|
+
typeof(pframe) original_frame = pframe;
|
1409
|
+
pframe = parent_frame;
|
1410
|
+
|
1411
|
+
#{jmp_code};
|
1412
|
+
|
1413
|
+
if (original_frame->target_frame != original_frame) {
|
1414
|
+
pframe->exception = original_frame->exception;
|
1415
|
+
pframe->target_frame = original_frame->target_frame;
|
1416
|
+
pframe->return_value = original_frame->return_value;
|
1417
|
+
|
1418
|
+
longjmp(pframe->jmp,1);
|
1419
|
+
}
|
1420
|
+
|
1421
|
+
return last_expression;
|
1422
|
+
}
|
1423
|
+
|
1424
|
+
#{code};
|
1425
|
+
|
1426
|
+
// restore previous frame
|
1427
|
+
typeof(pframe) original_frame = pframe;
|
1428
|
+
pframe = parent_frame;
|
1429
|
+
#{not_jmp_code};
|
1430
|
+
|
1431
|
+
return last_expression;
|
1432
|
+
|
1433
|
+
}
|
1434
|
+
"
|
1435
|
+
} + "((VALUE)pframe)"
|
930
1436
|
end
|
931
1437
|
|
932
1438
|
inline :C do |builder|
|