ParseTree 1.6.4 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,15 +1,25 @@
1
+ *** 1.7.0 / 2007-02-13
2
+
3
+ + 2 major enhancements:
4
+ + rewrite extracted and intended to be run before (or in front of) process.
5
+ + rewrite is now recursive as well, so children rewritings should be done independently of their parents. This should make complex rewriting layers much cleaner and allow me to eventually collect and publish a single "standard" rewriting layer.
6
+ + 1 minor enhancement:
7
+ + Iters are now {} if short and one line. YAY!
8
+ + 1 bug fix:
9
+ + Added test cases brought out by ruby2ruby/heckle.
10
+
1
11
  *** 1.6.4 / 2007-01-15
2
12
 
3
13
  + 1 minor enhancement:
4
- Switched short if/unless to 1 line expressions.
14
+ + Switched short if/unless to 1 line expressions.
5
15
  + 2 bug fixes:
6
- Fixed the nested case/when bug. YAY!
7
- Added dasgn_curr and defn_rescue test cases.
16
+ + Fixed the nested case/when bug. YAY!
17
+ + Added dasgn_curr and defn_rescue test cases.
8
18
 
9
19
  *** 1.6.3 / 2006-12-20
10
20
 
11
21
  + 1 bug fix:
12
- + ParseTree::translate was trying to translate inherited class methods.
22
+ + ParseTree::translate was trying to translate inherited class methods.
13
23
 
14
24
  *** 1.6.2 / 2006-12-19
15
25
 
@@ -25,7 +25,7 @@ require 'inline'
25
25
 
26
26
  class ParseTree
27
27
 
28
- VERSION = '1.6.4'
28
+ VERSION = '1.7.0'
29
29
 
30
30
  ##
31
31
  # Front end translation method.
@@ -590,10 +590,8 @@ again_no_block:
590
590
 
591
591
  case NODE_MASGN:
592
592
  add_to_parse_tree(current, node->nd_head, newlines, locals);
