ParseTree 2.0.0 → 2.0.1

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.
@@ -1,3 +1,25 @@
1
+ === 2.0.1 / 2007-08-21
2
+
3
+ * 1 major enhancement:
4
+
5
+ * Rewrote parse_tree_show to use parse_tree_for_string.
6
+ * parse_tree_show adds -n=node filtering -u unifying, and -s structure-only.
7
+ * parse_tree_show no longer needs -f
8
+
9
+ * 4 minor enhancements:
10
+
11
+ * Added context stack to SexpProcessor! YAY!!!
12
+ * Enforce type to be symbol in SexpProcessor... just makes life easier.
13
+ * Processing style change mode to UnifiedRuby. Prefer no rescues.
14
+ * Sexp#structure is no longer destructive.
15
+
16
+ * 4 bug fixes:
17
+
18
+ * Added 1.8.4 compatibility fix.
19
+ * Added args lifting in :defs in UnifiedRuby.
20
+ * Fixed unifying argscat, splat, and a couple other oddities.
21
+ * Added process_call to UnifiedRuby *sigh* I'm a tard.
22
+
1
23
  === 2.0.0 / 2007-08-01
2
24
 
3
25
  * 2 major enhancements:
@@ -3,47 +3,41 @@
3
3
  require 'pp'
4
4
  begin require 'rubygems' rescue LoadError end
5
5
  require 'parse_tree'
6
+ require 'sexp'
6
7
 
7
- def discover_new_classes_from
8
- old_classes = []
9
- ObjectSpace.each_object(Module) do |klass|
10
- old_classes << klass
11
- end
8
+ $u ||= false
9
+ $n ||= false
10
+ $s ||= false
11
+ $n = $n.intern if $n
12
12
 
13
- yield
13
+ ARGV.push "-" if ARGV.empty?
14
14
 
15
- new_classes = []
16
- ObjectSpace.each_object(Module) do |klass|
17
- new_classes << klass
18
- end
15
+ if $u then
16
+ require 'sexp_processor'
17
+ require 'unified_ruby'
19
18
 
20
- new_classes -= old_classes
21
- new_classes = [ eval($c) ] if defined? $c
22
- new_classes
23
- end
24
-
25
- $f = false unless defined? $f
26
-
27
- new_classes = discover_new_classes_from do
28
- ARGV.unshift "-" if ARGV.empty?
29
- ARGV.each do |name|
30
- if name == "-" then
31
- code = $stdin.read
32
- code = "class Example; def example; #{code}; end; end" if $f
33
- eval code unless code.nil?
34
- else
35
- require name
36
- end
19
+ class Unifier < SexpProcessor
20
+ include UnifiedRuby
37
21
  end
38
22
  end
39
23
 
40
- result = ParseTree.new.parse_tree(*new_classes)
24
+ parse_tree = ParseTree.new
25
+ unifier = Unifier.new if $u
41
26
 
42
- result = result[0][3][2][1][2..-1] if $f
27
+ ARGV.each do |file|
28
+ ruby = file == "-" ? $stdin.read : File.read(file)
43
29
 
44
- unless defined? $q then
45
- pp result
46
- else
47
- p result
48
- end
30
+ sexp = Sexp.from_array parse_tree.parse_tree_for_string(ruby, file).first
31
+ sexp = unifier.process(sexp) if $u
32
+ sexp = sexp.structure if $s
49
33
 
34
+ if $n then
35
+ sexp.each_of_type $n do |node|
36
+ p node
37
+ end
38
+ elsif defined? $q then
39
+ p sexp
40
+ else
41
+ pp sexp
42
+ end
43
+ end
@@ -41,7 +41,7 @@ end
41
41
 
42
42
  class ParseTree
43
43
 
44
- VERSION = '2.0.0'
44
+ VERSION = '2.0.1'
45
45
 
46
46
  ##
47
47
  # Front end translation method.
@@ -811,6 +811,9 @@ again_no_block:
811
811
  // nothing to do in this case, handled above
