fastruby 0.0.19 → 0.0.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/CHANGELOG +8 -0
  2. data/{README → README.rdoc} +6 -1
  3. data/Rakefile +7 -7
  4. data/benchmarks/benchmark.rb~ +14 -2
  5. data/ext/fastruby_base/fastruby_base.inl +8 -4
  6. data/lib/fastruby/builder/inference_updater.rb +76 -0
  7. data/lib/fastruby/builder/inference_updater.rb~ +76 -0
  8. data/lib/fastruby/builder/inferencer.rb +38 -0
  9. data/lib/fastruby/{inliner → builder}/inliner.rb +16 -27
  10. data/lib/fastruby/builder/inliner.rb~ +60 -0
  11. data/lib/fastruby/builder/locals_inference.rb +53 -0
  12. data/lib/fastruby/builder/lvar_type.rb +43 -0
  13. data/lib/fastruby/builder/lvar_type.rb~ +44 -0
  14. data/lib/fastruby/builder/pipeline.rb +43 -0
  15. data/lib/fastruby/builder/pipeline.rb~ +43 -0
  16. data/lib/fastruby/{reductor → builder}/reductor.rb +6 -3
  17. data/lib/fastruby/builder/reductor.rb~ +42 -0
  18. data/lib/fastruby/builder.rb +73 -25
  19. data/lib/fastruby/builder.rb~ +311 -0
  20. data/lib/fastruby/corelib/fixnum.rb +75 -0
  21. data/lib/fastruby/corelib/fixnum.rb~ +146 -0
  22. data/lib/fastruby/corelib/integer.rb +96 -0
  23. data/lib/fastruby/corelib/integer.rb~ +96 -0
  24. data/lib/fastruby/corelib.rb +23 -0
  25. data/lib/fastruby/corelib.rb~ +23 -0
  26. data/lib/fastruby/getlocals.rb +3 -1
  27. data/lib/fastruby/logging.rb +2 -2
  28. data/lib/fastruby/modules/inferencer/infer.rb +31 -0
  29. data/lib/fastruby/modules/inferencer/literal.rb +42 -0
  30. data/lib/fastruby/modules/inliner/call.rb +327 -0
  31. data/lib/fastruby/{inliner/modules/call.rb → modules/inliner/call.rb~} +14 -24
  32. data/lib/fastruby/modules/inliner/defn.rb +41 -0
  33. data/lib/fastruby/modules/inliner/defn.rb~ +29 -0
  34. data/lib/fastruby/modules/inliner/recursive.rb +40 -0
  35. data/lib/fastruby/{inliner/modules/recursive.rb → modules/inliner/recursive.rb~} +1 -1
  36. data/lib/fastruby/modules/lvar_type/call.rb +36 -0
  37. data/lib/fastruby/modules/lvar_type/call.rb~ +36 -0
  38. data/lib/fastruby/modules/lvar_type/defn.rb +42 -0
  39. data/lib/fastruby/modules/lvar_type/defn.rb~ +42 -0
  40. data/lib/fastruby/modules/lvar_type/lasgn.rb +41 -0
  41. data/lib/fastruby/modules/lvar_type/lasgn.rb~ +42 -0
  42. data/lib/fastruby/modules/lvar_type/recursive.rb +33 -0
  43. data/lib/fastruby/modules/lvar_type/recursive.rb~ +33 -0
  44. data/lib/fastruby/{reductor/modules → modules/reductor}/case.rb +0 -0
  45. data/lib/fastruby/modules/reductor/fastruby_flag.rb +33 -0
  46. data/lib/fastruby/{reductor/modules → modules/reductor}/for.rb +0 -0
  47. data/lib/fastruby/{reductor/modules → modules/reductor}/nontree.rb +0 -0
  48. data/lib/fastruby/modules/reductor/nontree.rb~ +32 -0
  49. data/lib/fastruby/{reductor/modules → modules/reductor}/recursive.rb +1 -1
  50. data/lib/fastruby/modules/reductor/recursive.rb~ +31 -0
  51. data/lib/fastruby/{translator/modules → modules/translator}/block.rb +0 -0
  52. data/lib/fastruby/modules/translator/call.rb +344 -0
  53. data/lib/fastruby/{translator/modules/call.rb → modules/translator/call.rb~} +24 -3
  54. data/lib/fastruby/{translator/modules → modules/translator}/defn.rb +10 -9
  55. data/lib/fastruby/modules/translator/defn.rb~ +267 -0
  56. data/lib/fastruby/{translator/modules → modules/translator}/directive.rb +3 -1
  57. data/lib/fastruby/modules/translator/directive.rb~ +44 -0
  58. data/lib/fastruby/{translator/modules → modules/translator}/exceptions.rb +3 -1
  59. data/lib/fastruby/modules/translator/exceptions.rb~ +120 -0
  60. data/lib/fastruby/{translator/modules → modules/translator}/flow.rb +0 -0
  61. data/lib/fastruby/modules/translator/iter.rb +745 -0
  62. data/lib/fastruby/{translator/modules/iter.rb → modules/translator/iter.rb~} +103 -48
  63. data/lib/fastruby/modules/translator/literal.rb +150 -0
  64. data/lib/fastruby/{translator/modules/literal.rb → modules/translator/literal.rb~} +3 -3
  65. data/lib/fastruby/{translator/modules → modules/translator}/logical.rb +0 -0
  66. data/lib/fastruby/{translator/modules → modules/translator}/method_group.rb +0 -0
  67. data/lib/fastruby/{translator/modules → modules/translator}/nonlocal.rb +18 -6
  68. data/lib/fastruby/modules/translator/nonlocal.rb~ +298 -0
  69. data/lib/fastruby/modules/translator/static.rb +290 -0
  70. data/lib/fastruby/{translator/modules/static.rb → modules/translator/static.rb~} +66 -17
  71. data/lib/fastruby/modules/translator/variable.rb +280 -0
  72. data/lib/fastruby/{translator/modules/variable.rb → modules/translator/variable.rb~} +14 -44
  73. data/lib/fastruby/modules.rb +30 -0
  74. data/lib/fastruby/object.rb +42 -6
  75. data/lib/fastruby/object.rb~ +159 -0
  76. data/lib/fastruby/set_tree.rb +7 -11
  77. data/lib/fastruby/set_tree.rb~ +71 -0
  78. data/lib/fastruby/sexp_extension.rb +29 -7
  79. data/lib/fastruby/sexp_extension.rb~ +262 -0
  80. data/lib/fastruby/translator/scope_mode_helper.rb~ +138 -0
  81. data/lib/fastruby/translator/translator.rb +87 -92
  82. data/lib/fastruby/translator/translator.rb~ +1600 -0
  83. data/lib/fastruby/translator/translator_modules.rb +3 -1
  84. data/lib/fastruby/translator/translator_modules.rb~ +53 -0
  85. data/lib/fastruby.rb +3 -1
  86. data/lib/fastruby.rb~ +3 -1
  87. data/lib/fastruby_only/base.rb +1 -0
  88. data/spec/corelib/numeric/fixnum_spec.rb +110 -0
  89. data/spec/corelib/numeric/fixnum_spec.rb~ +104 -0
  90. data/spec/corelib/numeric/integer_spec.rb +173 -0
  91. data/spec/corelib/numeric/integer_spec.rb~ +173 -0
  92. data/spec/fastruby_only/base_spec.rb +74 -0
  93. data/spec/graph/base_spec.rb +2 -1
  94. data/spec/graph/base_spec.rb~ +35 -0
  95. data/spec/graph/path_spec.rb +2 -2
  96. data/spec/graph/path_spec.rb~ +48 -0
  97. data/spec/graph/vertex_spec.rb +2 -1
  98. data/spec/graph/vertex_spec.rb~ +58 -0
  99. data/spec/reductor/base_spec.rb +1 -1
  100. data/spec/ruby/block/lambda_spec.rb~ +163 -0
  101. data/spec/ruby/block/proc_as_block_spec.rb~ +69 -1
  102. data/spec/ruby/block_spec.rb~ +2 -494
  103. data/spec/ruby/call/base_call_spec.rb +1 -1
  104. data/spec/ruby/call/base_call_spec.rb~ +2 -60
  105. data/spec/ruby/defn/replacement_spec.rb +26 -14
  106. data/spec/ruby/defn/replacement_spec.rb~ +13 -3
  107. data/spec/ruby/exception/internal_ex_spec.rb~ +86 -0
  108. data/spec/ruby/integrity_spec.rb~ +35 -1
  109. data/spec/ruby/variable_spec.rb~ +31 -0
  110. data/spec/scope_mode/flow_spec.rb +1 -1
  111. data/spec/scope_mode/flow_spec.rb~ +109 -0
  112. data/spec/sugar/base_spec.rb +29 -0
  113. data/spec/sugar/base_spec.rb~ +16 -0
  114. metadata +100 -43
  115. data/spec/fastruby/inliner/modules/call_spec.rb +0 -0
  116. data/spec/fastruby/translator/modules/nonlocal_spec.rb +0 -0
  117. data/spec/fastruby/translator/translator_spec.rb +0 -0
  118. data/spec/ruby/block/arguments_spec.rb~ +0 -214
  119. data/spec/ruby/block/break_spec.rb~ +0 -236
  120. data/spec/ruby/block/next_spec.rb~ +0 -85
  121. 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
+
@@ -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, snippet_hash, options = {})
48
- locals = Set.new
49
- locals << :self
50
-
51
- tree = Reductor.new.reduce tree
52
-
53
- FastRuby::GetLocalsProcessor.get_locals(tree).each do |local|
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
- sexp = FastRuby::FastRubySexp.new
34
- args.each &sexp.method(:<<)
35
- sexp
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