593
- if (node->nd_args) {
594
- if (node->nd_args != (NODE *)-1) {
595
- add_to_parse_tree(current, node->nd_args, newlines, locals);
596
- }
593
+ if (node->nd_args && node->nd_args != (NODE *)-1) {
594
+ add_to_parse_tree(current, node->nd_args, newlines, locals);
597
595
  }
598
596
  add_to_parse_tree(current, node->nd_value, newlines, locals);
599
597
  break;
@@ -65,7 +65,7 @@ class SexpTypeError < SexpProcessorError; end
65
65
  # super
66
66
  # self.strict = false
67
67
  # end
68
- #
68
+ #
69
69
  # def process_lit(exp)
70
70
  # val = exp.shift
71
71
  # return val
@@ -73,7 +73,7 @@ class SexpTypeError < SexpProcessorError; end
73
73
  # end
74
74
 
75
75
  class SexpProcessor
76
-
76
+
77
77
  ##
78
78
  # A default method to call if a process_<type> method is not found
79
79
  # for the Sexp type.
@@ -138,6 +138,7 @@ class SexpProcessor
138
138
  @expected = Sexp
139
139
  @require_empty = true
140
140
  @exceptions = {}
141
+ @process_level = 0
141
142
 
142
143
  # we do this on an instance basis so we can subclass it for
143
144
  # different processors.
@@ -154,6 +155,36 @@ class SexpProcessor
154
155
  end
155
156
  end
156
157
 
158
+ def assert_empty(meth, exp, exp_orig)
159
+ unless exp.empty? then
160
+ msg = "exp not empty after #{self.class}.#{meth} on #{exp.inspect}"
161
+ msg += " from #{exp_orig.inspect}" if $DEBUG
162
+ raise NotEmptyError, msg
163
+ end
164
+ end
165
+
166
+ def rewrite(exp)
167
+ meth = @rewriters[exp.first]
168
+ if meth then
169
+ r = self.send(meth, exp)
170
+ self.assert_empty(meth, exp, nil) if @require_empty
171
+ r
172
+ else
173
+ result = exp.class.new
174
+ until exp.empty? do
175
+ sub_exp = exp.shift
176
+ sub_result = nil
177
+
178
+ if Array === sub_exp then
179
+ result << rewrite(sub_exp)
180
+ else
181
+ result << sub_exp
182
+ end
183
+ end
184
+ result
185
+ end
186
+ end
187
+
157
188
  ##
158
189
  # Default Sexp processor. Invokes process_<type> methods matching
159
190
  # the Sexp type given. Performs additional checks as specified by
@@ -162,6 +193,8 @@ class SexpProcessor
162
193
  def process(exp)
163
194
  return nil if exp.nil?
164
195
 
196
+ @process_level += 1
197
+
165
198
  unless @unsupported_checked then
166
199
  m = public_methods.grep(/^process_/) { |o| o.sub(/^process_/, '').intern }
167
200
  supported = m - (m - @unsupported)
@@ -180,28 +213,13 @@ class SexpProcessor
180
213
  puts "// DEBUG: #{str}" if str =~ @debug[type]
181
214
  end
182
215
 
216
+ exp_orig = nil
183
217
  exp_orig = exp.deep_clone if $DEBUG or
184
218
  @debug.has_key? type or @exceptions.has_key?(type)
185
219
 
186
220
  raise UnsupportedNodeError, "'#{type}' is not a supported node type" if @unsupported.include? type
187
221
 
188
- # do a pass through the rewriter first, if any, reassign back to exp
189
- # TODO: maybe the whole rewriting thing needs to be nuked
190
- meth = @rewriters[type]
191
- if meth then
192
- new_exp = error_handler(type, exp_orig) do
193
- self.send(meth, exp)
194
- end
195
- # REFACTOR: duplicated from below
196
- if @require_empty and not exp.empty? then
197
- msg = "exp not empty after #{self.class}.#{meth} on #{exp.inspect}"
198
- if $DEBUG then
199
- msg += " from #{exp_orig.inspect}"
200
- end
201
- raise NotEmptyError, msg
202
- end
203
- exp = new_exp
204
- end
222
+ exp = self.rewrite(exp) if @process_level == 1
205
223
 
206
224
  # now do a pass with the real processor (or generic)
207
225
  meth = @processors[type] || @default_method
@@ -219,11 +237,7 @@ class SexpProcessor
219
237
 
220
238
  raise SexpTypeError, "Result must be a #{@expected}, was #{result.class}:#{result.inspect}" unless @expected === result
221
239
 
222
- if @require_empty and not exp.empty? then
223
- msg = "exp not empty after #{self.class}.#{meth} on #{exp.inspect}"
224
- msg += " from #{exp_orig.inspect}" if $DEBUG
225
- raise NotEmptyError, msg
226
- end
240
+ self.assert_empty(meth, exp, exp_orig) if @require_empty
227
241
  else
228
242
  unless @strict then
229
243
  until exp.empty? do
@@ -255,6 +269,9 @@ class SexpProcessor
255
269
  raise UnknownNodeError, msg
256
270
  end
257
271
  end
272
+
273
+ @process_level -= 1
274
+
258
275
  result
259
276
  end
260
277
 
@@ -129,13 +129,36 @@ class ParseTreeTestCase < Test::Unit::TestCase
129
129
  "ParseTree" => [:block_pass, [:vcall, :b], [:fcall, :a]],
130
130
  },
131
131
 
132
+ "block_pass_omgwtf" => {
133
+ "Ruby" => "define_attr_method(:x, :sequence_name, &Proc.new { |*args| nil })",
134
+ "ParseTree" => [:block_pass,
135
+ [:iter,
136
+ [:call, [:const, :Proc], :new],
137
+ [:masgn, [:dasgn_curr, :args]],
138
+ [:nil]],
139
+ [:fcall, :define_attr_method,
140
+ [:array, [:lit, :x], [:lit, :sequence_name]]]],
141
+ },
142
+
143
+ "block_pass_splat" => {
144
+ "Ruby" => "def blah(*args, &block)\n other(*args, &block)\nend",
145
+ "ParseTree" => [:defn, :blah,
146
+ [:scope,
147
+ [:block,
148
+ [:args, "*args".intern],
149
+ [:block_arg, :block],
150
+ [:block_pass,
151
+ [:lvar, :block],
152
+ [:fcall, :other, [:splat, [:lvar, :args]]]]]]],
153
+ },
154
+
132
155
  "bmethod" => {
133
156
  "Ruby" => [Examples, :unsplatted],
134
157
  "ParseTree" => [:defn,
135
158
  :unsplatted,
136
159
  [:bmethod,
137
160
  [:dasgn_curr, :x],
138
- [:call, [:dvar, :x], :+, [:array, [:lit, 1]]]]],
161
+ [:call, [:dvar, :x], "+".intern, [:array, [:lit, 1]]]]],
139
162
  "Ruby2Ruby" => "def unsplatted(x)\n (x + 1)\nend"