812
812
  } else if (arg_count == -2) {
813
813
  // nothing to do in this case, no name == no use
814
+ #if RUBY_VERSION_CODE < 185
815
+ rb_ary_push(current, rb_str_intern(rb_str_new2("*")));
816
+ #endif
814
817
  } else {
815
818
  rb_raise(rb_eArgError,
816
819
  "not a clue what this arg value is: %ld", arg_count);
@@ -199,7 +199,7 @@ class Sexp < Array # ZenTest FULL
199
199
  if Array === self.first then
200
200
  result = self.first.structure
201
201
  else
202
- result << self.shift
202
+ result << self.first
203
203
  self.grep(Array).each do |subexp|
204
204
  result << subexp.structure
205
205
  end
@@ -74,17 +74,6 @@ class SexpTypeError < SexpProcessorError; end
74
74
 
75
75
  class SexpProcessor
76
76
 
77
- ##
78
- # A default method to call if a process_<type> method is not found
79
- # for the Sexp type.
80
-
81
- attr_accessor :default_method
82
-
83
- ##
84
- # Emit a warning when the method in #default_method is called.
85
-
86
- attr_accessor :warn_on_default
87
-
88
77
  ##
89
78
  # Automatically shifts off the Sexp type before handing the
90
79
  # Sexp to process_<type>
@@ -92,16 +81,9 @@ class SexpProcessor
92
81
  attr_accessor :auto_shift_type
93
82
 
94
83
  ##
95
- # An array that specifies node types that are unsupported by this
96
- # processor. SexpProcessor will raise UnsupportedNodeError if you try
97
- # to process one of those node types.
84
+ # Return a stack of contexts. Most recent node is first.
98
85
 
99
- attr_accessor :unsupported
100
-
101
- ##
102
- # Raise an exception if no process_<type> method is found for a Sexp.
103
-
104
- attr_accessor :strict
86
+ attr_reader :context
105
87
 
106
88
  ##
107
89
  # A Hash of Sexp types and Regexp.
@@ -111,6 +93,12 @@ class SexpProcessor
111
93
 
112
94
  attr_accessor :debug
113
95
 
96
+ ##
97
+ # A default method to call if a process_<type> method is not found
98
+ # for the Sexp type.
99
+
100
+ attr_accessor :default_method
101
+
114
102
  ##
115
103
  # Expected result class
116
104
 
@@ -121,6 +109,23 @@ class SexpProcessor
121
109
 
122
110
  attr_accessor :require_empty
123
111
 
112
+ ##
113
+ # Raise an exception if no process_<type> method is found for a Sexp.
114
+
115
+ attr_accessor :strict
116
+
117
+ ##
118
+ # An array that specifies node types that are unsupported by this
119
+ # processor. SexpProcessor will raise UnsupportedNodeError if you try
120
+ # to process one of those node types.
121
+
122
+ attr_accessor :unsupported
123
+
124
+ ##
125
+ # Emit a warning when the method in #default_method is called.
126
+
127
+ attr_accessor :warn_on_default
128
+
124
129
  ##
125
130
  # Creates a new SexpProcessor. Use super to invoke this
126
131
  # initializer from SexpProcessor subclasses, then use the
@@ -144,6 +149,7 @@ class SexpProcessor
144
149
  # different processors.
145
150
  @processors = {}
146
151
  @rewriters = {}
152
+ @context = []
147
153
 
148
154
  public_methods.each do |name|
149
155
  case name
@@ -198,6 +204,10 @@ class SexpProcessor
198
204
  result = self.expected.new
199
205
 
200
206
  type = exp.first
207
+ raise "type should be a Symbol, not: #{exp.first.inspect}" unless
208
+ Symbol === type
209
+
210
+ @context.unshift type
201
211
 
202
212
  if @debug.has_key? type then
203
213
  str = exp.inspect
@@ -268,6 +278,7 @@ class SexpProcessor
268
278
 
269
279
  @process_level -= 1
270
280
 
281
+ @context.shift
271
282
  result
272
283
  end
273
284
 
@@ -1,5 +1,13 @@
1
1
 
2
+ $TESTING ||= false
3
+
2
4
  module UnifiedRuby
5
+ def rewrite_argscat(exp)
6
+ raise "unknown type #{exp.inspect}" unless exp[1][0] == :array
7
+ exp[1][0] = :arglist
8
+ exp
9
+ end
10
+
3
11
  def rewrite_bmethod(exp)
4
12
  exp[0] = :scope
5
13
 
@@ -25,6 +33,28 @@ module UnifiedRuby
25
33
  exp
26
34
  end
27
35
 
36
+ def rewrite_call(exp)
37
+ args = exp.last
38
+ case args
39
+ when nil
40
+ exp.pop
41
+ when Array
42
+ case args.first
43
+ when :array, :arglist then
44
+ args[0] = :arglist
45
+ when :argscat, :splat then
46
+ # do nothing
47
+ else
48
+ raise "unknown type in call #{args.first.inspect}"
49
+ end
50
+ return exp
51
+ end
52
+
53
+ exp << s(:arglist)
54
+
55
+ exp
56
+ end
57
+
28
58
  ##
29
59
  # :defn is one of the most complex of all the ASTs in ruby. We do
30
60
  # one of 3 different translations:
@@ -74,6 +104,14 @@ module UnifiedRuby
74
104
  exp
75
105
  end
76
106
 
107
+ def rewrite_defs(exp)
108
+ # move args up
109
+ args = exp.scope.block.args(true) rescue nil
110
+ exp.insert 3, args if args
111
+
112
+ exp
113
+ end
114
+
77
115
  def rewrite_dmethod(exp)
78
116
  exp.shift # type
79
117
  exp.shift # dmethod name
@@ -89,16 +127,7 @@ module UnifiedRuby
89
127
  exp.insert 1, nil
90
128
  exp.push nil if exp.size <= 3
91
129
 
92
- args = exp[-1]
93
- if Array === args and args.first == :array then
94
- args[0] = :arglist
95
- elsif args.nil? then
96
- exp[-1] = s(:arglist)
97
- else
98
- exp[-1] = s(:arglist, args) unless args.nil?
99
- end
100
-
101
- exp
130
+ rewrite_call(exp)
102
131
  end
103
132
 
104
133
  def rewrite_resbody(exp) # TODO: clean up and move to unified
@@ -108,8 +137,8 @@ module UnifiedRuby
108
137
  while exp and exp.first == :resbody do
109
138
  code << exp.shift
110
139
  list = exp.shift || s(:array)
111
- body = exp.shift rescue nil
112
- exp = exp.shift rescue nil
140
+ body = exp.empty? ? nil : exp.shift
141
+ exp = exp.empty? ? nil : exp.shift
113
142
 
114
143
  # code may be nil, :lasgn, or :block
115
144
  case body.first
@@ -133,9 +162,15 @@ module UnifiedRuby
133
162
  end
134
163
  end
135
164
 
136
- raise unless result.first == :resbody
137
- raise unless Sexp === result[1] and result[1].first == :array
138
- raise unless result[2].nil? or (Sexp === result[2] and ! result[2].empty?)
165
+ if $DEBUG or $TESTING then
166
+ structure = result.structure
167
+ raise "result structure wrong: #{structure[0..1].inspect}" unless
168
+ structure.flatten[0] == :resbody
169
+ raise "result structure wrong: #{structure[0..1].inspect}" unless
170
+ s(:array, :splat, :argscat).include? structure.flatten[1]
171
+ raise "result body wrong: #{structure[2].inspect}" unless
172
+ structure[2].nil? or not structure[2].empty?
173
+ end
139
174
 
140
175
  result
141
176
  end
@@ -16,6 +16,7 @@ class FakeProcessor1 < SexpProcessor # ZenTest SKIP
16
16
 
17
17
  def default_processor(exp)
18
18
  result = []
19
+ result << exp.shift
19
20
  until exp.empty? do
20
21
  result << exp.shift.to_s + " woot"
21
22
  end
@@ -36,18 +37,18 @@ class TestCompositeSexpProcessor < Test::Unit::TestCase
36
37
  end
37
38
 
38
39
  def test_process_fake1
39
- data = [1, 2, 3]
40
+ data = [:x, 1, 2, 3]
40
41
  @p << FakeProcessor1.new
41
42
  result = @p.process(data.dup)
42
- assert_equal(data.map {|x| "#{x} woot"}, result)
43
+ assert_equal [:x, "1 woot", "2 woot", "3 woot"], result
43
44
  end
44
45
 
45
46
  def test_process_fake1_twice
46
- data = [1, 2, 3]
47
+ data = [:x, 1, 2, 3]
47
48
  @p << FakeProcessor1.new
48
49
  @p << FakeProcessor1.new
49
50
  result = @p.process(data.dup)
50
- assert_equal(data.map {|x| "#{x} woot woot"}, result)
51
+ assert_equal [:x, "1 woot woot", "2 woot woot", "3 woot woot"], result
51
52
  end
52
53
 
53
54
  def test_processors
@@ -263,9 +263,11 @@ class TestSexp < SexpTestCase # ZenTest FULL
263
263
 
264
264
  def test_structure
265
265
  @sexp = s(:a, 1, 2, s(:b, 3, 4), 5, 6)
266
+ backup = @sexp.deep_clone
266
267
  expected = s(:a, s(:b))
267
268
 
268
269
  assert_equal(expected, @sexp.structure)
270
+ assert_equal(backup, @sexp)
269
271
  end
270
272
 
271
273
  def test_sub
@@ -1,4 +1,4 @@
1
- #!/usr/local/bin/ruby
1
+ #!/usr/local/bin/ruby -w
2
2
 
3
3
  $TESTING = true
4
4
 
@@ -31,6 +31,38 @@ class TestUnifiedRuby < Test::Unit::TestCase
31
31
  assert_equal @expect, @sp.process(@insert)
32
32
  end
33
33
 
34
+ def test_argscat
35
+ @insert = s(:argscat,
36
+ s(:array, s(:lvar, :container), s(:lvar, :point)),
37
+ s(:lvar, :args))
38
+ @expect = s(:argscat,
39
+ s(:arglist, s(:lvar, :container), s(:lvar, :point)),
40
+ s(:lvar, :args))
41
+
42
+ doit
43
+ end
44
+
45
+ def test_call_args
46
+ @insert = s(:call, s(:lit, 42), :y, s(:array, s(:lit, 24)))
47
+ @expect = s(:call, s(:lit, 42), :y, s(:arglist, s(:lit, 24)))
48
+
49
+ doit
50
+ end
51
+
52
+ def test_call_array_args
53
+ @insert = s(:call, s(:lit, 42), :y, s(:array))
54
+ @expect = s(:call, s(:lit, 42), :y, s(:arglist))
55
+
56
+ doit
57
+ end
58
+
59
+ def test_call_no_args
60
+ @insert = s(:call, s(:lit, 42), :y)
61
+ @expect = s(:call, s(:lit, 42), :y, s(:arglist))
62
+
63
+ doit
64
+ end
65
+
34
66
  def test_rewrite_bmethod
35
67
  @insert = s(:bmethod,
36
68
  s(:dasgn_curr, :x),
@@ -38,7 +70,7 @@ class TestUnifiedRuby < Test::Unit::TestCase
38
70
  @expect = s(:scope,
39
71
  s(:block,
40
72
  s(:args, :x),
41
- s(:call, s(:lvar, :x), :+, s(:array, s(:lit, 1)))))
73
+ s(:call, s(:lvar, :x), :+, s(:arglist, s(:lit, 1)))))
42
74
 
