fastruby 0.0.16 → 0.0.17
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 +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
|
}
|