140
163
  },
141
164
 
@@ -152,13 +175,13 @@ class ParseTreeTestCase < Test::Unit::TestCase
152
175
  },
153
176
 
154
177
  "break" => {
155
- "Ruby" => "loop do\n break if true\nend",
178
+ "Ruby" => "loop { break if true }",
156
179
  "ParseTree" => [:iter,
157
180
  [:fcall, :loop], nil, [:if, [:true], [:break], nil]],
158
181
  },
159
182
 
160
183
  "break_arg" => {
161
- "Ruby" => "loop do\n break 42 if true\nend",
184
+ "Ruby" => "loop { break 42 if true }",
162
185
  "ParseTree" => [:iter,
163
186
  [:fcall, :loop], nil,
164
187
  [:if, [:true], [:break, [:lit, 42]], nil]],
@@ -364,7 +387,7 @@ class ParseTreeTestCase < Test::Unit::TestCase
364
387
  },
365
388
 
366
389
  "dasgn" => {
367
- "Ruby" => "a.each do |x|\n b.each do |y|\n x = (x + 1)\n end\nend",
390
+ "Ruby" => "a.each { |x| b.each { |y| x = (x + 1) } }",
368
391
  "ParseTree" => [:iter,
369
392
  [:call, [:vcall, :a], :each],
370
393
  [:dasgn_curr, :x],
@@ -626,12 +649,12 @@ end",
626
649
  },
627
650
 
628
651
  "iteration1" => {
629
- "Ruby" => "loop do end",
652
+ "Ruby" => "loop { }",
630
653
  "ParseTree" => [:iter, [:fcall, :loop], nil],
631
654
  },
632
655
 
633
656
  "iteration2" => {
634
- "Ruby" => "array = [1, 2, 3]\narray.each do |x|\n puts(x.to_s)\nend\n",
657
+ "Ruby" => "array = [1, 2, 3]\narray.each { |x| puts(x.to_s) }\n",
635
658
  "ParseTree" => [:block,
636
659
  [:lasgn, :array,
637
660
  [:array, [:lit, 1], [:lit, 2], [:lit, 3]]],
@@ -642,7 +665,7 @@ end",
642
665
  },
643
666
 
644
667
  "iteration3" => {
645
- "Ruby" => "1.upto(3) do |n|\n puts(n.to_s)\nend",
668
+ "Ruby" => "1.upto(3) { |n| puts(n.to_s) }",
646
669
  "ParseTree" => [:iter,
647
670
  [:call, [:lit, 1], :upto, [:array, [:lit, 3]]],
648
671
  [:dasgn_curr, :n],
@@ -650,7 +673,7 @@ end",
650
673
  },
651
674
 
652
675
  "iteration4" => {
653
- "Ruby" => "3.downto(1) do |n|\n puts(n.to_s)\nend",
676
+ "Ruby" => "3.downto(1) { |n| puts(n.to_s) }",
654
677
  "ParseTree" => [:iter,
655
678
  [:call, [:lit, 3], :downto, [:array, [:lit, 1]]],
656
679
  [:dasgn_curr, :n],
@@ -662,13 +685,13 @@ end",
662
685
  "ParseTree" => [:block,
663
686
  [:lasgn, :argl, [:lit, 10]],
664
687
  [:while,
665
- [:call, [:lvar, :argl], :>=, [:array, [:lit, 1]]],
688
+ [:call, [:lvar, :argl], ">=".intern, [:array, [:lit, 1]]],
666
689
  [:block,
667
690
  [:fcall, :puts, [:array, [:str, "hello"]]],
668
691
  [:lasgn,
669
692
  :argl,
670
693
  [:call, [:lvar, :argl],
671
- :-, [:array, [:lit, 1]]]]], true]],
694
+ "-".intern, [:array, [:lit, 1]]]]], true]],
672
695
  },
673
696
 
