ParseTree 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: