fastruby 0.0.16 → 0.0.17
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +17 -1
- data/Rakefile +1 -1
- data/ext/fastruby_base/fastruby_base.inl +81 -3
- data/lib/fastruby/fastruby_sexp.rb +21 -0
- data/lib/fastruby/getlocals.rb +2 -1
- data/lib/fastruby/object.rb +1 -1
- data/lib/fastruby/sexp_extension.rb +189 -0
- data/lib/fastruby/sexp_extension_edges.rb +210 -0
- data/lib/fastruby/translator/modules/block.rb +29 -22
- data/lib/fastruby/translator/modules/call.rb +211 -34
- data/lib/fastruby/translator/modules/defn.rb +64 -29
- data/lib/fastruby/translator/modules/exceptions.rb +1 -1
- data/lib/fastruby/translator/modules/flow.rb +93 -31
- data/lib/fastruby/translator/modules/iter.rb +277 -340
- data/lib/fastruby/translator/modules/literal.rb +97 -20
- data/lib/fastruby/translator/modules/logical.rb +40 -5
- data/lib/fastruby/translator/modules/method_group.rb +41 -19
- data/lib/fastruby/translator/modules/nonlocal.rb +74 -29
- data/lib/fastruby/translator/modules/variable.rb +151 -42
- data/lib/fastruby/translator/scope_mode_helper.rb +161 -0
- data/lib/fastruby/translator/translator.rb +389 -302
- data/lib/fastruby.rb +1 -1
- data/lib/fastruby.rb~ +36 -0
- data/spec/edges_helper.rb +91 -0
- data/spec/graph/base_spec.rb +35 -0
- data/spec/graph/path_spec.rb +48 -0
- data/spec/graph/vertex_spec.rb +58 -0
- data/spec/ruby/block/proc_as_block_spec.rb +214 -0
- data/spec/ruby/block/redo_spec.rb +133 -0
- data/spec/ruby/defn/single_function_spec.rb +50 -0
- data/spec/scope_mode/base_spec.rb +55 -0
- data/spec/scope_mode/block_spec.rb +105 -0
- data/spec/scope_mode/call_spec.rb +24 -0
- data/spec/scope_mode/exception_spec.rb +34 -0
- data/spec/scope_mode/flow_spec.rb +99 -0
- data/spec/scope_mode/optimization_spec.rb +130 -0
- data/spec/sexp2graph/base_spec.rb +36 -0
- data/spec/sexp2graph/exception_spec.rb +172 -0
- data/spec/sexp2graph/flow_spec.rb +67 -0
- data/spec/sexp2graph/logical_spec.rb +21 -0
- data/spec/sexp2graph/variable_spec.rb +26 -0
- metadata +110 -120
- data/lib/fastruby/self +0 -82
- data/lib/len +0 -280
- data/spec/block/proc_as_block_spec.rb +0 -111
- data/spec/block/redo_spec.rb +0 -67
- /data/spec/{base_spec.rb → ruby/base_spec.rb} +0 -0
- /data/spec/{block → ruby/block}/arguments_spec.rb +0 -0
- /data/spec/{block → ruby/block}/block_as_proc_spec.rb +0 -0
- /data/spec/{block → ruby/block}/break_spec.rb +0 -0
- /data/spec/{block → ruby/block}/callcc_spec.rb +0 -0
- /data/spec/{block → ruby/block}/lambda_spec.rb +0 -0
- /data/spec/{block → ruby/block}/next_spec.rb +0 -0
- /data/spec/{block → ruby/block}/proc_spec.rb +0 -0
- /data/spec/{block → ruby/block}/retry_spec.rb +0 -0
- /data/spec/{block_spec.rb → ruby/block_spec.rb} +0 -0
- /data/spec/{call → ruby/call}/base_call_spec.rb +0 -0
- /data/spec/{call → ruby/call}/multiple_args_spec.rb +0 -0
- /data/spec/{control_spec.rb → ruby/control_spec.rb} +0 -0
- /data/spec/{defn → ruby/defn}/default_args_spec.rb +0 -0
- /data/spec/{defn → ruby/defn}/multiple_args_spec.rb +0 -0
- /data/spec/{defn → ruby/defn}/replacement_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/base_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/ensure_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/exc_trap_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/internal_ex_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/syntaxis_spec.rb +0 -0
- /data/spec/{expression_spec.rb → ruby/expression_spec.rb} +0 -0
- /data/spec/{flow_control → ruby/flow_control}/case_spec.rb +0 -0
- /data/spec/{flow_control → ruby/flow_control}/for_spec.rb +0 -0
- /data/spec/{integrity_spec.rb → ruby/integrity_spec.rb} +0 -0
- /data/spec/{jump → ruby/jump}/next_spec.rb +0 -0
- /data/spec/{literal_spec.rb → ruby/literal_spec.rb} +0 -0
- /data/spec/{module_spec.rb → ruby/module_spec.rb} +0 -0
- /data/spec/{return_spec.rb → ruby/return_spec.rb} +0 -0
- /data/spec/{singleton_spec.rb → ruby/singleton_spec.rb} +0 -0
- /data/spec/{sugar_spec.rb → ruby/sugar_spec.rb} +0 -0
- /data/spec/{variable_spec.rb → ruby/variable_spec.rb} +0 -0
@@ -33,10 +33,10 @@ module FastRuby
|
|
33
33
|
pframe = (void*)frame_param;
|
34
34
|
plocals = (void*)pframe->plocals;
|
35
35
|
|
36
|
-
if (
|
36
|
+
if ((plocals->block_function_address) == 0) {
|
37
37
|
#{_raise("rb_eLocalJumpError", "no block given")};
|
38
38
|
} else {
|
39
|
-
return ((VALUE(*)(int,VALUE*,VALUE,VALUE))
|
39
|
+
return ((VALUE(*)(int,VALUE*,VALUE,VALUE))(plocals->block_function_address))(size, block_args, (VALUE)(plocals->block_function_param), (VALUE)pframe);
|
40
40
|
}
|
41
41
|
}
|
42
42
|
"
|
@@ -45,15 +45,20 @@ module FastRuby
|
|
45
45
|
splat_arg = tree.find{|x| x == :yield ? false : x[0] == :splat}
|
46
46
|
ret = nil
|
47
47
|
if splat_arg
|
48
|
-
ret =
|
49
|
-
VALUE splat_array =
|
48
|
+
ret = "
|
49
|
+
VALUE splat_array = Qnil;
|
50
|
+
VALUE block_aux = Qnil;
|
51
|
+
#{to_c(splat_arg[1], "splat_array")};
|
50
52
|
|
51
53
|
if (CLASS_OF(splat_array) == rb_cArray) {
|
52
54
|
VALUE block_args[_RARRAY_LEN(splat_array) + #{tree.size}];
|
53
55
|
int i;
|
54
56
|
#{
|
55
57
|
(0..tree.size-3).map{|i|
|
56
|
-
"
|
58
|
+
"
|
59
|
+
#{to_c(tree[i+1], "block_aux")};
|
60
|
+
block_args[#{i}] = block_aux;
|
61
|
+
"
|
57
62
|
}.join(";\n")
|
58
63
|
};
|
59
64
|
|
@@ -61,53 +66,55 @@ module FastRuby
|
|
61
66
|
block_args[i+#{tree.size-2}] = rb_ary_entry(splat_array,i);
|
62
67
|
}
|
63
68
|
|
64
|
-
|
69
|
+
last_expression = #{anonymous_function(&block_code)}((VALUE)pframe, block_args, _RARRAY_LEN(splat_array) + #{tree.size-2});
|
65
70
|
} else {
|
66
71
|
VALUE block_args[1+#{tree.size}];
|
67
72
|
#{
|
68
73
|
(0..tree.size-3).map{|i|
|
69
|
-
"
|
74
|
+
"
|
75
|
+
#{to_c(tree[i+1], "block_aux")};
|
76
|
+
block_args[#{i}] = block_aux;
|
77
|
+
"
|
70
78
|
}.join(";\n")
|
71
79
|
};
|
72
80
|
|
73
81
|
block_args[#{tree.size-2}] = splat_array;
|
74
|
-
|
82
|
+
last_expression = #{anonymous_function(&block_code)}((VALUE)pframe, block_args, #{tree.size-1});
|
75
83
|
}
|
76
84
|
|
77
85
|
"
|
78
86
|
else
|
79
87
|
ret = if tree.size > 1
|
80
|
-
anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){#{tree[1..-1].map{|subtree| to_c subtree}.join(",")}},#{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})"
|
81
89
|
else
|
82
|
-
anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){}, #{tree.size-1})"
|
90
|
+
"last_expression = " + anonymous_function(&block_code)+"((VALUE)pframe, (VALUE[]){}, #{tree.size-1})"
|
83
91
|
end
|
84
92
|
end
|
85
93
|
|
86
94
|
protected_block(ret, false)
|
87
95
|
end
|
88
96
|
|
89
|
-
def to_c_block(tree)
|
97
|
+
def to_c_block(tree, result_variable = nil)
|
90
98
|
if tree.size == 1
|
91
99
|
return inline_block("return Qnil;")
|
92
100
|
end
|
93
|
-
|
101
|
+
|
94
102
|
str = ""
|
95
103
|
str = tree[1..-2].map{ |subtree|
|
96
|
-
to_c(subtree)
|
104
|
+
to_c(subtree,"last_expression")
|
97
105
|
}.join(";")
|
98
106
|
|
99
107
|
if tree[-1]
|
100
|
-
|
101
|
-
if tree[-1][0] != :return
|
102
|
-
str = str + ";last_expression = #{to_c(tree[-1])};"
|
103
|
-
else
|
104
|
-
str = str + ";#{to_c(tree[-1])};"
|
105
|
-
end
|
108
|
+
str = str + ";#{to_c(tree[-1],"last_expression")};"
|
106
109
|
end
|
107
110
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
+
if result_variable
|
112
|
+
str << "#{result_variable} = last_expression;"
|
113
|
+
str
|
114
|
+
else
|
115
|
+
str << "return last_expression;"
|
116
|
+
inline_block str
|
117
|
+
end
|
111
118
|
end
|
112
119
|
|
113
120
|
end
|
@@ -23,12 +23,18 @@ module FastRuby
|
|
23
23
|
|
24
24
|
register_translator_module self
|
25
25
|
|
26
|
-
def to_c_call(tree,
|
26
|
+
def to_c_call(tree, result_var = nil)
|
27
27
|
directive_code = directive(tree)
|
28
|
+
repass_var = @repass_var
|
29
|
+
|
28
30
|
if directive_code
|
29
|
-
|
31
|
+
if result_var
|
32
|
+
return "#{result_var} = #{directive_code};\n"
|
33
|
+
else
|
34
|
+
return directive_code
|
35
|
+
end
|
30
36
|
end
|
31
|
-
|
37
|
+
|
32
38
|
if tree[2] == :require
|
33
39
|
tree[2] = :fastruby_require
|
34
40
|
elsif tree[2] == :raise
|
@@ -36,10 +42,11 @@ module FastRuby
|
|
36
42
|
args = tree[3]
|
37
43
|
return _raise(args[1],args[2])
|
38
44
|
end
|
39
|
-
|
45
|
+
|
40
46
|
recv = tree[1]
|
41
47
|
mname = tree[2]
|
42
48
|
args = tree[3]
|
49
|
+
args_tree = tree[3]
|
43
50
|
|
44
51
|
# search block_pass on arguments
|
45
52
|
block_pass_arg = args.find{|arg| if arg == :arglist
|
@@ -47,24 +54,18 @@ module FastRuby
|
|
47
54
|
else
|
48
55
|
arg[0] == :block_pass
|
49
56
|
end}
|
57
|
+
|
50
58
|
if block_pass_arg
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
block_arguments_tree = s(:masgn, s(:array, s(:splat, s(:lasgn, :__xblock_arguments))))
|
61
|
-
block_tree = s(:call, block_pass_arg[1], :call, s(:arglist, s(:splat, s(:lvar, :__xblock_arguments))))
|
62
|
-
|
63
|
-
replace_iter_tree = s(:iter, call_tree, block_arguments_tree, block_tree).to_fastruby_sexp
|
64
|
-
|
65
|
-
return to_c(replace_iter_tree)
|
59
|
+
args_tree = args_tree.dup.reject{|st|
|
60
|
+
if st.respond_to? :node_type
|
61
|
+
st.node_type == :block_pass
|
62
|
+
else
|
63
|
+
false
|
64
|
+
end
|
65
|
+
}
|
66
|
+
args = args_tree
|
66
67
|
end
|
67
|
-
|
68
|
+
|
68
69
|
mname = :require_fastruby if mname == :require
|
69
70
|
|
70
71
|
argnum = args.size - 1
|
@@ -74,12 +75,40 @@ module FastRuby
|
|
74
75
|
recvtype = infer_type(recv)
|
75
76
|
|
76
77
|
if args.size > 1
|
78
|
+
if (not recvtype) or args.last[0] == :splat
|
79
|
+
if block_pass_arg
|
80
|
+
call_tree = tree.dup
|
81
|
+
call_tree[3] = args.select{|arg| if arg == :arglist
|
82
|
+
true
|
83
|
+
else
|
84
|
+
arg[0] != :block_pass
|
85
|
+
end
|
86
|
+
}
|
87
|
+
|
88
|
+
block_arguments_tree = s(:masgn, s(:array, s(:splat, s(:lasgn, :__xblock_arguments))))
|
89
|
+
block_tree = s(:call, s(:lvar, :__x_proc), :call, s(:arglist, s(:splat, s(:lvar, :__xblock_arguments))))
|
90
|
+
|
91
|
+
replace_iter_tree = s(:block,
|
92
|
+
s(:lasgn, :__x_proc, s(:call, block_pass_arg[1], :to_proc, s(:arglist))),
|
93
|
+
s(:iter, call_tree, block_arguments_tree, block_tree)
|
94
|
+
).to_fastruby_sexp
|
95
|
+
|
96
|
+
if result_var
|
97
|
+
return to_c(replace_iter_tree,result_var)
|
98
|
+
else
|
99
|
+
return to_c(replace_iter_tree)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
77
104
|
if args.last[0] == :splat
|
78
|
-
|
79
|
-
|
105
|
+
aux_varname = "_aux_" + rand(1000000).to_s
|
106
|
+
code = protected_block(
|
80
107
|
"
|
81
108
|
|
82
|
-
VALUE array =
|
109
|
+
VALUE array = Qnil;
|
110
|
+
|
111
|
+
#{to_c args.last[1], "array"};
|
83
112
|
|
84
113
|
if (TYPE(array) != T_ARRAY) {
|
85
114
|
array = rb_ary_new4(1,&array);
|
@@ -87,15 +116,21 @@ module FastRuby
|
|
87
116
|
|
88
117
|
int argc = #{args.size-2};
|
89
118
|
VALUE argv[#{args.size} + _RARRAY_LEN(array)];
|
90
|
-
|
119
|
+
VALUE #{aux_varname} = Qnil;
|
91
120
|
#{
|
92
121
|
i = -1
|
93
122
|
args[1..-2].map {|arg|
|
94
123
|
i = i + 1
|
95
|
-
"
|
124
|
+
"#{to_c arg, aux_varname};
|
125
|
+
argv[#{i}] = #{aux_varname};
|
126
|
+
"
|
96
127
|
}.join(";\n")
|
97
128
|
};
|
98
129
|
|
130
|
+
VALUE recv = Qnil;
|
131
|
+
|
132
|
+
#{to_c recv, "recv"};
|
133
|
+
|
99
134
|
int array_len = _RARRAY_LEN(array);
|
100
135
|
|
101
136
|
int i;
|
@@ -104,14 +139,17 @@ module FastRuby
|
|
104
139
|
argc++;
|
105
140
|
}
|
106
141
|
|
107
|
-
|
108
|
-
"
|
109
|
-
|
142
|
+
last_expression = rb_funcall2(recv, #{intern_num tree[2]}, argc, argv);
|
143
|
+
", true, repass_var)
|
144
|
+
|
145
|
+
if result_var
|
146
|
+
return "#{result_var} = #{code};\n"
|
147
|
+
else
|
148
|
+
return code
|
149
|
+
end
|
110
150
|
end
|
111
151
|
end
|
112
152
|
|
113
|
-
strargs = args[1..-1].map{|arg| to_c arg}.join(",")
|
114
|
-
|
115
153
|
if recvtype
|
116
154
|
|
117
155
|
address = nil
|
@@ -136,19 +174,158 @@ module FastRuby
|
|
136
174
|
extraargs_signature = ""
|
137
175
|
end
|
138
176
|
|
177
|
+
block_proc_tree = s(:call, block_pass_arg[1], :to_proc, s(:arglist)) if block_pass_arg
|
178
|
+
|
179
|
+
block_wrapping_proc = proc { |name| "
|
180
|
+
static VALUE #{name}(int argc, VALUE* argv, VALUE _locals, VALUE _parent_frame) {
|
181
|
+
return rb_proc_call(_locals, rb_ary_new4(argc, argv));
|
182
|
+
}
|
183
|
+
"
|
184
|
+
}
|
185
|
+
|
139
186
|
if argnum == 0
|
140
187
|
value_cast = "VALUE,VALUE,VALUE"
|
141
|
-
|
188
|
+
|
189
|
+
|
190
|
+
if block_pass_arg or result_var
|
191
|
+
code = "
|
192
|
+
{
|
193
|
+
VALUE recv = Qnil;
|
194
|
+
#{to_c recv, "recv"};
|
195
|
+
|
196
|
+
#{@block_struct} block, *pblock = Qfalse;
|
197
|
+
|
198
|
+
#{if block_pass_arg
|
199
|
+
"
|
200
|
+
VALUE proc = Qnil;
|
201
|
+
#{to_c(block_proc_tree, "proc") }
|
202
|
+
|
203
|
+
VALUE block_address_value = rb_ivar_get(proc, #{intern_num "__block_address"});
|
204
|
+
|
205
|
+
if (block_address_value != Qnil) {
|
206
|
+
block.block_function_address = NUM2PTR(block_address_value);
|
207
|
+
block.block_function_param = NUM2PTR(rb_ivar_get(proc, #{intern_num "__block_param"}));
|
208
|
+
block.proc = proc;
|
209
|
+
pblock = █
|
210
|
+
} else {
|
211
|
+
// create a block from a proc
|
212
|
+
block.block_function_address = ((void*)#{anonymous_function(&block_wrapping_proc)});
|
213
|
+
block.block_function_param = (void*)proc;
|
214
|
+
block.proc = proc;
|
215
|
+
pblock = █
|
216
|
+
}
|
217
|
+
|
218
|
+
"
|
219
|
+
end
|
220
|
+
}
|
221
|
+
|
222
|
+
#{if result_var
|
223
|
+
"
|
224
|
+
#{result_var} = ((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(recv, (VALUE)pblock, (VALUE)pframe);
|
225
|
+
"
|
226
|
+
else
|
227
|
+
"
|
228
|
+
((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(recv, (VALUE)pblock, (VALUE)pframe);
|
229
|
+
"
|
230
|
+
end
|
231
|
+
}
|
232
|
+
}
|
233
|
+
"
|
234
|
+
|
235
|
+
result_var ? code : inline_block(code)
|
236
|
+
else
|
237
|
+
"((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe)"
|
238
|
+
end
|
239
|
+
|
142
240
|
else
|
143
241
|
value_cast = ( ["VALUE"]*(args.size) ).join(",") + ",VALUE,VALUE"
|
144
|
-
"
|
242
|
+
suffix = "_" + rand(1000000).to_s+"_"
|
243
|
+
|
244
|
+
strargs = (0..args_tree.size-2).map{|i| "#{suffix}arg#{i}"}.join(",")
|
245
|
+
if block_pass_arg or result_var
|
246
|
+
code = "
|
247
|
+
{
|
248
|
+
VALUE recv = Qnil;
|
249
|
+
|
250
|
+
#{
|
251
|
+
(0..args_tree.size-2).map{ |x|
|
252
|
+
"VALUE #{suffix}arg#{x};"
|
253
|
+
}.join("\n")
|
254
|
+
}
|
255
|
+
|
256
|
+
#{
|
257
|
+
(0..args_tree.size-2).map{ |x|
|
258
|
+
to_c(args_tree[x+1], "#{suffix}arg#{x}") + ";"
|
259
|
+
}.join("\n")
|
260
|
+
}
|
261
|
+
|
262
|
+
#{to_c recv, "recv"};
|
263
|
+
|
264
|
+
#{@block_struct} block, *pblock = Qfalse;
|
265
|
+
|
266
|
+
#{if block_pass_arg
|
267
|
+
"
|
268
|
+
VALUE proc = Qnil;
|
269
|
+
#{to_c(block_proc_tree, "proc") }
|
270
|
+
VALUE block_address_value = rb_ivar_get(proc, #{intern_num "__block_address"});
|
271
|
+
if (block_address_value != Qnil) {
|
272
|
+
block.block_function_address = NUM2PTR(block_address_value);
|
273
|
+
block.block_function_param = NUM2PTR(rb_ivar_get(proc, #{intern_num "__block_param"}));
|
274
|
+
block.proc = proc;
|
275
|
+
pblock = █
|
276
|
+
} else {
|
277
|
+
// create a block from a proc
|
278
|
+
block.block_function_address = ((void*)#{anonymous_function(&block_wrapping_proc)});
|
279
|
+
block.block_function_param = (void*)proc;
|
280
|
+
block.proc = proc;
|
281
|
+
pblock = █
|
282
|
+
}
|
283
|
+
|
284
|
+
"
|
285
|
+
end
|
286
|
+
}
|
287
|
+
|
288
|
+
#{if result_var
|
289
|
+
"
|
290
|
+
#{result_var} = ((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(recv, (VALUE)pblock, (VALUE)pframe, #{strargs});
|
291
|
+
"
|
292
|
+
else
|
293
|
+
"
|
294
|
+
((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(recv, (VALUE)pblock, (VALUE)pframe, #{strargs});
|
295
|
+
"
|
296
|
+
end
|
297
|
+
}
|
298
|
+
|
299
|
+
|
300
|
+
}
|
301
|
+
"
|
302
|
+
result_var ? code : inline_block(code)
|
303
|
+
else
|
304
|
+
strargs = args[1..-1].map{|arg| to_c arg}.join(",")
|
305
|
+
"((VALUE(*)(#{value_cast}))#{encode_address(recvtype,signature,mname,tree,inference_complete)})(#{to_c recv}, Qfalse, (VALUE)pframe, #{strargs})"
|
306
|
+
end
|
145
307
|
end
|
146
308
|
|
147
309
|
else # else recvtype
|
148
310
|
if argnum == 0
|
149
|
-
protected_block("rb_funcall(#{to_c recv}, #{intern_num tree[2]}, 0)", true, repass_var)
|
311
|
+
code = protected_block("last_expression = rb_funcall(#{to_c recv}, #{intern_num tree[2]}, 0)", true, repass_var)
|
312
|
+
if result_var
|
313
|
+
"
|
314
|
+
#{result_var} = #{code};
|
315
|
+
"
|
316
|
+
else
|
317
|
+
code
|
318
|
+
end
|
150
319
|
else
|
151
|
-
|
320
|
+
strargs = args[1..-1].map{|arg| to_c arg}.join(",")
|
321
|
+
code = protected_block("last_expression = rb_funcall(#{to_c recv}, #{intern_num tree[2]}, #{argnum}, #{strargs} )", true, repass_var)
|
322
|
+
if result_var
|
323
|
+
"
|
324
|
+
#{result_var} = #{code};
|
325
|
+
"
|
326
|
+
else
|
327
|
+
code
|
328
|
+
end
|
152
329
|
end
|
153
330
|
end # if recvtype
|
154
331
|
end
|
@@ -22,7 +22,7 @@ module FastRuby
|
|
22
22
|
module DefnTranslator
|
23
23
|
register_translator_module self
|
24
24
|
|
25
|
-
def to_c_defn(tree)
|
25
|
+
def to_c_defn(tree, result_var = nil)
|
26
26
|
|
27
27
|
method_name = tree[1]
|
28
28
|
args_tree = tree[2].select{|x| x.to_s[0] != ?&}
|
@@ -40,27 +40,49 @@ module FastRuby
|
|
40
40
|
alt_options.delete(:self)
|
41
41
|
alt_options.delete(:main)
|
42
42
|
|
43
|
-
|
43
|
+
code = "
|
44
44
|
|
45
|
-
|
46
|
-
|
45
|
+
|
46
|
+
if (rb_obj_is_kind_of(plocals->self, rb_cClass) || rb_obj_is_kind_of(plocals->self, rb_cModule)) {
|
47
|
+
rb_define_method(plocals->self, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1);
|
48
|
+
|
49
|
+
#{global_klass_variable} = plocals->self;
|
50
|
+
// set tree
|
51
|
+
rb_funcall(#{literal_value FastRuby}, #{intern_num :set_tree}, 5,
|
52
|
+
#{global_klass_variable},
|
53
|
+
rb_str_new2(#{method_name.to_s.inspect}),
|
54
|
+
#{literal_value tree},
|
55
|
+
#{literal_value snippet_hash},
|
56
|
+
#{literal_value alt_options}
|
57
|
+
|
58
|
+
);
|
59
|
+
|
60
|
+
} else {
|
61
|
+
VALUE obj = plocals->self;
|
62
|
+
rb_define_singleton_method(obj, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1 );
|
63
|
+
|
64
|
+
#{global_klass_variable} = CLASS_OF(obj);
|
65
|
+
// set tree
|
66
|
+
rb_funcall(#{literal_value FastRuby}, #{intern_num :set_tree}, 5,
|
67
|
+
#{global_klass_variable},
|
68
|
+
rb_str_new2(#{method_name.to_s.inspect}),
|
69
|
+
#{literal_value tree},
|
70
|
+
#{literal_value snippet_hash},
|
71
|
+
#{literal_value alt_options}
|
72
|
+
|
73
|
+
);
|
74
|
+
}
|
47
75
|
|
48
|
-
#{global_klass_variable} = plocals->self;
|
49
|
-
// set tree
|
50
|
-
rb_funcall(#{literal_value FastRuby}, #{intern_num :set_tree}, 5,
|
51
|
-
#{global_klass_variable},
|
52
|
-
rb_str_new2(#{method_name.to_s.inspect}),
|
53
|
-
#{literal_value tree},
|
54
|
-
#{literal_value snippet_hash},
|
55
|
-
#{literal_value alt_options}
|
56
|
-
|
57
|
-
);
|
58
|
-
|
59
76
|
"
|
60
77
|
|
78
|
+
if result_var
|
79
|
+
code + "\n#{result_var} = Qnil;"
|
80
|
+
else
|
81
|
+
inline_block code + "\nreturn Qnil;\n"
|
82
|
+
end
|
61
83
|
end
|
62
84
|
|
63
|
-
def to_c_defs(tree)
|
85
|
+
def to_c_defs(tree, result_var = nil)
|
64
86
|
method_name = tree[2]
|
65
87
|
args_tree = tree[3].select{|x| x.to_s[0] != ?&}
|
66
88
|
|
@@ -78,9 +100,10 @@ module FastRuby
|
|
78
100
|
alt_options.delete(:self)
|
79
101
|
alt_options.delete(:main)
|
80
102
|
|
81
|
-
|
103
|
+
code = "
|
82
104
|
|
83
|
-
VALUE obj =
|
105
|
+
VALUE obj = Qnil;
|
106
|
+
#{to_c tree[1], "obj"};
|
84
107
|
rb_define_singleton_method(obj, #{method_name.to_s.inspect}, #{anonymous_method_name}, -1 );
|
85
108
|
|
86
109
|
#{global_klass_variable} = CLASS_OF(obj);
|
@@ -95,12 +118,22 @@ module FastRuby
|
|
95
118
|
);
|
96
119
|
|
97
120
|
"
|
121
|
+
|
122
|
+
if result_var
|
123
|
+
code + "\n#{result_var} = Qnil;"
|
124
|
+
else
|
125
|
+
inline_block code + "\nreturn Qnil;\n"
|
126
|
+
end
|
98
127
|
|
99
128
|
end
|
100
129
|
|
101
|
-
def to_c_scope(tree)
|
130
|
+
def to_c_scope(tree, result_var = nil)
|
102
131
|
if tree[1]
|
103
|
-
|
132
|
+
if result_var
|
133
|
+
to_c(tree[1], result_var)
|
134
|
+
else
|
135
|
+
to_c(tree[1])
|
136
|
+
end
|
104
137
|
else
|
105
138
|
"Qnil"
|
106
139
|
end
|
@@ -120,11 +153,11 @@ private
|
|
120
153
|
method_name[1] = 0;
|
121
154
|
|
122
155
|
sprintf(method_name+1, \"#{method_name}\");
|
123
|
-
sprintf(method_name+strlen(method_name), \"%lu\",
|
156
|
+
sprintf(method_name+strlen(method_name), \"%lu\", (unsigned long)NUM2PTR(rb_obj_id(CLASS_OF(self))));
|
124
157
|
|
125
158
|
int i;
|
126
159
|
for (i=0; i<argc_; i++) {
|
127
|
-
sprintf(method_name+strlen(method_name), \"%lu\",
|
160
|
+
sprintf(method_name+strlen(method_name), \"%lu\", (unsigned long)NUM2PTR(rb_obj_id(CLASS_OF(argv[i]))));
|
128
161
|
}
|
129
162
|
|
130
163
|
void** address = 0;
|
@@ -136,9 +169,9 @@ private
|
|
136
169
|
rb_method_hash = rb_funcall(klass, #{intern_num :method_hash},1,#{literal_value method_name});
|
137
170
|
|
138
171
|
if (rb_method_hash != Qnil) {
|
139
|
-
VALUE tmp = rb_hash_aref(rb_method_hash,
|
172
|
+
VALUE tmp = rb_hash_aref(rb_method_hash, PTR2NUM(id));
|
140
173
|
if (tmp != Qnil) {
|
141
|
-
address = (void**)
|
174
|
+
address = (void**)NUM2PTR(tmp);
|
142
175
|
fptr = *address;
|
143
176
|
}
|
144
177
|
}
|
@@ -159,9 +192,9 @@ private
|
|
159
192
|
rb_method_hash = rb_funcall(klass, #{intern_num :method_hash},1,#{literal_value method_name});
|
160
193
|
|
161
194
|
if (rb_method_hash != Qnil) {
|
162
|
-
VALUE tmp = rb_hash_aref(rb_method_hash,
|
195
|
+
VALUE tmp = rb_hash_aref(rb_method_hash, PTR2NUM(id));
|
163
196
|
if (tmp != Qnil) {
|
164
|
-
address = (void**)
|
197
|
+
address = (void**)NUM2PTR(tmp);
|
165
198
|
fptr = *address;
|
166
199
|
}
|
167
200
|
}
|
@@ -190,16 +223,18 @@ private
|
|
190
223
|
frame.thread_data = rb_current_thread_data();
|
191
224
|
frame.targetted = 0;
|
192
225
|
|
193
|
-
VALUE block = Qfalse;
|
226
|
+
volatile VALUE block = Qfalse;
|
194
227
|
|
195
228
|
if (rb_block_given_p()) {
|
196
229
|
struct {
|
197
|
-
void
|
198
|
-
void
|
230
|
+
void* block_function_address;
|
231
|
+
void* block_function_param;
|
232
|
+
VALUE proc;
|
199
233
|
} block_struct;
|
200
234
|
|
201
235
|
block_struct.block_function_address = re_yield;
|
202
236
|
block_struct.block_function_param = 0;
|
237
|
+
block_struct.proc = rb_block_proc();
|
203
238
|
|
204
239
|
block = (VALUE)&block_struct;
|
205
240
|
}
|