43
75
  doit
44
76
  end
@@ -51,7 +83,7 @@ class TestUnifiedRuby < Test::Unit::TestCase
51
83
  s(:block,
52
84
  s(:args),
53
85
  s(:call, s(:call, nil, :x, s(:arglist)),
54
- :+, s(:array, s(:lit, 1)))))
86
+ :+, s(:arglist, s(:lit, 1)))))
55
87
 
56
88
  doit
57
89
  end
@@ -98,7 +130,36 @@ class TestUnifiedRuby < Test::Unit::TestCase
98
130
  s(:block_pass,
99
131
  s(:lvar, :block),
100
132
  s(:call, nil, :other,
101
- s(:arglist, s(:splat, s(:lvar, :args))))))))
133
+ s(:splat, s(:lvar, :args)))))))
134
+
135
+ doit
136
+ end
137
+
138
+ def test_rewrite_defn_bmethod_alias
139
+ @insert = s(:defn, :group,
140
+ s(:fbody,
141
+ s(:bmethod,
142
+ s(:masgn, s(:dasgn_curr, :params)),
143
+ s(:block,
144
+ s(:lit, 42)))))
145
+ @expect = s(:defn, :group,
146
+ s(:args, :"*params"),
147
+ s(:scope,
148
+ s(:block, s(:lit, 42))))
149
+
150
+ doit
151
+ end
152
+
153
+ def test_rewrite_defn_ivar
154
+ @insert = s(:defn, :reader, s(:ivar, :@reader))
155
+ @expect = s(:defn, :reader, s(:args), s(:ivar, :@reader))
156
+
157
+ doit
158
+ end
159
+
160
+ def test_rewrite_defs
161
+ @insert = s(:defs, s(:self), :meth, s(:scope, s(:block, s(:args), s(:true))))
162
+ @expect = s(:defs, s(:self), :meth, s(:args), s(:scope, s(:block, s(:true))))
102
163
 