674
697
  "iteration6" => {
@@ -766,9 +789,28 @@ end",
766
789
  "masgn_iasgn" => {
767
790
  "Ruby" => "a, @b = c, d",
768
791
  "ParseTree" => [:masgn,
769
- [:array, [:lasgn, :a], [:iasgn, :@b]],
792
+ [:array, [:lasgn, :a], [:iasgn, "@b".intern]],
770
793
  [:array, [:vcall, :c], [:vcall, :d]]],
771
794
  },
795
+
796
+ "masgn_attrasgn" => {
797
+ "Ruby" => "a, b.c = d, e",
798
+ "ParseTree" => [:masgn,
799
+ [:array, [:lasgn, :a], [:attrasgn, [:vcall, :b], :c=]],
800
+ [:array, [:vcall, :d], [:vcall, :e]]],
801
+ },
802
+
803
+ "masgn_splat" => {
804
+ "Ruby" => "a, b, *c = d, e, f, g",
805
+ "ParseTree" => [:masgn,
806
+ [:array, [:lasgn, :a], [:lasgn, :b]],
807
+ [:lasgn, :c],
808
+ [:array,
809
+ [:vcall, :d], [:vcall, :e],
810
+ [:vcall, :f], [:vcall, :g]]]
811
+ },
812
+
813
+
772
814
  "match" => {
773
815
  "Ruby" => "1 if /x/",
774
816
  "ParseTree" => [:if, [:match, [:lit, /x/]], [:lit, 1], nil],
@@ -792,7 +834,7 @@ end",
792
834
  },
793
835
 
794
836
  "next" => {
795
- "Ruby" => "loop do\n next if false\nend",
837
+ "Ruby" => "loop { next if false }",
796
838
  "ParseTree" => [:iter,
797
839
  [:fcall, :loop],
798
840
  nil,
@@ -862,28 +904,28 @@ end",
862
904
  },
863
905
 
864
906
  "postexe" => {
865
- "Ruby" => "END {\n 1\n}",
907
+ "Ruby" => "END { 1 }",
866
908
  "ParseTree" => [:iter, [:postexe], nil, [:lit, 1]],
867
909
  },
868
910
 
869
- "proc_no_args" => {
870
- "Ruby" => "proc do\n (x + 1)\nend",
911
+ "proc_args" => {
912
+ "Ruby" => "proc { |x| (x + 1) }",
871
913
  "ParseTree" => [:iter,
872
914
  [:fcall, :proc],
873
- nil,
874
- [:call, [:vcall, :x], :+, [:array, [:lit, 1]]]],
915
+ [:dasgn_curr, :x],
916
+ [:call, [:dvar, :x], :+, [:array, [:lit, 1]]]],
875
917
  },
876
918
 
877
- "proc_args" => {
878
- "Ruby" => "proc do |x|\n (x + 1)\nend",
919
+ "proc_no_args" => {
920
+ "Ruby" => "proc { (x + 1) }",
879
921
  "ParseTree" => [:iter,
880
922
  [:fcall, :proc],
881
- [:dasgn_curr, :x],
882
- [:call, [:dvar, :x], :+, [:array, [:lit, 1]]]],
923
+ nil,
924
+ [:call, [:vcall, :x], :+, [:array, [:lit, 1]]]],
883
925
  },
884
926
 
885
927
  "redo" => {
886
- "Ruby" => "loop do\n redo if false\nend",
928
+ "Ruby" => "loop { redo if false }",
887
929
  "ParseTree" => [:iter,
888
930
  [:fcall, :loop], nil, [:if, [:false], [:redo], nil]],
889
931
  },
@@ -893,16 +935,16 @@ end",
893
935
  "ParseTree" => [:rescue, [:vcall, :blah], [:resbody, nil, [:nil]]],
894
936
  },
895
937
 
896
- "rescue_block_nada" => {
897
- "Ruby" => "begin\n blah\nrescue\n # do nothing\nend\n",
898
- "ParseTree" => [:begin, [:rescue, [:vcall, :blah], [:resbody, nil]]]
899
- },
900
-
901
938
  "rescue_block_body" => {
902
939
  "Ruby" => "begin\n blah\nrescue\n nil\nend\n",
903
940
  "ParseTree" => [:begin, [:rescue, [:vcall, :blah], [:resbody, nil, [:nil]]]],
904
941
  },
905
942
 
943
+ "rescue_block_nada" => {
944
+ "Ruby" => "begin\n blah\nrescue\n # do nothing\nend\n",
945
+ "ParseTree" => [:begin, [:rescue, [:vcall, :blah], [:resbody, nil]]]
946
+ },
947
+
906
948
  "rescue_exceptions" => {
907
949
  "Ruby" => "begin\n blah\nrescue RuntimeError => r\n # do nothing\nend\n",
908
950
  "ParseTree" => [:begin,
@@ -978,18 +1020,18 @@ end",
978
1020
  "Ruby2Ruby" => "undef :x\nundef :y\nundef :z\n",
979
1021
  },
980
1022
 
981
- "until_pre" => {
982
- "Ruby" => "until false do\n (1 + 1)\nend",
983
- "ParseTree" => [:until, [:false],
984
- [:call, [:lit, 1], :+, [:array, [:lit, 1]]], true],
985
- },
986
-
987
1023
  "until_post" => {
988
1024
  "Ruby" => "begin\n (1 + 1)\nend until false",
989
1025
  "ParseTree" => [:until, [:false],
990
1026
  [:call, [:lit, 1], :+, [:array, [:lit, 1]]], false],
991
1027
  },
992
1028
 
1029
+ "until_pre" => {
1030
+ "Ruby" => "until false do\n (1 + 1)\nend",
1031
+ "ParseTree" => [:until, [:false],
1032
+ [:call, [:lit, 1], :+, [:array, [:lit, 1]]], true],
1033
+ },
1034
+
993
1035
  "valias" => {
994
1036
  "Ruby" => "alias $y $x",
995
1037
  "ParseTree" => [:valias, :$y, :$x],
@@ -1114,7 +1156,7 @@ end",
1114
1156
  unless data.has_key?(output_name) then
1115
1157
  $stderr.puts "add_test(#{node.inspect}, :same)"
1116
1158
  end
1117
- assert data.has_key?(output_name), "Unknown expected data"
1159
+ assert data.has_key?(output_name), "Missing test data: #{self.class} #{node}"
1118
1160
  input = data[input_name].deep_clone
1119
1161
 
1120
1162
  expected = if data[output_name] == :same then
@@ -52,16 +52,15 @@ class TestProcessor < SexpProcessor # ZenTest SKIP
52
52
 
53
53
  def process_string(exp)
54
54
  return exp.shift
55
- end
55
+ end
56
56
 
57
- def rewrite_rewritable(exp)
57
+ def rewrite_rewritable(exp) # (a b c) => (a c b)
58
58
  return s(exp.shift, exp.pop, exp.shift)
59
59
  end
60
60
 
61
61
  def process_rewritable(exp)
62
62
  return s(exp.shift, exp.shift == 2, exp.shift == 1)
63
63
  end
64
-
65
64
  end
66
65
 
67
66
  class TestProcessorDefault < SexpProcessor # ZenTest SKIP
@@ -140,7 +139,6 @@ class TestSexpProcessor < Test::Unit::TestCase
140
139
 
141
140
  def test_require_empty_false
142
141
  @processor.require_empty = false
143
- @processor.expected = Object
144
142
 
145
143
  assert_nothing_raised do
146
144
  @processor.process([:nonempty, 1, 2, 3])
@@ -159,11 +157,26 @@ class TestSexpProcessor < Test::Unit::TestCase
159
157
  assert_equal([1, 2, 3], @processor.process(s(:strip, 1, 2, 3)))
160
158
  end
161
159
 
160
+ def test_rewrite
161
+ assert_equal(s(:rewritable, :b, :a),
162
+ @processor.rewrite(s(:rewritable, :a, :b)))
163
+ end
164
+
165
+ def test_rewrite_deep
166
+ assert_equal(s(:specific, s(:rewritable, :b, :a)),
167
+ @processor.rewrite(s(:specific, s(:rewritable, :a, :b))))
168
+ end
169
+
162
170
  def test_process_rewrite
163
171
  assert_equal(s(:rewritable, true, true),
164
172
  @processor.process(s(:rewritable, 1, 2)))
165
173
  end
166
174
 
175
+ def test_process_rewrite_deep
176
+ assert_equal(s(s(:rewritable, :b, :a)),
177
+ @processor.process(s(:specific, s(:rewritable, :a, :b))))
178
+ end
179
+
167
180
  def test_process_rewrite_not_empty
168
181
  assert_raise(NotEmptyError) do
169
182
  @processor.process(s(:rewritable, 1, 2, 2))
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0.9
3
3
  specification_version: 1
4
4
  name: ParseTree
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.6.4
7
- date: 2007-01-15 00:00:00 -08:00
6
+ version: 1.7.0
7
+ date: 2007-02-13 00:00:00 -08:00
8
8
  summary: Extract and enumerate ruby parse trees.
9
9
  require_paths:
10
10
  - lib
@@ -84,5 +84,5 @@ dependencies:
84
84
  requirements:
85
85
  - - ">="
86
86
  - !ruby/object:Gem::Version
87
- version: 1.1.7
87
+ version: 1.2.0
88
88
  version: