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.
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