103
164
  doit
104
165
  end
@@ -127,23 +188,28 @@ class TestUnifiedRuby < Test::Unit::TestCase
127
188
  @expect = s(:scope,
128
189
  s(:block,
129
190
  s(:args, :x),
130
- s(:call, s(:lvar, :x), :+, s(:array, s(:lit, 1)))))
191
+ s(:call, s(:lvar, :x), :+, s(:arglist, s(:lit, 1)))))
131
192
 
132
193
  doit
133
194
  end
134
195
 
135
- def test_rewrite_defn_bmethod_alias
136
- @insert = s(:defn, :group,
137
- s(:fbody,
138
- s(:bmethod,
139
- s(:masgn, s(:dasgn_curr, :params)),
140
- s(:block,
141
- s(:lit, 42)))))
142
- @expect = s(:defn, :group,
143
- s(:args, :"*params"),
144
- s(:scope,
145
- s(:block, s(:lit, 42))))
196
+ def test_rewrite_fcall
197
+ @insert = s(:fcall, :puts, s(:array, s(:lit, :blah)))
198
+ @expect = s(:call, nil, :puts, s(:arglist, s(:lit, :blah)))
199
+
200
+ doit
201
+ end
202
+
203
+ def test_rewrite_fcall_loop
204
+ @insert = s(:iter, s(:fcall, :loop), nil)
205
+ @expect = s(:iter, s(:call, nil, :loop, s(:arglist)), nil)
206
+
207
+ doit
208
+ end
146
209
 
