fastruby 0.0.18 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +10 -0
- data/Rakefile +2 -1
- data/benchmarks/benchmark.rb~ +2 -4
- data/benchmarks/benchmark3.rb~ +2 -4
- data/ext/fastruby_base/fastruby_base.inl +1 -1
- data/lib/fastruby/builder.rb +8 -7
- data/lib/fastruby/fastruby_sexp.rb +18 -0
- data/lib/fastruby/inliner/modules/call.rb +254 -67
- data/lib/fastruby/inliner/modules/recursive.rb +5 -0
- data/lib/fastruby/reductor/modules/case.rb +2 -1
- data/lib/fastruby/translator/modules/block.rb +65 -59
- data/lib/fastruby/translator/modules/call.rb +7 -4
- data/lib/fastruby/translator/modules/exceptions.rb +66 -64
- data/lib/fastruby/translator/modules/flow.rb +8 -8
- data/lib/fastruby/translator/modules/literal.rb +5 -4
- data/lib/fastruby/translator/modules/method_group.rb +6 -5
- data/lib/fastruby/translator/modules/nonlocal.rb +153 -11
- data/lib/fastruby/translator/modules/static.rb +8 -8
- data/lib/fastruby/translator/modules/variable.rb +15 -15
- data/lib/fastruby/translator/translator.rb +156 -59
- data/lib/fastruby.rb +1 -1
- data/lib/fastruby.rb~ +36 -0
- data/spec/fastruby/inliner/modules/call_spec.rb +0 -0
- data/spec/fastruby/translator/modules/nonlocal_spec.rb +0 -0
- data/spec/fastruby/translator/translator_spec.rb +0 -0
- data/spec/ruby/base_spec.rb~ +5 -5
- data/spec/ruby/block/break_spec.rb~ +236 -0
- data/spec/ruby/block/lambda_spec.rb~ +38 -0
- data/spec/ruby/block/next_spec.rb~ +85 -0
- data/spec/ruby/call/base_call_spec.rb~ +83 -0
- data/spec/ruby/defn/replacement_spec.rb +52 -2
- data/spec/ruby/defn/replacement_spec.rb~ +52 -2
- data/spec/ruby/exception/base_spec.rb +22 -1
- data/spec/ruby/return_spec.rb~ +99 -0
- metadata +30 -10
@@ -42,55 +42,55 @@ module FastRuby
|
|
42
42
|
}
|
43
43
|
|
44
44
|
splat_arg = tree.find{|x| x == :yield ? false : x[0] == :splat}
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
if (CLASS_OF(splat_array) == rb_cArray) {
|
53
|
-
VALUE block_args[_RARRAY_LEN(splat_array) + #{tree.size}];
|
54
|
-
int i;
|
55
|
-
#{
|
56
|
-
(0..tree.size-3).map{|i|
|
57
|
-
"
|
58
|
-
#{to_c(tree[i+1], "block_aux")};
|
59
|
-
block_args[#{i}] = block_aux;
|
60
|
-
"
|
61
|
-
}.join(";\n")
|
62
|
-
};
|
45
|
+
|
46
|
+
protected_block(false) do
|
47
|
+
if splat_arg
|
48
|
+
"
|
49
|
+
VALUE splat_array = Qnil;
|
50
|
+
VALUE block_aux = Qnil;
|
51
|
+
#{to_c(splat_arg[1], "splat_array")};
|
63
52
|
|
64
|
-
|
65
|
-
block_args[
|
53
|
+
if (CLASS_OF(splat_array) == rb_cArray) {
|
54
|
+
VALUE block_args[_RARRAY_LEN(splat_array) + #{tree.size}];
|
55
|
+
int i;
|
56
|
+
#{
|
57
|
+
(0..tree.size-3).map{|i|
|
58
|
+
"
|
59
|
+
#{to_c(tree[i+1], "block_aux")};
|
60
|
+
block_args[#{i}] = block_aux;
|
61
|
+
"
|
62
|
+
}.join(";\n")
|
63
|
+
};
|
64
|
+
|
65
|
+
for (i=0; i<_RARRAY_LEN(splat_array); i++) {
|
66
|
+
block_args[i+#{tree.size-2}] = rb_ary_entry(splat_array,i);
|
67
|
+
}
|
68
|
+
|
69
|
+
last_expression = #{anonymous_function(&block_code)}((VALUE)pframe, block_args, _RARRAY_LEN(splat_array) + #{tree.size-2});
|
70
|
+
} else {
|
71
|
+
VALUE block_args[1+#{tree.size}];
|
72
|
+
#{
|
73
|
+
(0..tree.size-3).map{|i|
|
74
|
+
"
|
75
|
+
#{to_c(tree[i+1], "block_aux")};
|
76
|
+
block_args[#{i}] = block_aux;
|
77
|
+
"
|
78
|
+
}.join(";\n")
|
79
|
+
};
|
80
|
+
|
81
|
+
block_args[#{tree.size-2}] = splat_array;
|
82
|
+
last_expression = #{anonymous_function(&block_code)}((VALUE)pframe, block_args, #{tree.size-1});
|
66
83
|
}
|
67
84
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
"
|
77
|
-
}.join(";\n")
|
78
|
-
};
|
79
|
-
|
80
|
-
block_args[#{tree.size-2}] = splat_array;
|
81
|
-
last_expression = #{anonymous_function(&block_code)}((VALUE)pframe, block_args, #{tree.size-1});
|
82
|
-
}
|
83
|
-
|
84
|
-
"
|
85
|
-
else
|
86
|
-
ret = if tree.size > 1
|
87
|
-
"last_expression = " + anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){#{tree[1..-1].map{|subtree| to_c subtree}.join(",")}},#{tree.size-1})"
|
88
|
-
else
|
89
|
-
"last_expression = " + anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){}, #{tree.size-1})"
|
90
|
-
end
|
85
|
+
"
|
86
|
+
else
|
87
|
+
if tree.size > 1
|
88
|
+
"last_expression = " + anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){#{tree[1..-1].map{|subtree| to_c subtree}.join(",")}},#{tree.size-1})"
|
89
|
+
else
|
90
|
+
"last_expression = " + anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){}, #{tree.size-1})"
|
91
|
+
end
|
92
|
+
end
|
91
93
|
end
|
92
|
-
|
93
|
-
protected_block(ret, false)
|
94
94
|
end
|
95
95
|
|
96
96
|
define_translator_for(:block, :method => :to_c_block)
|
@@ -98,24 +98,30 @@ module FastRuby
|
|
98
98
|
if tree.size == 1
|
99
99
|
return inline_block("return Qnil;")
|
100
100
|
end
|
101
|
-
|
102
|
-
str = ""
|
103
|
-
str = tree[1..-2].map{ |subtree|
|
104
|
-
to_c(subtree,"last_expression")
|
105
|
-
}.join(";")
|
106
101
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
102
|
+
code = proc{
|
103
|
+
|
104
|
+
str = tree[1..-2].map{ |subtree|
|
105
|
+
to_c(subtree,"last_expression")
|
106
|
+
}.join(";")
|
107
|
+
|
108
|
+
if tree[-1]
|
109
|
+
str = str + ";#{to_c(tree[-1],"last_expression")};"
|
110
|
+
end
|
111
|
+
|
112
|
+
if result_variable
|
113
|
+
str << "#{result_variable} = last_expression;"
|
114
|
+
else
|
115
|
+
str << "return last_expression;"
|
116
|
+
end
|
113
117
|
str
|
118
|
+
}
|
119
|
+
|
120
|
+
if result_variable
|
121
|
+
code.call
|
114
122
|
else
|
115
|
-
|
116
|
-
inline_block str
|
123
|
+
inline_block &code
|
117
124
|
end
|
118
125
|
end
|
119
|
-
|
120
126
|
end
|
121
127
|
end
|
@@ -170,7 +170,7 @@ module FastRuby
|
|
170
170
|
|
171
171
|
|
172
172
|
if block_pass_arg or result_var
|
173
|
-
code = "
|
173
|
+
code = proc{ "
|
174
174
|
{
|
175
175
|
VALUE recv = Qnil;
|
176
176
|
#{to_c recv, "recv"};
|
@@ -213,8 +213,9 @@ module FastRuby
|
|
213
213
|
}
|
214
214
|
}
|
215
215
|
"
|
216
|
+
}
|
216
217
|
|
217
|
-
result_var ? code : inline_block(code)
|
218
|
+
result_var ? code.call : inline_block(&code)
|
218
219
|
else
|
219
220
|
"((VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe, 0, (VALUE[]){})"
|
220
221
|
end
|
@@ -225,7 +226,7 @@ module FastRuby
|
|
225
226
|
|
226
227
|
strargs = (0..args_tree.size-2).map{|i| "#{suffix}arg#{i}"}.join(",")
|
227
228
|
if block_pass_arg or result_var
|
228
|
-
code = "
|
229
|
+
code = proc{ "
|
229
230
|
{
|
230
231
|
VALUE recv = Qnil;
|
231
232
|
|
@@ -281,7 +282,9 @@ module FastRuby
|
|
281
282
|
|
282
283
|
}
|
283
284
|
"
|
284
|
-
|
285
|
+
}
|
286
|
+
|
287
|
+
result_var ? code.call : inline_block(&code)
|
285
288
|
else
|
286
289
|
strargs = args[1..-1].map{|arg| to_c arg}.join(",")
|
287
290
|
"((VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe, #{args.size-1}, (VALUE[]){#{strargs}})"
|
@@ -23,73 +23,75 @@ module FastRuby
|
|
23
23
|
|
24
24
|
define_translator_for(:rescue, :method => :to_c_rescue, :arity => 1)
|
25
25
|
def to_c_rescue(tree)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
else
|
35
|
-
resbody_tree = tree[2]
|
36
|
-
else_tree = nil
|
37
|
-
if tree[-1]
|
38
|
-
if tree[-1][0] != :resbody
|
39
|
-
else_tree = tree[-1]
|
26
|
+
catch_on_throw do
|
27
|
+
if tree[1][0] == :resbody
|
28
|
+
else_tree = tree[2]
|
29
|
+
|
30
|
+
if else_tree
|
31
|
+
to_c else_tree
|
32
|
+
else
|
33
|
+
"Qnil"
|
40
34
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
tree[1..-1].each do |resbody_tree|
|
50
|
-
next if resbody_tree[0] != :resbody
|
51
|
-
|
52
|
-
if resbody_tree[1].size == 1
|
53
|
-
resbody_tree[1][1] = s(:const, :Exception)
|
54
|
-
end
|
55
|
-
|
56
|
-
if resbody_tree[1].last[0] == :lasgn
|
57
|
-
lasgn_code = to_c(resbody_tree[1].last)
|
35
|
+
else
|
36
|
+
resbody_tree = tree[2]
|
37
|
+
else_tree = nil
|
38
|
+
if tree[-1]
|
39
|
+
if tree[-1][0] != :resbody
|
40
|
+
else_tree = tree[-1]
|
41
|
+
end
|
58
42
|
end
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
43
|
+
|
44
|
+
catch_condition_array = []
|
45
|
+
lasgn_code = ""
|
46
|
+
resbody_code = to_c(resbody_tree[2])
|
47
|
+
|
48
|
+
rescue_code = ""
|
49
|
+
|
50
|
+
tree[1..-1].each do |resbody_tree|
|
51
|
+
next if resbody_tree[0] != :resbody
|
52
|
+
|
53
|
+
if resbody_tree[1].size == 1
|
54
|
+
resbody_tree[1][1] = s(:const, :Exception)
|
55
|
+
end
|
56
|
+
|
57
|
+
if resbody_tree[1].last[0] == :lasgn
|
58
|
+
lasgn_code = to_c(resbody_tree[1].last)
|
59
|
+
end
|
60
|
+
|
61
|
+
resbody_tree[1][1..-1].each do |xtree|
|
62
|
+
if xtree[0] != :lasgn
|
63
|
+
trapcode = "rb_eException";
|
64
|
+
|
65
|
+
if xtree
|
66
|
+
trapcode = to_c(xtree)
|
67
|
+
end
|
68
|
+
|
69
|
+
catch_condition_array << "(rb_obj_is_kind_of(frame.thread_data->exception,#{trapcode}) == Qtrue)"
|
66
70
|
end
|
67
|
-
|
68
|
-
catch_condition_array << "(rb_obj_is_kind_of(frame.thread_data->exception,#{trapcode}) == Qtrue)"
|
69
71
|
end
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
72
|
+
|
73
|
+
rescue_code << "
|
74
|
+
if (aux == FASTRUBY_TAG_RAISE) {
|
75
|
+
if (#{catch_condition_array.join(" || ")})
|
76
|
+
{
|
77
|
+
// trap exception
|
78
|
+
frame.targetted = 1;
|
79
|
+
|
80
|
+
#{lasgn_code};
|
81
|
+
|
82
|
+
#{resbody_code};
|
83
|
+
}
|
82
84
|
}
|
83
|
-
|
84
|
-
|
85
|
+
"
|
86
|
+
end
|
87
|
+
|
88
|
+
frame_call(
|
89
|
+
"ret = " + frame(to_c(tree[1])+";","
|
90
|
+
#{rescue_code}
|
91
|
+
", else_tree ? to_c(else_tree) : nil, 1)
|
92
|
+
|
93
|
+
)
|
85
94
|
end
|
86
|
-
|
87
|
-
frame_call(
|
88
|
-
"ret = " + frame(to_c(tree[1])+";","
|
89
|
-
#{rescue_code}
|
90
|
-
", else_tree ? to_c(else_tree) : nil, 1)
|
91
|
-
|
92
|
-
)
|
93
95
|
end
|
94
96
|
end
|
95
97
|
|
@@ -99,9 +101,9 @@ module FastRuby
|
|
99
101
|
to_c tree[1]
|
100
102
|
else
|
101
103
|
ensured_code = to_c tree[2]
|
102
|
-
inline_block
|
103
|
-
#{frame(to_c(tree[1]),ensured_code,ensured_code,1)};
|
104
|
-
|
104
|
+
inline_block {
|
105
|
+
"#{frame(to_c(tree[1]),ensured_code,ensured_code,1)};"
|
106
|
+
}
|
105
107
|
end
|
106
108
|
end
|
107
109
|
|
@@ -31,7 +31,7 @@ module FastRuby
|
|
31
31
|
infered_value = infer_value(condition_tree)
|
32
32
|
unless infered_value
|
33
33
|
|
34
|
-
code = "
|
34
|
+
code = proc{"
|
35
35
|
{
|
36
36
|
VALUE condition_result;
|
37
37
|
#{to_c condition_tree, "condition_result"};
|
@@ -44,12 +44,12 @@ module FastRuby
|
|
44
44
|
" : ""
|
45
45
|
}
|
46
46
|
}
|
47
|
-
"
|
47
|
+
"}
|
48
48
|
|
49
49
|
if result_variable_
|
50
|
-
code
|
50
|
+
code.call
|
51
51
|
else
|
52
|
-
inline_block code + "; return last_expression;"
|
52
|
+
inline_block { code.call + "; return last_expression;" }
|
53
53
|
end
|
54
54
|
else
|
55
55
|
if infered_value.value
|
@@ -70,7 +70,7 @@ module FastRuby
|
|
70
70
|
begin_while = "begin_while_"+rand(10000000).to_s
|
71
71
|
end_while = "end_while_"+rand(10000000).to_s
|
72
72
|
aux_varname = "_aux_" + rand(10000000).to_s
|
73
|
-
code = "
|
73
|
+
code = proc{ "
|
74
74
|
{
|
75
75
|
VALUE while_condition;
|
76
76
|
VALUE #{aux_varname};
|
@@ -90,12 +90,12 @@ module FastRuby
|
|
90
90
|
end
|
91
91
|
}
|
92
92
|
}
|
93
|
-
"
|
93
|
+
"}
|
94
94
|
|
95
95
|
if result_var
|
96
|
-
code
|
96
|
+
code.call
|
97
97
|
else
|
98
|
-
inline_block code
|
98
|
+
inline_block &code
|
99
99
|
end
|
100
100
|
|
101
101
|
end
|
@@ -32,6 +32,7 @@ module FastRuby
|
|
32
32
|
key_tmp_var = "_key_"+rand(1000000).to_s
|
33
33
|
value_tmp_var = "_value_"+rand(1000000).to_s
|
34
34
|
|
35
|
+
code = proc{
|
35
36
|
hash_aset_code = ""
|
36
37
|
(0..(tree.size-3)/2).each do |i|
|
37
38
|
strkey = to_c tree[1 + i * 2]
|
@@ -49,7 +50,7 @@ module FastRuby
|
|
49
50
|
"
|
50
51
|
end
|
51
52
|
|
52
|
-
|
53
|
+
"
|
53
54
|
{
|
54
55
|
VALUE #{hash_tmp_var} = rb_hash_new();
|
55
56
|
#{hash_aset_code};
|
@@ -61,12 +62,12 @@ module FastRuby
|
|
61
62
|
end
|
62
63
|
};
|
63
64
|
}
|
64
|
-
"
|
65
|
+
"}
|
65
66
|
|
66
67
|
if result_var
|
67
|
-
code
|
68
|
+
code.call
|
68
69
|
else
|
69
|
-
inline_block code
|
70
|
+
inline_block &code
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
@@ -89,8 +89,8 @@ private
|
|
89
89
|
alt_locals << local
|
90
90
|
end
|
91
91
|
|
92
|
+
code = proc{
|
92
93
|
fun = nil
|
93
|
-
|
94
94
|
locals_scope(alt_locals) do
|
95
95
|
fun = anonymous_function { |method_name| "static VALUE #{method_name}(VALUE self) {
|
96
96
|
|
@@ -158,8 +158,8 @@ private
|
|
158
158
|
"
|
159
159
|
}
|
160
160
|
end
|
161
|
-
|
162
|
-
|
161
|
+
|
162
|
+
"
|
163
163
|
{
|
164
164
|
#{init_code}
|
165
165
|
|
@@ -168,11 +168,12 @@ private
|
|
168
168
|
#{fun}(tmpklass);
|
169
169
|
}
|
170
170
|
"
|
171
|
+
}
|
171
172
|
|
172
173
|
if result_var
|
173
|
-
code + "\n#{result_var} = Qnil;\n"
|
174
|
+
code.call + "\n#{result_var} = Qnil;\n"
|
174
175
|
else
|
175
|
-
inline_block code + "\nreturn Qnil;\n"
|
176
|
+
inline_block &code + "\nreturn Qnil;\n"
|
176
177
|
end
|
177
178
|
|
178
179
|
end
|
@@ -23,15 +23,16 @@ module FastRuby
|
|
23
23
|
|
24
24
|
define_translator_for(:return, :method => :to_c_return)
|
25
25
|
def to_c_return(tree, return_variable = nil)
|
26
|
-
code = "
|
26
|
+
code = proc{"
|
27
27
|
#{to_c(tree[1],"last_expression")};
|
28
28
|
goto local_return;
|
29
29
|
return Qnil;
|
30
|
-
"
|
30
|
+
"}
|
31
|
+
|
31
32
|
if return_variable
|
32
|
-
code
|
33
|
+
code.call
|
33
34
|
else
|
34
|
-
inline_block code
|
35
|
+
inline_block &code
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
@@ -40,7 +41,7 @@ module FastRuby
|
|
40
41
|
|
41
42
|
value_tmp_var = "value_" + rand(10000000).to_s
|
42
43
|
|
43
|
-
code = "
|
44
|
+
code = proc{"
|
44
45
|
|
45
46
|
{
|
46
47
|
VALUE #{value_tmp_var} = Qnil;
|
@@ -65,10 +66,10 @@ module FastRuby
|
|
65
66
|
longjmp(pframe->jmp,FASTRUBY_TAG_BREAK);
|
66
67
|
|
67
68
|
}
|
68
|
-
"
|
69
|
+
"}
|
69
70
|
|
70
71
|
if result_var
|
71
|
-
code
|
72
|
+
code.call
|
72
73
|
else
|
73
74
|
inline_block code
|
74
75
|
end
|
@@ -117,7 +118,7 @@ module FastRuby
|
|
117
118
|
def to_c_next(tree, result_var = nil)
|
118
119
|
tmp_varname = "_acc_" + rand(10000000).to_s
|
119
120
|
if @on_block
|
120
|
-
code = "
|
121
|
+
code =proc {"
|
121
122
|
{
|
122
123
|
last_expression = Qnil;
|
123
124
|
|
@@ -129,15 +130,156 @@ module FastRuby
|
|
129
130
|
pframe->thread_data->accumulator = last_expression;
|
130
131
|
goto fastruby_local_next;
|
131
132
|
}
|
132
|
-
"
|
133
|
+
"}
|
134
|
+
|
133
135
|
if result_var
|
134
|
-
code
|
136
|
+
code.call
|
135
137
|
else
|
136
|
-
inline_block code
|
138
|
+
inline_block &code
|
137
139
|
end
|
138
140
|
else
|
139
141
|
_raise("rb_eLocalJumpError","illegal next");
|
140
142
|
end
|
141
143
|
end
|
144
|
+
|
145
|
+
define_method_handler(:to_c, :priority => 100) { |tree, result_var = nil|
|
146
|
+
|
147
|
+
call_tree = tree[1]
|
148
|
+
catch_tag_id = call_tree[3][1][1]
|
149
|
+
included_catch_jmp = false
|
150
|
+
|
151
|
+
@catch_jmp = @catch_jmp || Set.new
|
152
|
+
|
153
|
+
begin
|
154
|
+
inner_code = catch_block(catch_tag_id) do
|
155
|
+
to_c(tree[3],result_var)
|
156
|
+
end
|
157
|
+
|
158
|
+
included_catch_jmp = true if @catch_jmp.include?(catch_tag_id)
|
159
|
+
ensure
|
160
|
+
@catch_jmp.delete(catch_tag_id)
|
161
|
+
end
|
162
|
+
|
163
|
+
if included_catch_jmp
|
164
|
+
new_frame = anonymous_function{ |name| "
|
165
|
+
static VALUE #{name}(VALUE param) {
|
166
|
+
volatile VALUE last_expression = Qnil;
|
167
|
+
#{@frame_struct} frame;
|
168
|
+
|
169
|
+
typeof(frame)* volatile pframe;
|
170
|
+
typeof(frame)* volatile parent_frame;
|
171
|
+
#{@locals_struct}* volatile plocals;
|
172
|
+
|
173
|
+
parent_frame = (void*)param;
|
174
|
+
|
175
|
+
frame.parent_frame = (void*)param;
|
176
|
+
frame.plocals = parent_frame->plocals;
|
177
|
+
frame.rescue = parent_frame->rescue;
|
178
|
+
frame.targetted = 0;
|
179
|
+
frame.thread_data = parent_frame->thread_data;
|
180
|
+
frame.return_value = Qnil;
|
181
|
+
frame.thread_data->accumulator = Qnil;
|
182
|
+
if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
|
183
|
+
|
184
|
+
plocals = frame.plocals;
|
185
|
+
pframe = &frame;
|
186
|
+
|
187
|
+
volatile int aux = setjmp(frame.jmp);
|
188
|
+
if (aux != 0) {
|
189
|
+
// restore previous frame
|
190
|
+
typeof(pframe) original_frame = pframe;
|
191
|
+
pframe = parent_frame;
|
192
|
+
|
193
|
+
if (aux == (int)#{intern_num catch_tag_id.to_s + "_end"}) {
|
194
|
+
return frame.thread_data->accumulator;
|
195
|
+
} else if (aux == (int)#{intern_num catch_tag_id.to_s + "_start"}) {
|
196
|
+
} else {
|
197
|
+
longjmp(pframe->jmp,aux);
|
198
|
+
}
|
199
|
+
|
200
|
+
return last_expression;
|
201
|
+
}
|
202
|
+
|
203
|
+
#{catch_tag_id.to_s}_start:
|
204
|
+
#{inner_code};
|
205
|
+
#{catch_tag_id.to_s}_end:
|
206
|
+
return last_expression;
|
207
|
+
#{@catch_blocks.map { |cb|
|
208
|
+
"#{cb.to_s}_end:
|
209
|
+
|
210
|
+
plocals->return_value = last_expression;
|
211
|
+
plocals->targetted = 1;
|
212
|
+
longjmp(pframe->jmp, #{intern_num( cb.to_s + "_end")});
|
213
|
+
|
214
|
+
#{cb.to_s}_start:
|
215
|
+
|
216
|
+
plocals->return_value = last_expression;
|
217
|
+
plocals->targetted = 1;
|
218
|
+
longjmp(pframe->jmp, #{intern_num( cb.to_s + "_start")});
|
219
|
+
|
220
|
+
"
|
221
|
+
|
222
|
+
}.join("\n")
|
223
|
+
}
|
224
|
+
|
225
|
+
}
|
226
|
+
"
|
227
|
+
} + "((VALUE)pframe)"
|
228
|
+
|
229
|
+
if result_var
|
230
|
+
"#{result_var} = #{new_frame};"
|
231
|
+
else
|
232
|
+
new_frame
|
233
|
+
end
|
234
|
+
else
|
235
|
+
"
|
236
|
+
#{catch_tag_id.to_s}_start:
|
237
|
+
#{inner_code};
|
238
|
+
#{catch_tag_id.to_s}_end:
|
239
|
+
|
240
|
+
"
|
241
|
+
end
|
242
|
+
|
243
|
+
}.condition{|tree, result_var = nil|
|
244
|
+
tree.node_type == :iter && tree[1][2] == :_catch
|
245
|
+
}
|
246
|
+
|
247
|
+
define_method_handler(:to_c, :priority => 100) { |tree, result_var = nil|
|
248
|
+
code = ""
|
249
|
+
|
250
|
+
catch_tag_id = tree[3][1][1]
|
251
|
+
|
252
|
+
if @catch_jmp_on_throw
|
253
|
+
@catch_jmp << catch_tag_id
|
254
|
+
end
|
255
|
+
|
256
|
+
code << to_c(tree[3][2] || fs(:nil), "last_expression")
|
257
|
+
code << "pframe->thread_data->accumulator = last_expression;"
|
258
|
+
code << "goto #{catch_tag_id.to_s}_end;"
|
259
|
+
|
260
|
+
if result_var
|
261
|
+
code
|
262
|
+
else
|
263
|
+
inline_block code
|
264
|
+
end
|
265
|
+
}.condition{|tree, result_var = nil|
|
266
|
+
tree.node_type == :call && tree[2] == :_throw
|
267
|
+
}
|
268
|
+
|
269
|
+
define_method_handler(:to_c, :priority => 100) { |tree, result_var = nil|
|
270
|
+
code = ""
|
271
|
+
|
272
|
+
catch_tag_id = tree[3][1][1]
|
273
|
+
code << "goto #{catch_tag_id.to_s}_start;"
|
274
|
+
|
275
|
+
if result_var
|
276
|
+
code
|
277
|
+
else
|
278
|
+
inline_block code
|
279
|
+
end
|
280
|
+
}.condition{|tree, result_var = nil|
|
281
|
+
tree.node_type == :call && tree[2] == :_loop
|
282
|
+
}
|
283
|
+
|
142
284
|
end
|
143
285
|
end
|