fastruby 0.0.5 → 0.0.6
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 +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
|