fastruby 0.0.19 → 0.0.20
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +8 -0
- data/{README → README.rdoc} +6 -1
- data/Rakefile +7 -7
- data/benchmarks/benchmark.rb~ +14 -2
- data/ext/fastruby_base/fastruby_base.inl +8 -4
- data/lib/fastruby/builder/inference_updater.rb +76 -0
- data/lib/fastruby/builder/inference_updater.rb~ +76 -0
- data/lib/fastruby/builder/inferencer.rb +38 -0
- data/lib/fastruby/{inliner → builder}/inliner.rb +16 -27
- data/lib/fastruby/builder/inliner.rb~ +60 -0
- data/lib/fastruby/builder/locals_inference.rb +53 -0
- data/lib/fastruby/builder/lvar_type.rb +43 -0
- data/lib/fastruby/builder/lvar_type.rb~ +44 -0
- data/lib/fastruby/builder/pipeline.rb +43 -0
- data/lib/fastruby/builder/pipeline.rb~ +43 -0
- data/lib/fastruby/{reductor → builder}/reductor.rb +6 -3
- data/lib/fastruby/builder/reductor.rb~ +42 -0
- data/lib/fastruby/builder.rb +73 -25
- data/lib/fastruby/builder.rb~ +311 -0
- data/lib/fastruby/corelib/fixnum.rb +75 -0
- data/lib/fastruby/corelib/fixnum.rb~ +146 -0
- data/lib/fastruby/corelib/integer.rb +96 -0
- data/lib/fastruby/corelib/integer.rb~ +96 -0
- data/lib/fastruby/corelib.rb +23 -0
- data/lib/fastruby/corelib.rb~ +23 -0
- data/lib/fastruby/getlocals.rb +3 -1
- data/lib/fastruby/logging.rb +2 -2
- data/lib/fastruby/modules/inferencer/infer.rb +31 -0
- data/lib/fastruby/modules/inferencer/literal.rb +42 -0
- data/lib/fastruby/modules/inliner/call.rb +327 -0
- data/lib/fastruby/{inliner/modules/call.rb → modules/inliner/call.rb~} +14 -24
- data/lib/fastruby/modules/inliner/defn.rb +41 -0
- data/lib/fastruby/modules/inliner/defn.rb~ +29 -0
- data/lib/fastruby/modules/inliner/recursive.rb +40 -0
- data/lib/fastruby/{inliner/modules/recursive.rb → modules/inliner/recursive.rb~} +1 -1
- data/lib/fastruby/modules/lvar_type/call.rb +36 -0
- data/lib/fastruby/modules/lvar_type/call.rb~ +36 -0
- data/lib/fastruby/modules/lvar_type/defn.rb +42 -0
- data/lib/fastruby/modules/lvar_type/defn.rb~ +42 -0
- data/lib/fastruby/modules/lvar_type/lasgn.rb +41 -0
- data/lib/fastruby/modules/lvar_type/lasgn.rb~ +42 -0
- data/lib/fastruby/modules/lvar_type/recursive.rb +33 -0
- data/lib/fastruby/modules/lvar_type/recursive.rb~ +33 -0
- data/lib/fastruby/{reductor/modules → modules/reductor}/case.rb +0 -0
- data/lib/fastruby/modules/reductor/fastruby_flag.rb +33 -0
- data/lib/fastruby/{reductor/modules → modules/reductor}/for.rb +0 -0
- data/lib/fastruby/{reductor/modules → modules/reductor}/nontree.rb +0 -0
- data/lib/fastruby/modules/reductor/nontree.rb~ +32 -0
- data/lib/fastruby/{reductor/modules → modules/reductor}/recursive.rb +1 -1
- data/lib/fastruby/modules/reductor/recursive.rb~ +31 -0
- data/lib/fastruby/{translator/modules → modules/translator}/block.rb +0 -0
- data/lib/fastruby/modules/translator/call.rb +344 -0
- data/lib/fastruby/{translator/modules/call.rb → modules/translator/call.rb~} +24 -3
- data/lib/fastruby/{translator/modules → modules/translator}/defn.rb +10 -9
- data/lib/fastruby/modules/translator/defn.rb~ +267 -0
- data/lib/fastruby/{translator/modules → modules/translator}/directive.rb +3 -1
- data/lib/fastruby/modules/translator/directive.rb~ +44 -0
- data/lib/fastruby/{translator/modules → modules/translator}/exceptions.rb +3 -1
- data/lib/fastruby/modules/translator/exceptions.rb~ +120 -0
- data/lib/fastruby/{translator/modules → modules/translator}/flow.rb +0 -0
- data/lib/fastruby/modules/translator/iter.rb +745 -0
- data/lib/fastruby/{translator/modules/iter.rb → modules/translator/iter.rb~} +103 -48
- data/lib/fastruby/modules/translator/literal.rb +150 -0
- data/lib/fastruby/{translator/modules/literal.rb → modules/translator/literal.rb~} +3 -3
- data/lib/fastruby/{translator/modules → modules/translator}/logical.rb +0 -0
- data/lib/fastruby/{translator/modules → modules/translator}/method_group.rb +0 -0
- data/lib/fastruby/{translator/modules → modules/translator}/nonlocal.rb +18 -6
- data/lib/fastruby/modules/translator/nonlocal.rb~ +298 -0
- data/lib/fastruby/modules/translator/static.rb +290 -0
- data/lib/fastruby/{translator/modules/static.rb → modules/translator/static.rb~} +66 -17
- data/lib/fastruby/modules/translator/variable.rb +280 -0
- data/lib/fastruby/{translator/modules/variable.rb → modules/translator/variable.rb~} +14 -44
- data/lib/fastruby/modules.rb +30 -0
- data/lib/fastruby/object.rb +42 -6
- data/lib/fastruby/object.rb~ +159 -0
- data/lib/fastruby/set_tree.rb +7 -11
- data/lib/fastruby/set_tree.rb~ +71 -0
- data/lib/fastruby/sexp_extension.rb +29 -7
- data/lib/fastruby/sexp_extension.rb~ +262 -0
- data/lib/fastruby/translator/scope_mode_helper.rb~ +138 -0
- data/lib/fastruby/translator/translator.rb +87 -92
- data/lib/fastruby/translator/translator.rb~ +1600 -0
- data/lib/fastruby/translator/translator_modules.rb +3 -1
- data/lib/fastruby/translator/translator_modules.rb~ +53 -0
- data/lib/fastruby.rb +3 -1
- data/lib/fastruby.rb~ +3 -1
- data/lib/fastruby_only/base.rb +1 -0
- data/spec/corelib/numeric/fixnum_spec.rb +110 -0
- data/spec/corelib/numeric/fixnum_spec.rb~ +104 -0
- data/spec/corelib/numeric/integer_spec.rb +173 -0
- data/spec/corelib/numeric/integer_spec.rb~ +173 -0
- data/spec/fastruby_only/base_spec.rb +74 -0
- data/spec/graph/base_spec.rb +2 -1
- data/spec/graph/base_spec.rb~ +35 -0
- data/spec/graph/path_spec.rb +2 -2
- data/spec/graph/path_spec.rb~ +48 -0
- data/spec/graph/vertex_spec.rb +2 -1
- data/spec/graph/vertex_spec.rb~ +58 -0
- data/spec/reductor/base_spec.rb +1 -1
- data/spec/ruby/block/lambda_spec.rb~ +163 -0
- data/spec/ruby/block/proc_as_block_spec.rb~ +69 -1
- data/spec/ruby/block_spec.rb~ +2 -494
- data/spec/ruby/call/base_call_spec.rb +1 -1
- data/spec/ruby/call/base_call_spec.rb~ +2 -60
- data/spec/ruby/defn/replacement_spec.rb +26 -14
- data/spec/ruby/defn/replacement_spec.rb~ +13 -3
- data/spec/ruby/exception/internal_ex_spec.rb~ +86 -0
- data/spec/ruby/integrity_spec.rb~ +35 -1
- data/spec/ruby/variable_spec.rb~ +31 -0
- data/spec/scope_mode/flow_spec.rb +1 -1
- data/spec/scope_mode/flow_spec.rb~ +109 -0
- data/spec/sugar/base_spec.rb +29 -0
- data/spec/sugar/base_spec.rb~ +16 -0
- metadata +100 -43
- 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/block/arguments_spec.rb~ +0 -214
- data/spec/ruby/block/break_spec.rb~ +0 -236
- data/spec/ruby/block/next_spec.rb~ +0 -85
- data/spec/ruby/block/retry_spec.rb~ +0 -43
@@ -0,0 +1,159 @@
|
|
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
|
+
require "fastruby/cache/cache"
|
25
|
+
require "fastruby/sexp_extension"
|
26
|
+
require "fastruby"
|
27
|
+
require "digest"
|
28
|
+
require "method_source"
|
29
|
+
|
30
|
+
# clean rubyinline cache
|
31
|
+
system("rm -fr #{ENV["HOME"]}/.ruby_inline/*")
|
32
|
+
|
33
|
+
$top_level_binding = binding
|
34
|
+
|
35
|
+
def lvar_type(*x); end
|
36
|
+
|
37
|
+
class Class
|
38
|
+
def optimize(method_name)
|
39
|
+
fastruby instance_method(method_name).source
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module FastRuby
|
44
|
+
def self.encapsulate_tree(tree, method_name)
|
45
|
+
generated_tree = tree
|
46
|
+
|
47
|
+
if generated_tree[0] == :scope
|
48
|
+
generated_tree = s(:defn, method_name.to_sym, s(:args),
|
49
|
+
s(:scope, s(:block, generated_tree[1])))
|
50
|
+
elsif generated_tree[0] == :block
|
51
|
+
generated_tree = s(:defn, method_name.to_sym, s(:args),
|
52
|
+
s(:scope, generated_tree))
|
53
|
+
else
|
54
|
+
generated_tree = s(:defn, method_name.to_sym, s(:args),
|
55
|
+
s(:scope, s(:block, generated_tree)))
|
56
|
+
end
|
57
|
+
|
58
|
+
generated_tree.to_fastruby_sexp
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class Object
|
63
|
+
def fastruby?
|
64
|
+
false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class Object
|
69
|
+
|
70
|
+
def infer(a); self; end
|
71
|
+
def fastruby(*arguments, &blk)
|
72
|
+
if blk
|
73
|
+
method_container = Class.new
|
74
|
+
class << method_container
|
75
|
+
attr_accessor :_self
|
76
|
+
attr_accessor :fastruby_options
|
77
|
+
end
|
78
|
+
|
79
|
+
method_container._self = self
|
80
|
+
method_container.fastruby_options = arguments.inject({},&:merge)
|
81
|
+
|
82
|
+
def method_container.method_added(mname)
|
83
|
+
m = instance_method(mname)
|
84
|
+
if fastruby_options[:fastruby_only]
|
85
|
+
tree = FastRuby::FastRubySexp.parse m.source
|
86
|
+
|
87
|
+
unless FastRuby.acceptable_tree?(tree)
|
88
|
+
_self.class_eval(m.source)
|
89
|
+
return
|
90
|
+
end
|
91
|
+
|
92
|
+
FastRuby.set_tree(_self, tree[1], tree, fastruby_options)
|
93
|
+
else
|
94
|
+
@_self.fastruby m.source, fastruby_options
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
method_container.class_eval(&blk)
|
99
|
+
|
100
|
+
return nil
|
101
|
+
end
|
102
|
+
|
103
|
+
options_hashes = arguments[1..-1]
|
104
|
+
argument = arguments.first
|
105
|
+
|
106
|
+
options_hash = {:validate_lvar_types => true}
|
107
|
+
options_hashes.each do |opt|
|
108
|
+
options_hash.merge!(opt)
|
109
|
+
end
|
110
|
+
|
111
|
+
tree = nil
|
112
|
+
|
113
|
+
require "fastruby/fastruby_sexp" unless defined? FastRuby::FastRubySexp
|
114
|
+
if argument.instance_of? FastRuby::FastRubySexp
|
115
|
+
tree = argument
|
116
|
+
elsif argument.instance_of? String
|
117
|
+
unless defined? RubyParser
|
118
|
+
require "rubygems"
|
119
|
+
require "ruby_parser"
|
120
|
+
end
|
121
|
+
tree = RubyParser.new.parse(argument).to_fastruby_sexp
|
122
|
+
else
|
123
|
+
raise ArgumentError
|
124
|
+
end
|
125
|
+
|
126
|
+
return unless tree
|
127
|
+
method_name = "_anonymous_" + Digest::SHA1.hexdigest(tree.inspect)
|
128
|
+
Object.execute_tree(FastRuby.encapsulate_tree(tree,method_name), {:main => method_name, :self => self}.merge(options_hash))
|
129
|
+
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.execute_tree(tree,*options_hashes)
|
134
|
+
options_hash = {:validate_lvar_types => true}
|
135
|
+
options_hashes.each do |opt|
|
136
|
+
options_hash.merge!(opt)
|
137
|
+
end
|
138
|
+
|
139
|
+
require "fastruby/fastruby_sexp"
|
140
|
+
method_name = tree[1]
|
141
|
+
|
142
|
+
self_ = options_hash[:self]
|
143
|
+
self_ = self unless self_.instance_of? Class
|
144
|
+
|
145
|
+
FastRuby.set_tree(self_, method_name, tree, options_hash)
|
146
|
+
|
147
|
+
class << self
|
148
|
+
$metaclass = self
|
149
|
+
end
|
150
|
+
|
151
|
+
self_.build([$class_self],method_name,true)
|
152
|
+
end
|
153
|
+
|
154
|
+
def gc_register_object
|
155
|
+
$refered_from_code_array = Array.new unless $refered_from_code_array
|
156
|
+
$refered_from_code_array << self
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
data/lib/fastruby/set_tree.rb
CHANGED
@@ -21,7 +21,6 @@ along with fastruby. if not, see <http://www.gnu.org/licenses/>.
|
|
21
21
|
require "fastruby/builder"
|
22
22
|
require "fastruby/getlocals"
|
23
23
|
require "fastruby/method_extension"
|
24
|
-
require "fastruby/reductor/reductor"
|
25
24
|
|
26
25
|
module FastRuby
|
27
26
|
|
@@ -44,14 +43,13 @@ module FastRuby
|
|
44
43
|
nil
|
45
44
|
end
|
46
45
|
|
47
|
-
def self.set_tree(klass, method_name, tree,
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
locals << local
|
46
|
+
def self.set_tree(klass, method_name, tree, options = {})
|
47
|
+
unless options[:skip_reduce]
|
48
|
+
unless defined? Reductor
|
49
|
+
require "fastruby/builder/reductor"
|
50
|
+
end
|
51
|
+
|
52
|
+
tree = Reductor.new.reduce(tree)
|
55
53
|
end
|
56
54
|
|
57
55
|
klass.class_eval do
|
@@ -63,9 +61,7 @@ module FastRuby
|
|
63
61
|
fastrubym = klass.fastruby_method(method_name)
|
64
62
|
|
65
63
|
fastrubym.tree = tree
|
66
|
-
fastrubym.locals = locals
|
67
64
|
fastrubym.options = options
|
68
|
-
fastrubym.snippet_hash = snippet_hash
|
69
65
|
fastrubym.tree_changed
|
70
66
|
|
71
67
|
nil
|
@@ -0,0 +1,71 @@
|
|
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.unset_tree(klass, method_name)
|
40
|
+
fastrubym = klass.fastruby_method(method_name)
|
41
|
+
fastrubym.tree = nil
|
42
|
+
fastrubym.tree_changed
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.set_tree(klass, method_name, tree, options = {})
|
47
|
+
unless options[:skip_reduce]
|
48
|
+
unless defined? Reductor
|
49
|
+
require "fastruby/builder/reductor"
|
50
|
+
end
|
51
|
+
|
52
|
+
tree = Reductor.new.reduce(tree)
|
53
|
+
end
|
54
|
+
|
55
|
+
klass.class_eval do
|
56
|
+
class << self
|
57
|
+
include FastRuby::BuilderModule
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
fastrubym = klass.fastruby_method(method_name)
|
62
|
+
|
63
|
+
fastrubym.tree = tree
|
64
|
+
fastrubym.options = options
|
65
|
+
fastrubym.tree_changed
|
66
|
+
require "pry"; binding.pry
|
67
|
+
|
68
|
+
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
end
|
@@ -30,9 +30,32 @@ class Object
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def fs(*args)
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
if String === args.first
|
34
|
+
tree = FastRuby::FastRubySexp.parse(args.first)
|
35
|
+
|
36
|
+
if args.size > 1
|
37
|
+
replacement_hash = {}
|
38
|
+
args[1..-1].each do |arg|
|
39
|
+
replacement_hash.merge!(arg)
|
40
|
+
end
|
41
|
+
|
42
|
+
tree = tree.transform{|subtree|
|
43
|
+
if subtree.node_type == :call
|
44
|
+
next replacement_hash[subtree[2]]
|
45
|
+
elsif subtree.node_type == :lvar
|
46
|
+
next replacement_hash[subtree[1]]
|
47
|
+
else
|
48
|
+
next nil
|
49
|
+
end
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
tree
|
54
|
+
else
|
55
|
+
sexp = FastRuby::FastRubySexp.new
|
56
|
+
args.each {|subtree| sexp << subtree}
|
57
|
+
sexp
|
58
|
+
end
|
36
59
|
end
|
37
60
|
|
38
61
|
module FastRuby
|
@@ -56,14 +79,14 @@ module FastRuby
|
|
56
79
|
@vertexes << orig
|
57
80
|
@vertexes << dest
|
58
81
|
|
59
|
-
@vertex_output[orig] ||= Set.new
|
60
|
-
@vertex_output[orig] << dest
|
82
|
+
@vertex_output[orig.object_id] ||= Set.new
|
83
|
+
@vertex_output[orig.object_id] << dest
|
61
84
|
|
62
85
|
@edges << [orig,dest]
|
63
86
|
end
|
64
87
|
|
65
88
|
def each_vertex_output(vertex,&blk)
|
66
|
-
outputs = @vertex_output[vertex]
|
89
|
+
outputs = @vertex_output[vertex.object_id]
|
67
90
|
if outputs
|
68
91
|
blk ? outputs.each(&blk) : outputs
|
69
92
|
else
|
@@ -102,7 +125,6 @@ module FastRuby
|
|
102
125
|
|
103
126
|
def transform(&blk)
|
104
127
|
ret = FastRuby::FastRubySexp.from_sexp( blk.call(self) )
|
105
|
-
|
106
128
|
unless ret
|
107
129
|
ret = FastRuby::FastRubySexp.new
|
108
130
|
each{|st2|
|
@@ -0,0 +1,262 @@
|
|
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
|
+
require "fastruby/sexp_extension_edges"
|
23
|
+
require "ruby_parser"
|
24
|
+
require "set"
|
25
|
+
|
26
|
+
class Object
|
27
|
+
def to_fastruby_sexp
|
28
|
+
self
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def fs(*args)
|
33
|
+
if String === args.first
|
34
|
+
tree = FastRuby::FastRubySexp.parse(args.first)
|
35
|
+
|
36
|
+
if args.size > 1
|
37
|
+
replacement_hash = {}
|
38
|
+
args[1..-1].each do |arg|
|
39
|
+
replacement_hash.merge!(arg)
|
40
|
+
end
|
41
|
+
|
42
|
+
tree = tree.transform{|subtree|
|
43
|
+
if subtree.node_type == :call
|
44
|
+
next replacement_hash[subtree[2]]
|
45
|
+
elsif subtree.node_type == :lvar
|
46
|
+
next replacement_hash[subtree[1]]
|
47
|
+
else
|
48
|
+
next nil
|
49
|
+
end
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
tree
|
54
|
+
else
|
55
|
+
sexp = FastRuby::FastRubySexp.new
|
56
|
+
args.each &sexp.method(:<<)
|
57
|
+
sexp
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
module FastRuby
|
62
|
+
class Graph
|
63
|
+
attr_reader :edges
|
64
|
+
attr_reader :vertexes
|
65
|
+
|
66
|
+
def initialize(hash = {})
|
67
|
+
@edges = []
|
68
|
+
@vertexes = Set.new
|
69
|
+
@vertex_output = Hash.new
|
70
|
+
|
71
|
+
hash.each do |orig,v|
|
72
|
+
v.each do |dest|
|
73
|
+
add_edge(orig,dest)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def add_edge(orig,dest)
|
79
|
+
@vertexes << orig
|
80
|
+
@vertexes << dest
|
81
|
+
|
82
|
+
@vertex_output[orig.object_id] ||= Set.new
|
83
|
+
@vertex_output[orig.object_id] << dest
|
84
|
+
|
85
|
+
@edges << [orig,dest]
|
86
|
+
end
|
87
|
+
|
88
|
+
def each_vertex_output(vertex,&blk)
|
89
|
+
outputs = @vertex_output[vertex.object_id]
|
90
|
+
if outputs
|
91
|
+
blk ? outputs.each(&blk) : outputs
|
92
|
+
else
|
93
|
+
Set.new
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def each_path_from(vertex, history = [])
|
98
|
+
outputs = each_vertex_output(vertex) - history.select{|h| h[0] == vertex }.map(&:last)
|
99
|
+
outputs.delete(vertex)
|
100
|
+
|
101
|
+
if outputs.count == 0
|
102
|
+
yield [vertex]
|
103
|
+
return
|
104
|
+
end
|
105
|
+
|
106
|
+
outputs.each do |vo|
|
107
|
+
each_path_from(vo,history+[[vertex,vo]]) do |subpath|
|
108
|
+
yield [vertex]+subpath
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class FastRubySexp
|
115
|
+
def self.from_sexp(value)
|
116
|
+
return nil if value == nil
|
117
|
+
return value if value.kind_of? FastRubySexp
|
118
|
+
|
119
|
+
ary = FastRuby::FastRubySexp.new
|
120
|
+
value.each do |x|
|
121
|
+
ary << x.to_fastruby_sexp
|
122
|
+
end
|
123
|
+
ary
|
124
|
+
end
|
125
|
+
|
126
|
+
def transform(&blk)
|
127
|
+
ret = FastRuby::FastRubySexp.from_sexp( blk.call(self) )
|
128
|
+
unless ret
|
129
|
+
ret = FastRuby::FastRubySexp.new
|
130
|
+
each{|st2|
|
131
|
+
if st2.respond_to?(:transform)
|
132
|
+
ret << st2.transform(&blk)
|
133
|
+
else
|
134
|
+
ret << st2
|
135
|
+
end
|
136
|
+
}
|
137
|
+
end
|
138
|
+
|
139
|
+
ret
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.parse(code)
|
143
|
+
from_sexp(RubyParser.new.parse(code))
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_graph
|
147
|
+
graph = Graph.new
|
148
|
+
self.edges.each &graph.method(:add_edge)
|
149
|
+
|
150
|
+
if ENV['FASTRUBY_GRAPH_VERTEX_CHECK'] == '1'
|
151
|
+
output_vertexes = [];
|
152
|
+
|
153
|
+
self.walk_tree do |subtree|
|
154
|
+
if graph.each_vertex_output(subtree).count == 0
|
155
|
+
# vertexes with no output
|
156
|
+
unless [:arglist,:scope].include? subtree.node_type
|
157
|
+
output_vertexes << subtree
|
158
|
+
if output_vertexes.count > 1
|
159
|
+
raise RuntimeError, "invalid output vertexes #{output_vertexes.map &:node_type}"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
graph
|
167
|
+
end
|
168
|
+
|
169
|
+
def edges
|
170
|
+
Edges.new(self)
|
171
|
+
end
|
172
|
+
|
173
|
+
def first_tree
|
174
|
+
if respond_to? "first_tree_#{node_type}"
|
175
|
+
send("first_tree_#{node_type}")
|
176
|
+
else
|
177
|
+
return self[1].first_tree if self.count == 2 and self[1].respond_to? :node_type
|
178
|
+
return self[1].first_tree if [:if,:block,:while,:until,:or,:and,:ensure].include? node_type
|
179
|
+
return self[2].first_tree if [:lasgn,:iasgn,:gasgn,:cdecl].include? node_type
|
180
|
+
|
181
|
+
self
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def first_tree_rescue
|
186
|
+
if self[1].node_type == :resbody
|
187
|
+
return self
|
188
|
+
else
|
189
|
+
return self[1].first_tree
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def first_tree_return
|
194
|
+
self[1] ? self[1].first_tree : self
|
195
|
+
end
|
196
|
+
|
197
|
+
alias first_tree_break first_tree_return
|
198
|
+
alias first_tree_next first_tree_return
|
199
|
+
|
200
|
+
def first_tree_yield
|
201
|
+
if self.size > 1
|
202
|
+
self[-1].first_tree
|
203
|
+
else
|
204
|
+
self
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def first_tree_iter
|
209
|
+
call_tree = self[1]
|
210
|
+
recv = call_tree[1]
|
211
|
+
if recv
|
212
|
+
recv.first_tree
|
213
|
+
else
|
214
|
+
args_tree = call_tree[3]
|
215
|
+
if args_tree.size > 1
|
216
|
+
args_tree[1].first_tree
|
217
|
+
else
|
218
|
+
call_tree
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def first_tree_call
|
224
|
+
recv = self[1]
|
225
|
+
if recv
|
226
|
+
recv.first_tree
|
227
|
+
else
|
228
|
+
args_tree = self[3]
|
229
|
+
if args_tree.size > 1
|
230
|
+
args_tree[1].first_tree
|
231
|
+
else
|
232
|
+
self
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def find_break(&blk)
|
238
|
+
subarray = if node_type == :while
|
239
|
+
[]
|
240
|
+
elsif node_type == :iter
|
241
|
+
self[1..-2]
|
242
|
+
elsif node_type == :break
|
243
|
+
blk.call(self)
|
244
|
+
return; nil
|
245
|
+
else
|
246
|
+
self[1..-1]
|
247
|
+
end
|
248
|
+
|
249
|
+
subarray.each do |subtree|
|
250
|
+
if subtree.respond_to? :find_break
|
251
|
+
subtree.find_break(&blk)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
class Sexp
|
259
|
+
def to_fastruby_sexp
|
260
|
+
FastRuby::FastRubySexp.from_sexp(self)
|
261
|
+
end
|
262
|
+
end
|