210
+ def test_rewrite_fcall_splat
211
+ @insert = s(:fcall, :method, s(:splat, s(:vcall, :a)))
212
+ @expect = s(:call, nil, :method, s(:splat, s(:call, nil, :a, s(:arglist))))
147
213
  doit
148
214
  end
149
215
 
@@ -198,32 +264,10 @@ class TestUnifiedRuby < Test::Unit::TestCase
198
264
  doit
199
265
  end
200
266
 
201
- def test_rewrite_defn_ivar
202
- @insert = s(:defn, :reader, s(:ivar, :@reader))
203
- @expect = s(:defn, :reader, s(:args), s(:ivar, :@reader))
204
-
205
- doit
206
- end
207
-
208
267
  def test_rewrite_vcall
209
268
  @insert = s(:vcall, :puts)
210
269
  @expect = s(:call, nil, :puts, s(:arglist))
211
270
 
212
271
  doit
213
272
  end
214
-
215
- def test_rewrite_fcall
216
- @insert = s(:fcall, :puts, s(:array, s(:lit, :blah)))
217
- @expect = s(:call, nil, :puts, s(:arglist, s(:lit, :blah)))
218
-
219
- doit
220
- end
221
-
222
- def test_rewrite_fcall_loop
223
- @insert = s(:iter, s(:fcall, :loop), nil)
224
- @expect = s(:iter, s(:call, nil, :loop, s(:arglist)), nil)
225
-
226
- doit
227
- end
228
-
229
273
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: ParseTree
5
5
  version: !ruby/object:Gem::Version
6
- version: 2.0.0
7
- date: 2007-08-01 00:00:00 -07:00
6
+ version: 2.0.1
7
+ date: 2007-08-21 00:00:00 -07:00
8
8
  summary: ParseTree is a C extension (using RubyInline) that extracts the parse tree for an entire class or a specific method and returns it as a s-expression (aka sexp) using ruby's arrays, strings, symbols, and integers.
9
9
  require_paths:
10
10
  - lib
@@ -89,5 +89,5 @@ dependencies:
89
89
  requirements:
90
90
  - - ">="
91
91
  - !ruby/object:Gem::Version
92
- version: 1.2.2
92
+ version: 1.3.0
93
93
  version: