fastruby 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +2 -0
- data/README +18 -2
- data/Rakefile +1 -1
- data/lib/fastruby/builder.rb +144 -20
- data/lib/fastruby/cache/cache.rb +86 -0
- data/lib/fastruby/custom_require.rb +3 -0
- data/lib/fastruby/exceptions.rb +10 -0
- data/lib/fastruby/fastruby_sexp.rb +25 -0
- data/lib/fastruby/getlocals.rb +2 -2
- data/lib/fastruby/object.rb +57 -268
- data/lib/fastruby/set_tree.rb +61 -0
- data/lib/fastruby/sexp_extension.rb +37 -0
- data/lib/fastruby/translator.rb +748 -287
- data/lib/fastruby.rb +12 -2
- metadata +8 -4
data/lib/fastruby/object.rb
CHANGED
@@ -18,14 +18,10 @@ you should have received a copy of the gnu general public license
|
|
18
18
|
along with fastruby. if not, see <http://www.gnu.org/licenses/>.
|
19
19
|
|
20
20
|
=end
|
21
|
-
require "fastruby/translator"
|
22
21
|
require "fastruby/builder"
|
23
22
|
require "fastruby/getlocals"
|
24
23
|
require "fastruby/method_extension"
|
25
|
-
require "fastruby/
|
26
|
-
require "ruby_parser"
|
27
|
-
require "inline"
|
28
|
-
|
24
|
+
require "fastruby/cache/cache"
|
29
25
|
|
30
26
|
# clean rubyinline cache
|
31
27
|
system("rm -fr #{ENV["HOME"]}/.ruby_inline/*")
|
@@ -47,313 +43,106 @@ module FastRuby
|
|
47
43
|
s(:scope, s(:block, generated_tree)))
|
48
44
|
end
|
49
45
|
|
50
|
-
generated_tree
|
46
|
+
generated_tree.to_fastruby_sexp
|
51
47
|
end
|
52
48
|
end
|
53
49
|
|
54
50
|
class Object
|
55
|
-
|
56
51
|
def fastruby(argument, *options_hashes)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
elsif argument.instance_of? String
|
62
|
-
tree = RubyParser.new.parse(argument)
|
63
|
-
else
|
64
|
-
raise ArgumentError
|
52
|
+
options_hash = {:validate_lvar_types => true}
|
53
|
+
options_hash[:no_cache] = true if ENV['FASTRUBY_NO_CACHE'] == "1"
|
54
|
+
options_hashes.each do |opt|
|
55
|
+
options_hash.merge!(opt)
|
65
56
|
end
|
66
57
|
|
67
|
-
|
58
|
+
objs = Array.new
|
68
59
|
|
69
|
-
|
70
|
-
|
60
|
+
unless options_hash[:no_cache]
|
61
|
+
snippet_hash = FastRuby.cache.hash_snippet(argument,options_hash[:validate_lvar_types].to_s)
|
62
|
+
objs = FastRuby.cache.retrieve(snippet_hash)
|
63
|
+
end
|
71
64
|
|
72
|
-
|
73
|
-
superclassname = Object.to_class_name tree[2]
|
65
|
+
if objs.empty?
|
74
66
|
|
75
|
-
|
76
|
-
class #{classname} < #{superclassname}
|
77
|
-
end
|
78
|
-
", $top_level_binding)
|
67
|
+
tree = nil
|
79
68
|
|
69
|
+
require "fastruby/fastruby_sexp"
|
70
|
+
if argument.instance_of? FastRuby::FastRubySexp
|
71
|
+
tree = argument
|
72
|
+
elsif argument.instance_of? String
|
73
|
+
require "rubygems"
|
74
|
+
require "ruby_parser"
|
75
|
+
require "fastruby/sexp_extension"
|
76
|
+
tree = RubyParser.new.parse(argument).to_fastruby_sexp
|
80
77
|
else
|
81
|
-
|
82
|
-
class #{classname}
|
83
|
-
end
|
84
|
-
", $top_level_binding)
|
85
|
-
end
|
86
|
-
|
87
|
-
klass = eval(classname)
|
88
|
-
|
89
|
-
method_name = "_anonymous_" + rand(100000000000).to_s
|
90
|
-
$generated_tree = FastRuby.encapsulate_tree(tree[3],method_name)
|
91
|
-
$options_hashes = options_hashes
|
92
|
-
|
93
|
-
klass.class_eval do
|
94
|
-
class << self
|
95
|
-
fastruby $generated_tree, *$options_hashes
|
96
|
-
end
|
78
|
+
raise ArgumentError
|
97
79
|
end
|
98
80
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
eval("
|
104
|
-
module #{modulename}
|
105
|
-
end
|
106
|
-
", $top_level_binding)
|
107
|
-
|
108
|
-
klass = eval(modulename)
|
109
|
-
|
110
|
-
method_name = "_anonymous_" + rand(100000000000).to_s
|
111
|
-
$generated_tree = FastRuby.encapsulate_tree(tree[2],method_name)
|
112
|
-
$options_hashes = options_hashes
|
81
|
+
return unless tree
|
82
|
+
method_name = "_anonymous_" + rand(100000000000).to_s
|
83
|
+
Object.execute_tree(FastRuby.encapsulate_tree(tree,method_name), :main => method_name, :self => self, :snippet_hash => snippet_hash, *[options_hash])
|
113
84
|
|
114
|
-
klass.class_eval do
|
115
|
-
class << self
|
116
|
-
fastruby $generated_tree, *$options_hashes
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
klass.send(method_name)
|
121
|
-
elsif tree[0] == :defn
|
122
|
-
Object.fastruby_defn(tree, *options_hashes)
|
123
85
|
else
|
124
|
-
method_name = "_anonymous_" + rand(100000000000).to_s
|
125
|
-
Object.fastruby(FastRuby.encapsulate_tree(tree,method_name), *options_hashes)
|
126
|
-
send(method_name)
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def self.fastruby_defs(*args)
|
131
|
-
raise NoMethodError, "not implemented yet"
|
132
|
-
end
|
133
|
-
|
134
|
-
def self.fastruby(argument,*options_hashes)
|
135
86
|
|
136
|
-
|
87
|
+
objs.sort{|x,y|
|
88
|
+
(y =~ /Inline_Object/ ? 1 : 0) - (x =~ /Inline_Object/ ? 1 : 0)
|
89
|
+
}.each do |obj|
|
137
90
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
return unless tree
|
147
|
-
|
148
|
-
if tree.node_type == :defn
|
149
|
-
fastruby_defn(tree,*options_hashes)
|
150
|
-
else
|
151
|
-
method_name = "_anonymous_" + rand(100000000000).to_s
|
152
|
-
$generated_tree = FastRuby.encapsulate_tree(tree,method_name)
|
153
|
-
$options_hashes = options_hashes
|
154
|
-
|
155
|
-
klass = self
|
156
|
-
klass.class_eval do
|
157
|
-
class << self
|
158
|
-
fastruby_defn($generated_tree,*$options_hashes)
|
91
|
+
begin
|
92
|
+
$last_obj_proc = nil
|
93
|
+
require obj
|
94
|
+
if $last_obj_proc
|
95
|
+
FastRuby.cache.register_proc(obj, $last_obj_proc)
|
96
|
+
end
|
97
|
+
FastRuby.cache.execute(obj, self)
|
98
|
+
rescue
|
159
99
|
end
|
160
100
|
end
|
161
|
-
|
162
|
-
send(method_name)
|
163
101
|
end
|
164
|
-
|
165
102
|
end
|
166
103
|
|
167
|
-
def self.
|
168
|
-
|
104
|
+
def self.execute_tree(argument,*options_hashes)
|
169
105
|
options_hash = {:validate_lvar_types => true}
|
170
106
|
options_hashes.each do |opt|
|
171
107
|
options_hash.merge!(opt)
|
172
108
|
end
|
173
109
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
110
|
+
require "fastruby/fastruby_sexp"
|
111
|
+
if argument.instance_of? FastRuby::FastRubySexp
|
112
|
+
tree = argument
|
113
|
+
elsif argument.instance_of? String
|
114
|
+
require "rubygems"
|
115
|
+
require "ruby_parser"
|
116
|
+
require "fastruby/sexp_extension"
|
117
|
+
tree = RubyParser.new.parse(argument).to_fastruby_sexp
|
118
|
+
else
|
119
|
+
require "pry"
|
120
|
+
binding.pry
|
121
|
+
raise ArgumentError
|
182
122
|
end
|
183
123
|
|
184
124
|
method_name = tree[1]
|
185
|
-
args_tree = tree[2]
|
186
|
-
|
187
|
-
hashname = "$hash" + rand(1000000).to_s
|
188
125
|
|
189
|
-
|
126
|
+
self_ = options_hash[:self]
|
127
|
+
self_ = self unless self_.instance_of? Class
|
190
128
|
|
191
|
-
|
192
|
-
locals << :self
|
129
|
+
FastRuby.set_tree(self_, method_name, tree, options_hash[:snippet_hash], options_hash)
|
193
130
|
|
194
|
-
|
195
|
-
|
131
|
+
class << self
|
132
|
+
$metaclass = self
|
196
133
|
end
|
197
134
|
|
198
|
-
self_
|
199
|
-
hash.instance_eval{@klass = self_}
|
200
|
-
hash.instance_eval{@method_name = method_name}
|
201
|
-
|
202
|
-
class_eval do
|
203
|
-
class << self
|
204
|
-
include FastRuby::BuilderModule
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
fastrubym = self_.fastruby_method(method_name)
|
209
|
-
fastrubym.tree = tree
|
210
|
-
fastrubym.locals = locals
|
211
|
-
fastrubym.options = options_hash
|
212
|
-
|
213
|
-
def hash.build(key)
|
214
|
-
@klass.build(key, @method_name)
|
215
|
-
end
|
216
|
-
|
217
|
-
eval("#{hashname} = hash")
|
218
|
-
|
219
|
-
value_cast = ( ["VALUE"]*(args_tree.size+2) ).join(",")
|
220
|
-
|
221
|
-
main_signature_argument = args_tree[1..-1].first || "self"
|
222
|
-
|
223
|
-
strmethodargs = ""
|
224
|
-
strmethodargs_class = (["self"] + args_tree[1..-1]).map{|arg| "CLASS_OF(#{arg.to_s})"}.join(",")
|
225
|
-
|
226
|
-
if args_tree.size > 1
|
227
|
-
strmethodargs = "self,block,(VALUE)&frame,#{args_tree[1..-1].map(&:to_s).join(",") }"
|
228
|
-
else
|
229
|
-
strmethodargs = "self,block,(VALUE)&frame"
|
230
|
-
end
|
231
|
-
|
232
|
-
strmethod_signature = (["self"] + args_tree[1..-1]).map { |arg|
|
233
|
-
"sprintf(method_name+strlen(method_name), \"%lu\", CLASS_OF(#{arg}));\n"
|
234
|
-
}.join
|
235
|
-
|
236
|
-
c_code = "VALUE #{method_name}(#{args_tree[1..-1].map{|arg| "VALUE #{arg}" }.join(",")}) {
|
237
|
-
VALUE method_hash = (VALUE)#{hash.internal_value};
|
238
|
-
VALUE klass = (VALUE)#{self.internal_value};
|
239
|
-
|
240
|
-
char method_name[0x100];
|
241
|
-
|
242
|
-
method_name[0] = '_';
|
243
|
-
method_name[1] = 0;
|
244
|
-
|
245
|
-
sprintf(method_name+1, \"#{method_name}\");
|
246
|
-
#{strmethod_signature}
|
247
|
-
|
248
|
-
NODE* body;
|
249
|
-
ID id;
|
250
|
-
|
251
|
-
id = rb_intern(method_name);
|
252
|
-
body = rb_method_node(klass,id);
|
253
|
-
|
254
|
-
if (body == 0) {
|
255
|
-
VALUE argv_class[] = {#{strmethodargs_class} };
|
256
|
-
VALUE signature = rb_ary_new4(#{args_tree.size},argv_class);
|
257
|
-
|
258
|
-
rb_funcall(method_hash, #{:build.to_i}, 1, signature);
|
259
|
-
body = rb_method_node(klass,id);
|
260
|
-
}
|
261
|
-
|
262
|
-
if (nd_type(body) == NODE_CFUNC) {
|
263
|
-
struct {
|
264
|
-
void* parent_frame;
|
265
|
-
void* target_frame;
|
266
|
-
void* plocals;
|
267
|
-
jmp_buf jmp;
|
268
|
-
VALUE return_value;
|
269
|
-
VALUE exception;
|
270
|
-
int rescue;
|
271
|
-
} frame;
|
272
|
-
|
273
|
-
frame.target_frame = 0;
|
274
|
-
frame.parent_frame = 0;
|
275
|
-
frame.rescue = 0;
|
276
|
-
frame.exception = Qnil;
|
277
|
-
frame.return_value = Qnil;
|
278
|
-
|
279
|
-
int argc = body->nd_argc;
|
280
|
-
|
281
|
-
VALUE block = Qfalse;
|
282
|
-
|
283
|
-
if (rb_block_given_p()) {
|
284
|
-
struct {
|
285
|
-
void *block_function_address;
|
286
|
-
void *block_function_param;
|
287
|
-
} block_struct;
|
288
|
-
|
289
|
-
block_struct.block_function_address = re_yield;
|
290
|
-
block_struct.block_function_param = 0;
|
291
|
-
|
292
|
-
block = (VALUE)&block_struct;
|
293
|
-
}
|
294
|
-
|
295
|
-
int aux = setjmp(frame.jmp);
|
296
|
-
if (aux != 0) {
|
297
|
-
if (frame.target_frame == (void*)-1) {
|
298
|
-
rb_funcall(self, #{:raise.to_i}, 1, frame.exception);
|
299
|
-
}
|
300
|
-
|
301
|
-
if (frame.target_frame != &frame) {
|
302
|
-
VALUE ex = rb_funcall(
|
303
|
-
(VALUE)#{FastRuby::Context::UnwindFastrubyFrame.internal_value},
|
304
|
-
#{:new.to_i},
|
305
|
-
3,
|
306
|
-
frame.exception,
|
307
|
-
LONG2FIX(frame.target_frame),
|
308
|
-
frame.return_value
|
309
|
-
);
|
310
|
-
|
311
|
-
rb_funcall(self, #{:raise.to_i}, 1, ex);
|
312
|
-
}
|
313
|
-
|
314
|
-
return Qnil;
|
315
|
-
}
|
316
|
-
|
317
|
-
if (argc == #{args_tree.size+1}) {
|
318
|
-
return ((VALUE(*)(#{value_cast}))body->nd_cfnc)(#{strmethodargs});
|
319
|
-
} else if (argc == -1) {
|
320
|
-
VALUE argv[] = {#{(["block,(VALUE)&frame"]+args_tree[1..-1]).map(&:to_s).join(",")} };
|
321
|
-
return ((VALUE(*)(int,VALUE*,VALUE))body->nd_cfnc)(#{args_tree.size},argv,self);
|
322
|
-
} else if (argc == -2) {
|
323
|
-
VALUE argv[] = {#{(["block,(VALUE)&frame"]+args_tree[1..-1]).map(&:to_s).join(",")} };
|
324
|
-
return ((VALUE(*)(VALUE,VALUE))body->nd_cfnc)(self, rb_ary_new4(#{args_tree.size},argv));
|
325
|
-
} else {
|
326
|
-
rb_raise(rb_eArgError, \"wrong number of arguments (#{args_tree.size-1} for %d)\", argc);
|
327
|
-
}
|
328
|
-
}
|
329
|
-
|
330
|
-
return Qnil;
|
331
|
-
}"
|
332
|
-
|
333
|
-
inline :C do |builder|
|
334
|
-
builder.include "<node.h>"
|
335
|
-
builder.inc << "static VALUE re_yield(int argc, VALUE* argv, VALUE param, VALUE _parent_frame) {
|
336
|
-
return rb_yield_splat(rb_ary_new4(argc,argv));
|
337
|
-
}"
|
338
|
-
builder.c c_code
|
339
|
-
end
|
135
|
+
self_.build([$class_self],method_name,true)
|
340
136
|
end
|
341
137
|
|
342
|
-
def
|
138
|
+
def gc_register_object
|
343
139
|
$refered_from_code_array = Array.new unless $refered_from_code_array
|
344
140
|
$refered_from_code_array << self
|
345
|
-
|
346
|
-
internal_value_
|
347
|
-
end
|
348
|
-
|
349
|
-
inline :C do |builder|
|
350
|
-
builder.c "VALUE internal_value_() {
|
351
|
-
return INT2FIX(self);
|
352
|
-
}"
|
353
141
|
end
|
354
142
|
|
355
143
|
private
|
356
144
|
def self.to_class_name(argument)
|
145
|
+
require "sexp"
|
357
146
|
if argument.instance_of? Symbol
|
358
147
|
argument.to_s
|
359
148
|
elsif argument.instance_of? Sexp
|
@@ -0,0 +1,61 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
This file is part of the fastruby project, http://github.com/tario/fastruby
|
4
|
+
|
5
|
+
Copyright (c) 2011 Roberto Dario Seminara <robertodarioseminara@gmail.com>
|
6
|
+
|
7
|
+
fastruby is free software: you can redistribute it and/or modify
|
8
|
+
it under the terms of the gnu general public license as published by
|
9
|
+
the free software foundation, either version 3 of the license, or
|
10
|
+
(at your option) any later version.
|
11
|
+
|
12
|
+
fastruby is distributed in the hope that it will be useful,
|
13
|
+
but without any warranty; without even the implied warranty of
|
14
|
+
merchantability or fitness for a particular purpose. see the
|
15
|
+
gnu general public license for more details.
|
16
|
+
|
17
|
+
you should have received a copy of the gnu general public license
|
18
|
+
along with fastruby. if not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
=end
|
21
|
+
require "fastruby/builder"
|
22
|
+
require "fastruby/getlocals"
|
23
|
+
require "fastruby/method_extension"
|
24
|
+
|
25
|
+
module FastRuby
|
26
|
+
|
27
|
+
def self.make_str_signature(method_name, signature)
|
28
|
+
"_" + method_name.to_s + signature.map(&:__id__).map(&:to_s).join
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.set_builder_module(klass)
|
32
|
+
klass.class_eval do
|
33
|
+
class << self
|
34
|
+
include FastRuby::BuilderModule
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.set_tree(klass, method_name, tree, snippet_hash, options = {})
|
40
|
+
locals = Set.new
|
41
|
+
locals << :self
|
42
|
+
|
43
|
+
FastRuby::GetLocalsProcessor.get_locals(tree).each do |local|
|
44
|
+
locals << local
|
45
|
+
end
|
46
|
+
|
47
|
+
klass.class_eval do
|
48
|
+
class << self
|
49
|
+
include FastRuby::BuilderModule
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
fastrubym = klass.fastruby_method(method_name)
|
54
|
+
fastrubym.tree = tree
|
55
|
+
fastrubym.locals = locals
|
56
|
+
fastrubym.options = options
|
57
|
+
fastrubym.snippet_hash = snippet_hash
|
58
|
+
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
This file is part of the fastruby project, http://github.com/tario/fastruby
|
4
|
+
|
5
|
+
Copyright (c) 2011 Roberto Dario Seminara <robertodarioseminara@gmail.com>
|
6
|
+
|
7
|
+
fastruby is free software: you can redistribute it and/or modify
|
8
|
+
it under the terms of the gnu general public license as published by
|
9
|
+
the free software foundation, either version 3 of the license, or
|
10
|
+
(at your option) any later version.
|
11
|
+
|
12
|
+
fastruby is distributed in the hope that it will be useful,
|
13
|
+
but without any warranty; without even the implied warranty of
|
14
|
+
merchantability or fitness for a particular purpose. see the
|
15
|
+
gnu general public license for more details.
|
16
|
+
|
17
|
+
you should have received a copy of the gnu general public license
|
18
|
+
along with fastruby. if not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
=end
|
21
|
+
require "fastruby/fastruby_sexp"
|
22
|
+
|
23
|
+
class Object
|
24
|
+
def to_fastruby_sexp
|
25
|
+
self
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Sexp
|
30
|
+
def to_fastruby_sexp
|
31
|
+
ary = FastRuby::FastRubySexp.new
|
32
|
+
each do |x|
|
33
|
+
ary << x.to_fastruby_sexp
|
34
|
+
end
|
35
|
+
ary
|
36
|
+
end
|
37
|
+
end
|