fastruby 0.0.19 → 0.0.20
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 +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
|