ParseTree 1.3.7 → 1.4.0

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,21 @@
1
+ *** 1.4.0 / 2005-10-15
2
+
3
+ + 5 minor enhancements
4
+ + Improved Makefile's install rule, uninstall, and added FILTER to all.
5
+ + Fixed minor issues w/ Makefile.
6
+ + Added -I=loadpath to parse_tree_abc.
7
+ + Added *args support for methods.
8
+ + Split out sexp to its own file.
9
+ + 2 bug fixes
10
+ + Fixed weird bug in parse_tree_deps where sort was failing on deps.
11
+ + ! Fixed fatal bug in parse_tree.rb caused by safe_level fix in ruby 1.8.3.
12
+
13
+ *** 1.3.8 / 2005-09-27
14
+
15
+ + 1 bug fix:
16
+ + Our private version of struct METHOD went out of sync w/ latest ruby.
17
+ + Only use this if you are on 1.8.3+.
18
+
1
19
  *** 1.3.7 / 2005-07-13
2
20
 
3
21
  + 3 bug fixes:
data/Makefile CHANGED
@@ -3,9 +3,27 @@ RUBY_DEBUG?=
3
3
  RUBY_FLAGS?=-w -Ilib:bin:../../RubyInline/dev
4
4
  RUBY_LIB?=$(shell $(RUBY) -rrbconfig -e 'include Config; print CONFIG["sitelibdir"]')
5
5
  PREFIX?=/usr/local
6
+ FILTER?=
7
+
8
+ LIB_FILES= \
9
+ composite_sexp_processor.rb \
10
+ parse_tree.rb \
11
+ sexp.rb \
12
+ sexp_processor.rb \
13
+ $(END)
14
+
15
+ TEST_FILES= \
16
+ test_sexp_processor.rb \
17
+ $(END)
18
+
19
+ BIN_FILES= \
20
+ parse_tree_abc \
21
+ parse_tree_show \
22
+ parse_tree_deps \
23
+ $(END)
6
24
 
7
25
  all test: FORCE
8
- $(RUBY) $(RUBY_DEBUG) $(RUBY_FLAGS) test/test_all.rb
26
+ $(RUBY) $(RUBY_DEBUG) $(RUBY_FLAGS) test/test_all.rb $(FILTER)
9
27
 
10
28
  # we only install test_sexp_processor.rb to help make ruby_to_c's
11
29
  # subclass tests work.
@@ -14,19 +32,17 @@ docs:
14
32
  rdoc -d -I png --main SexpProcessor -x test_\* -x something.rb
15
33
 
16
34
  install:
17
- cp -f lib/parse_tree.rb lib/sexp_processor.rb lib/composite_sexp_processor.rb $(RUBY_LIB)
18
- cp -f test/test_sexp_processor.rb $(RUBY_LIB)
19
- cp -f bin/parse_tree_show $(PREFIX)/bin
20
- cp -f bin/parse_tree_abc $(PREFIX)/bin
21
- chmod 444 $(RUBY_LIB)/parse_tree.rb $(RUBY_LIB)/sexp_processor.rb $(RUBY_LIB)/composite_sexp_processor.rb $(RUBY_LIB)/test_sexp_processor.rb
22
- chmod 555 $(PREFIX)/bin/parse_tree_show $(PREFIX)/bin/parse_tree_abc
35
+ cd lib && install -m 0444 $(LIB_FILES) $(RUBY_LIB)
36
+ cd test && install -m 0444 $(TEST_FILES) $(RUBY_LIB)
37
+ cd bin && install -m 0555 $(BIN_FILES) $(PREFIX)/bin
23
38
 
24
39
  uninstall:
25
- rm -f $(RUBY_LIB)/parse_tree.rb $(RUBY_LIB)/sexp_processor.rb $(RUBY_LIB)/composite_sexp_processor.rb $(RUBY_LIB)/test_sexp_processor.rb
26
- rm -f $(PREFIX)/bin/parse_tree_show $(PREFIX)/bin/parse_tree_abc
40
+ cd $(RUBY_LIB) && rm -f $(LIB_FILES) $(TEST_FILES)
41
+ cd $(PREFIX)/bin && rm -f $(BIN_FILES)
27
42
 
28
43
  audit:
29
- ZenTest composite_sexp_processor.rb sexp_processor.rb test_all.rb test_composite_sexp_processor.rb test_sexp_processor.rb
44
+ ZenTest -I=lib:test $(addprefix lib/,$(LIB_FILES)) test/test_all.rb
45
+ # test_composite_sexp_processor.rb test_sexp_processor.rb
30
46
 
31
47
  clean:
32
48
  -find . -name \*~ | xargs rm
@@ -36,6 +52,6 @@ demo:
36
52
  echo 1+1 | $(RUBY) $(RUBY_FLAGS) ./bin/parse_tree_show -f
37
53
 
38
54
  gem:
39
- gem ParseTree.gemspec
55
+ ruby ParseTree.gemspec
40
56
 
41
57
  FORCE:
@@ -1,17 +1,20 @@
1
1
  History.txt
2
2
  Makefile
3
3
  Manifest.txt
4
- README.txt
5
4
  ParseTree.gemspec
5
+ README.txt
6
6
  bin/parse_tree_abc
7
7
  bin/parse_tree_deps
8
8
  bin/parse_tree_show
9
+ demo/printer.rb
9
10
  lib/composite_sexp_processor.rb
10
11
  lib/parse_tree.rb
12
+ lib/sexp.rb
11
13
  lib/sexp_processor.rb
12
14
  test/something.rb
13
15
  test/test_all.rb
14
16
  test/test_composite_sexp_processor.rb
15
17
  test/test_parse_tree.rb
18
+ test/test_sexp.rb
16
19
  test/test_sexp_processor.rb
17
20
  validate.sh
@@ -1,4 +1,4 @@
1
- #!/usr/local/bin/ruby
1
+ #!/usr/local/bin/ruby -ws
2
2
 
3
3
  # ABC metric
4
4
  #
@@ -6,9 +6,16 @@
6
6
  #
7
7
  # A simple way to measure the complexity of a function or method.
8
8
 
9
+ if defined? $I and String === $I then
10
+ $I.split(/:/).each do |dir|
11
+ $: << dir
12
+ end
13
+ end
14
+
9
15
  PARSE_TREE_ABC=true
10
16
 
11
17
  begin require 'rubygems' rescue LoadError end
18
+ require 'sexp'
12
19
  require 'parse_tree'
13
20
  require 'sexp_processor'
14
21
 
@@ -78,5 +85,5 @@ score.sort_by { |k,v| v }.reverse.each do |key,val|
78
85
  tval += val
79
86
  printf "%3d) %-50s = %2d + %2d + %2d = %6.2f\n", count, name, a, b, c, val
80
87
  count += 1
81
- end
88
+ end rescue nil
82
89
  printf "%3d) %-50s = %2d + %2d + %2d = %6.2f\n", count, "Total", ta, tb, tc, tval
@@ -33,7 +33,7 @@ class DependencyAnalyzer < SexpProcessor
33
33
  end
34
34
 
35
35
  deps = analyzer.dependencies
36
- deps.keys.sort.each do |dep_to|
36
+ deps.keys.sort_by {|k| k.to_s}.each do |dep_to|
37
37
  dep_from = deps[dep_to]
38
38
  puts "#{dep_to}: #{dep_from.uniq.sort.join(", ")}"
39
39
  end
@@ -57,5 +57,6 @@ end
57
57
  if __FILE__ == $0 then
58
58
  ARGV.each { |name| require name }
59
59
  ObjectSpace.each_object(Module) { |klass| new_classes << klass }
60
+ new_classes.delete DependencyAnalyzer unless defined? $a
60
61
  DependencyAnalyzer.process(*(new_classes - old_classes))
61
62
  end
@@ -0,0 +1,20 @@
1
+ #!/usr/local/bin/ruby -w
2
+ require 'rubygems'
3
+ require 'sexp_processor'
4
+
5
+ class QuickPrinter < SexpProcessor
6
+ def initialize
7
+ super
8
+ self.strict = false
9
+ self.auto_shift_type = true
10
+ end
11
+ def process_defn(exp)
12
+ name = exp.shift
13
+ args = process exp.shift
14
+ body = process exp.shift
15
+ puts " def #{name}"
16
+ return s(:defn, name, args, body)
17
+ end
18
+ end
19
+
20
+ QuickPrinter.new.process(*ParseTree.new.parse_tree(QuickPrinter))
@@ -24,7 +24,7 @@ require 'inline'
24
24
 
25
25
  class ParseTree
26
26
 
27
- VERSION = '1.3.7'
27
+ VERSION = '1.4.0'
28
28
 
29
29
  ##
30
30
  # Initializes a ParseTree instance. Includes newline nodes if
@@ -129,13 +129,14 @@ class ParseTree
129
129
  # builder.add_compile_flags "-Wmissing-prototypes"
130
130
  # builder.add_compile_flags "-Wsign-compare"
131
131
 
132
- builder.prefix %q{
132
+ builder.prefix %{
133
133
  #define nd_3rd u3.node
134
134
 
135
135
  struct METHOD {
136
136
  VALUE klass, rklass;
137
137
  VALUE recv;
138
138
  ID id, oid;
139
+ #{ RUBY_VERSION <= "1.8.2" ? "" : "int safe_level;" }
139
140
  NODE *body;
140
141
  };
141
142
 
@@ -586,7 +587,8 @@ again_no_block:
586
587
  arg_count = node->nd_rest;
587
588
  if (arg_count > 0) {
588
589
  // *arg name
589
- rb_ary_push(current, ID2SYM(locals[node->nd_rest + 1]));
590
+ VALUE sym = rb_str_intern(rb_str_plus(rb_str_new2("*"), rb_str_new2(rb_id2name(locals[node->nd_rest + 1]))));
591
+ rb_ary_push(current, sym);
590
592
  } else if (arg_count == -1) {
591
593
  // nothing to do in this case, handled above
592
594
  } else if (arg_count == -2) {
@@ -0,0 +1,257 @@
1
+ ##
2
+ # Sexps are the basic storage mechanism of SexpProcessor. Sexps have
3
+ # a +type+ (to be renamed +node_type+) which is the first element of
4
+ # the Sexp. The type is used by SexpProcessor to determine whom to
5
+ # dispatch the Sexp to for processing.
6
+
7
+ $TESTING ||= false # unless defined $TESTING
8
+
9
+ class Sexp < Array # ZenTest FULL
10
+
11
+ @@array_types = [ :array, :args, ]
12
+
13
+ ##
14
+ # Named positional parameters.
15
+ # Use with +SexpProcessor.require_empty=false+.
16
+ attr_accessor :accessors
17
+
18
+ ##
19
+ # Create a new Sexp containing +args+.
20
+
21
+ def initialize(*args)
22
+ @accessors = []
23
+ super(args)
24
+ end
25
+
26
+ def self.from_array(a)
27
+ ary = Array === a ? a : [a]
28
+
29
+ result = self.new
30
+
31
+ ary.each do |x|
32
+ case x
33
+ when Sexp
34
+ result << x
35
+ when Array
36
+ result << self.from_array(x)
37
+ else
38
+ result << x
39
+ end
40
+ end
41
+
42
+ result
43
+ end
44
+
45
+ def ==(obj) # :nodoc:
46
+ if obj.class == self.class then
47
+ super
48
+ else
49
+ false
50
+ end
51
+ end
52
+
53
+ def ===(sexp)
54
+ return nil unless Sexp === sexp
55
+ pattern = self # this is just for my brain
56
+
57
+ return true if pattern == sexp
58
+
59
+ sexp.each do |subset|
60
+ return true if pattern === subset
61
+ end
62
+
63
+ return nil
64
+ end
65
+
66
+ def =~(pattern)
67
+ return pattern === self
68
+ end
69
+
70
+ ##
71
+ # Returns true if the node_type is +array+ or +args+.
72
+ #
73
+ # REFACTOR: to TypedSexp - we only care when we have units.
74
+
75
+ def array_type?
76
+ type = self.first
77
+ @@array_types.include? type
78
+ end
79
+
80
+ ##
81
+ # Enumeratates the sexp yielding to +b+ when the node_type == +t+.
82
+
83
+ def each_of_type(t, &b)
84
+ each do | elem |
85
+ if Sexp === elem then
86
+ elem.each_of_type(t, &b)
87
+ b.call(elem) if elem.first == t
88
+ end
89
+ end
90
+ end
91
+
92
+ ##
93
+ # Replaces all elements whose node_type is +from+ with +to+. Used
94
+ # only for the most trivial of rewrites.
95
+
96
+ def find_and_replace_all(from, to)
97
+ each_with_index do | elem, index |
98
+ if Sexp === elem then
99
+ elem.find_and_replace_all(from, to)
100
+ else
101
+ self[index] = to if elem == from
102
+ end
103
+ end
104
+ end
105
+
106
+ def gsub(pattern, repl)
107
+ return repl if pattern == self
108
+
109
+ new = self.map do |subset|
110
+ case subset
111
+ when Sexp then
112
+ subset.gsub(pattern, repl)
113
+ else
114
+ subset
115
+ end
116
+ end
117
+
118
+ return Sexp.from_array(new)
119
+ end
120
+
121
+ def inspect # :nodoc:
122
+ sexp_str = self.map {|x|x.inspect}.join(', ')
123
+ return "s(#{sexp_str})"
124
+ end
125
+
126
+ ##
127
+ # Fancy-Schmancy method used to implement named positional accessors
128
+ # via +accessors+.
129
+ #
130
+ # Example:
131
+ #
132
+ # class MyProcessor < SexpProcessor
133
+ # def initialize
134
+ # super
135
+ # self.require_empty = false
136
+ # self.sexp_accessors = {
137
+ # :call => [:lhs, :name, :rhs]
138
+ # }
139
+ # ...
140
+ # end
141
+ #
142
+ # def process_call(exp)
143
+ # lhs = exp.lhs
144
+ # name = exp.name
145
+ # rhs = exp.rhs
146
+ # ...
147
+ # end
148
+ # end
149
+
150
+ def method_missing(meth, *a, &b)
151
+ super unless @accessors.include? meth
152
+
153
+ index = @accessors.index(meth) + 1 # skip type
154
+ return self.at(index)
155
+ end
156
+
157
+ def pretty_print(q) # :nodoc:
158
+ q.group(1, 's(', ')') do
159
+ q.seplist(self) {|v| q.pp v }
160
+ end
161
+ end
162
+
163
+ ##
164
+ # Returns the Sexp without the node_type.
165
+
166
+ def sexp_body
167
+ self[1..-1]
168
+ end
169
+
170
+ ##
171
+ # If run with debug, Sexp will raise if you shift on an empty
172
+ # Sexp. Helps with debugging.
173
+
174
+ def shift
175
+ raise "I'm empty" if self.empty?
176
+ super
177
+ end if $DEBUG or $TESTING
178
+
179
+ ##
180
+ # Returnes the bare bones structure of the sexp.
181
+ # s(:a, :b, s(:c, :d), :e) => s(:a, s(:c))
182
+
183
+ def structure
184
+ result = self.class.new
185
+ if Array === self.first then
186
+ result = self.first.structure
187
+ else
188
+ result << self.shift
189
+ self.grep(Array).each do |subexp|
190
+ result << subexp.structure
191
+ end
192
+ end
193
+ result
194
+ end
195
+
196
+ def sub(pattern, repl)
197
+ return repl.dup if pattern == self
198
+
199
+ done = false
200
+
201
+ new = self.map do |subset|
202
+ if done then
203
+ subset
204
+ else
205
+ case subset
206
+ when Sexp then
207
+ if pattern == subset then
208
+ done = true
209
+ repl.dup
210
+ elsif pattern === subset then
211
+ done = true
212
+ subset.sub pattern, repl
213
+ else
214
+ subset
215
+ end
216
+ else
217
+ subset
218
+ end
219
+ end
220
+ end
221
+
222
+ return Sexp.from_array(new)
223
+ end
224
+
225
+ def to_a # :nodoc:
226
+ self.map { |o| Sexp === o ? o.to_a : o }
227
+ end
228
+
229
+ def to_s # :nodoc:
230
+ inspect
231
+ end
232
+
233
+ end
234
+
235
+ class SexpMatchSpecial < Sexp; end
236
+
237
+ class SexpAny < SexpMatchSpecial
238
+ def ===(o)
239
+ return Sexp === o
240
+ end
241
+
242
+ def inspect
243
+ "ANY"
244
+ end
245
+ end
246
+
247
+ module SexpMatchSpecials
248
+ def ANY(); return SexpAny.new; end
249
+ end
250
+
251
+ ##
252
+ # This is just a stupid shortcut to make indentation much cleaner.
253
+
254
+ def s(*args)
255
+ Sexp.new(*args)
256
+ end
257
+
@@ -1,6 +1,8 @@
1
1
 
2
2
  $TESTING = false unless defined? $TESTING
3
3
 
4
+ require 'sexp'
5
+
4
6
  class Object
5
7
 
6
8
  ##
@@ -13,185 +15,6 @@ class Object
13
15
  end
14
16
  end
15
17
 
16
- ##
17
- # Sexps are the basic storage mechanism of SexpProcessor. Sexps have
18
- # a +type+ (to be renamed +node_type+) which is the first element of
19
- # the Sexp. The type is used by SexpProcessor to determine whom to
20
- # dispatch the Sexp to for processing.
21
-
22
- class Sexp < Array # ZenTest FULL
23
-
24
- @@array_types = [ :array, :args, ]
25
-
26
- ##
27
- # Named positional parameters.
28
- # Use with +SexpProcessor.require_empty=false+.
29
- attr_accessor :accessors
30
-
31
- ##
32
- # Create a new Sexp containing +args+.
33
-
34
- def initialize(*args)
35
- @accessors = []
36
- super(args)
37
- end
38
-
39
- def self.from_array(a)
40
- ary = Array === a ? a : [a]
41
-
42
- result = self.new
43
-
44
- ary.each do |x|
45
- case x
46
- when Sexp
47
- result << x
48
- when Array
49
- result << self.from_array(x)
50
- else
51
- result << x
52
- end
53
- end
54
-
55
- result
56
- end
57
-
58
- ##
59
- # Returns true if the node_type is +array+ or +args+.
60
- #
61
- # REFACTOR: to TypedSexp - we only care when we have units.
62
-
63
- def array_type?
64
- type = self.first
65
- @@array_types.include? type
66
- end
67
-
68
- ##
69
- # Enumeratates the sexp yielding to +b+ when the node_type == +t+.
70
-
71
- def each_of_type(t, &b)
72
- each do | elem |
73
- if Sexp === elem then
74
- elem.each_of_type(t, &b)
75
- b.call(elem) if elem.first == t
76
- end
77
- end
78
- end
79
-
80
- ##
81
- # Replaces all elements whose node_type is +from+ with +to+. Used
82
- # only for the most trivial of rewrites.
83
-
84
- def find_and_replace_all(from, to)
85
- each_with_index do | elem, index |
86
- if Sexp === elem then
87
- elem.find_and_replace_all(from, to)
88
- else
89
- self[index] = to if elem == from
90
- end
91
- end
92
- end
93
-
94
- ##
95
- # Fancy-Schmancy method used to implement named positional accessors
96
- # via +accessors+.
97
- #
98
- # Example:
99
- #
100
- # class MyProcessor < SexpProcessor
101
- # def initialize
102
- # super
103
- # self.require_empty = false
104
- # self.sexp_accessors = {
105
- # :call => [:lhs, :name, :rhs]
106
- # }
107
- # ...
108
- # end
109
- #
110
- # def process_call(exp)
111
- # lhs = exp.lhs
112
- # name = exp.name
113
- # rhs = exp.rhs
114
- # ...
115
- # end
116
- # end
117
-
118
- def method_missing(meth, *a, &b)
119
- super unless @accessors.include? meth
120
-
121
- index = @accessors.index(meth) + 1 # skip type
122
- return self.at(index)
123
- end
124
-
125
- ##
126
- # Returns the Sexp without the node_type.
127
-
128
- def sexp_body
129
- self[1..-1]
130
- end
131
-
132
- ##
133
- # Returnes the bare bones structure of the sexp.
134
- # s(:a, :b, s(:c, :d), :e) => s(:a, s(:c))
135
-
136
- def structure
137
- result = self.class.new
138
- if Array === self.first then
139
- result = self.first.structure
140
- else
141
- result << self.shift
142
- self.grep(Array).each do |subexp|
143
- result << subexp.structure
144
- end
145
- end
146
- result
147
- end
148
-
149
- def ==(obj) # :nodoc:
150
- case obj
151
- when Sexp
152
- super
153
- else
154
- false
155
- end
156
- end
157
-
158
- def to_a # :nodoc:
159
- self.map { |o| Sexp === o ? o.to_a : o }
160
- end
161
-
162
- def inspect # :nodoc:
163
- sexp_str = self.map {|x|x.inspect}.join(', ')
164
- return "s(#{sexp_str})"
165
- end
166
-
167
- def pretty_print(q) # :nodoc:
168
- q.group(1, 's(', ')') do
169
- q.seplist(self) {|v| q.pp v }
170
- end
171
- end
172
-
173
- def to_s # :nodoc:
174
- inspect
175
- end
176
-
177
- ##
178
- # If run with debug, Sexp will raise if you shift on an empty
179
- # Sexp. Helps with debugging.
180
-
181
- def shift
182
- raise "I'm empty" if self.empty?
183
- super
184
- end if $DEBUG or $TESTING
185
-
186
- end
187
-
188
- ##
189
- # This is just a stupid shortcut to make indentation much cleaner.
190
-
191
- def s(*args)
192
- Sexp.new(*args)
193
- end
194
-
195
18
  ##
196
19
  # SexpProcessor base exception class.
197
20
 
@@ -124,6 +124,12 @@ class Something
124
124
 
125
125
  # Other edge cases:
126
126
 
127
+ def opt_args(arg1, arg2 = 42, *args)
128
+ arg3 = arg1 * arg2 * 7
129
+ puts(arg3.to_s)
130
+ return "foo"
131
+ end
132
+
127
133
  def multi_args(arg1, arg2)
128
134
  arg3 = arg1 * arg2 * 7
129
135
  puts(arg3.to_s)
@@ -177,6 +177,21 @@ class TestParseTree < Test::Unit::TestCase
177
177
  [:call, [:lit, 3], :downto, [:array, [:lit, 1]]],
178
178
  nil,
179
179
  [:fcall, :puts, [:array, [:str, "hello"]]]]]]]
180
+ @@opt_args = [:defn, :opt_args,
181
+ [:scope,
182
+ [:block,
183
+ [:args, :arg1, :arg2, :"*args", [:block, [:lasgn, :arg2, [:lit, 42]]]],
184
+ [:lasgn, :arg3,
185
+ [:call,
186
+ [:call,
187
+ [:lvar, :arg1],
188
+ :*,
189
+ [:array, [:lvar, :arg2]]],
190
+ :*,
191
+ [:array, [:lit, 7]]]],
192
+ [:fcall, :puts, [:array, [:call, [:lvar, :arg3], :to_s]]],
193
+ [:return,
194
+ [:str, "foo"]]]]]
180
195
  @@multi_args = [:defn, :multi_args,
181
196
  [:scope,
182
197
  [:block,
@@ -0,0 +1,298 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ $TESTING = true
4
+
5
+ require 'test/unit' if $0 == __FILE__ unless defined? $ZENTEST and $ZENTEST
6
+ require 'test/unit/testcase'
7
+ require 'sexp_processor'
8
+ require 'stringio'
9
+ require 'pp'
10
+
11
+ class SexpTestCase < Test::Unit::TestCase
12
+
13
+ # KEY for regex tests
14
+ # :a == no change
15
+ # :b == will change (but sometimes ONLY once)
16
+ # :c == change to
17
+
18
+ include SexpMatchSpecials
19
+
20
+ def util_equals3(x, y)
21
+ result = x === y
22
+ assert_not_nil result, "#{x.inspect} does not === #{y.inspect}"
23
+ end
24
+
25
+ def setup
26
+ @any = ANY()
27
+ end
28
+
29
+ def test_stupid
30
+ # shuts up test/unit
31
+ end
32
+ end
33
+
34
+ class TestSexp < SexpTestCase # ZenTest FULL
35
+
36
+ def util_pretty_print(expect, input)
37
+ io = StringIO.new
38
+ PP.pp(input, io)
39
+ io.rewind
40
+ assert_equal(expect, io.read.chomp)
41
+ end
42
+
43
+ def setup
44
+ super
45
+ @sexp_class = Object.const_get(self.class.name[4..-1])
46
+ @processor = SexpProcessor.new
47
+ @sexp = @sexp_class.new(1, 2, 3)
48
+ @basic_sexp = s(:lasgn, :var, s(:lit, 42))
49
+ @re = s(:lit, 42)
50
+ @bad1 = s(:lit, 24)
51
+ @bad1 = s(:blah, 42)
52
+ end
53
+
54
+ def test_class_from_array
55
+ # raise NotImplementedError, 'Need to write test_class_from_array'
56
+ end
57
+
58
+ def test_class_index
59
+ # raise NotImplementedError, 'Need to write test_class_index'
60
+ end
61
+
62
+ def test_accessors; end # handled
63
+
64
+ def test_accessors_equals
65
+ a = s(:call, s(:lit, 1), "func", s(:array, s(:lit, 2)))
66
+ a.accessors = [:lhs, :name, :rhs]
67
+
68
+ assert_equal a.accessors, [:lhs, :name, :rhs]
69
+
70
+ assert_equal s(:lit, 1), a.lhs
71
+ assert_equal "func", a.name
72
+ assert_equal s(:array, s(:lit, 2)), a.rhs
73
+
74
+ a.accessors = []
75
+
76
+ assert_raises NoMethodError do
77
+ a.lhs
78
+ end
79
+ end
80
+
81
+ def test_array_type_eh
82
+ assert_equal false, @sexp.array_type?
83
+ @sexp.unshift :array
84
+ assert_equal true, @sexp.array_type?
85
+ end
86
+
87
+ def test_each_of_type
88
+ # TODO: huh... this tests fails if top level sexp :b is removed
89
+ @sexp = s(:b, s(:a, s(:b, s(:a), :a, s(:b, :a), s(:b, s(:a)))))
90
+ count = 0
91
+ @sexp.each_of_type(:a) do |exp|
92
+ count += 1
93
+ end
94
+ assert_equal(3, count, "must find 3 a's in #{@sexp.inspect}")
95
+ end
96
+
97
+ def test_equals2_array
98
+ # can't use assert_equals because it uses array as receiver
99
+ assert_not_equal(@sexp, [1, 2, 3],
100
+ "Sexp must not be equal to equivalent array")
101
+ # both directions just in case
102
+ # HACK - this seems to be a bug in ruby as far as I'm concerned
103
+ # assert_not_equal([1, 2, 3], @sexp,
104
+ # "Sexp must not be equal to equivalent array")
105
+ end
106
+
107
+ def test_equals2_not_body
108
+ sexp2 = s(1, 2, 5)
109
+ assert_not_equal(@sexp, sexp2)
110
+ end
111
+
112
+ def test_equals2_sexp
113
+ sexp2 = s(1, 2, 3)
114
+ if @sexp.class == Sexp then
115
+ # sexp3 = t(1, 2, 3, Type.str)
116
+ # case @sexp
117
+ # when TypedSexp
118
+ # assert_equal(@sexp, sexp3)
119
+ # assert_not_equal(@sexp, sexp2)
120
+ # when Sexp
121
+ assert_equal(@sexp, sexp2)
122
+ # assert_not_equal(@sexp, sexp3)
123
+ else
124
+ assert_not_equal(@sexp, sexp2)
125
+ # else
126
+ # flunk "unknown type"
127
+ end
128
+ end
129
+
130
+ def test_equals3_any
131
+ util_equals3 @any, s()
132
+ util_equals3 @any, s(:a)
133
+ util_equals3 @any, s(:a, :b, s(:c))
134
+ end
135
+
136
+ def test_equals3_full_match
137
+ util_equals3 s(), s() # 0
138
+ util_equals3 s(:blah), s(:blah) # 1
139
+ util_equals3 s(:a, :b), s(:a, :b) # 2
140
+ util_equals3 @basic_sexp, @basic_sexp.dup # deeper structure
141
+ end
142
+
143
+ def test_equals3_mismatch
144
+ assert_nil s() === s(:a)
145
+ assert_nil s(:a) === s()
146
+ assert_nil s(:blah1) === s(:blah2)
147
+ assert_nil s(:a) === s(:a, :b)
148
+ assert_nil s(:a, :b) === s(:a)
149
+ assert_nil s(:a1, :b) === s(:a2, :b)
150
+ assert_nil s(:a, :b1) === s(:a, :b2)
151
+ assert_nil @basic_sexp === @basic_sexp.dup.push(42)
152
+ assert_nil @basic_sexp.dup.push(42) === @basic_sexp
153
+ end
154
+
155
+ def test_equals3_subset_match
156
+ util_equals3 s(:a), s(s(:a), s(:b)) # left
157
+ util_equals3 s(:a), s(:blah, s(:a ), s(:b)) # mid 1
158
+ util_equals3 s(:a, 1), s(:blah, s(:a, 1), s(:b)) # mid 2
159
+ util_equals3 @basic_sexp, s(:blah, @basic_sexp.dup, s(:b)) # mid deeper
160
+ util_equals3 @basic_sexp, s(@basic_sexp.dup, s(:a), s(:b)) # left deeper
161
+
162
+ util_equals3 s(:a), s(:blah, s(:blah, s(:a))) # left deeper
163
+ end
164
+
165
+ # def test_equalstilde_any
166
+ # result = @basic_sexp =~ s(:lit, ANY())
167
+ # p result
168
+ # assert result
169
+ # end
170
+
171
+ def test_equalstilde_fancy
172
+ assert_nil s(:b) =~ s(:a, s(:b), :c)
173
+ assert_not_nil s(:a, s(:b), :c) =~ s(:b)
174
+ end
175
+
176
+ def test_equalstilde_plain
177
+ result = @basic_sexp =~ @re
178
+ assert result
179
+ end
180
+
181
+ def test_find_and_replace_all
182
+ @sexp = s(:a, s(:b, s(:a), s(:b), s(:b, s(:a))))
183
+ expected = s(:a, s(:a, s(:a), s(:a), s(:a, s(:a))))
184
+
185
+ @sexp.find_and_replace_all(:b, :a)
186
+
187
+ assert_equal(expected, @sexp)
188
+ end
189
+
190
+ def test_gsub
191
+ assert_equal s(:c), s().gsub(s(), s(:c))
192
+ assert_equal s(:c), s(:b).gsub(s(:b), s(:c))
193
+ assert_equal s(:a), s(:a).gsub(s(:b), s(:c))
194
+ assert_equal s(:a, s(:c)), s(:a, s(:b)).gsub(s(:b), s(:c))
195
+
196
+ assert_equal(s(:a, s(:c), s(:c)),
197
+ s(:a, s(:b), s(:b)).gsub(s(:b), s(:c)))
198
+ assert_equal(s(:a, s(:c), s(:a, s(:c))),
199
+ s(:a, s(:b), s(:a, s(:b))).gsub(s(:b), s(:c)))
200
+ end
201
+
202
+ def test_inspect
203
+ k = @sexp_class
204
+ n = k.name[0].chr.downcase
205
+ assert_equal("#{n}()",
206
+ k.new().inspect)
207
+ assert_equal("#{n}(:a)",
208
+ k.new(:a).inspect)
209
+ assert_equal("#{n}(:a, :b)",
210
+ k.new(:a, :b).inspect)
211
+ assert_equal("#{n}(:a, #{n}(:b))",
212
+ k.new(:a, k.new(:b)).inspect)
213
+ end
214
+
215
+ def test_method_missing
216
+ assert_raises NoMethodError do
217
+ @sexp.no_such_method
218
+ end
219
+
220
+ @sexp.accessors = [:its_a_method_now]
221
+
222
+ assert_nothing_raised do
223
+ assert_equal 2, @sexp.its_a_method_now
224
+ end
225
+ end
226
+
227
+ def test_pretty_print
228
+ util_pretty_print("s()",
229
+ s())
230
+ util_pretty_print("s(:a)",
231
+ s(:a))
232
+ util_pretty_print("s(:a, :b)",
233
+ s(:a, :b))
234
+ util_pretty_print("s(:a, s(:b))",
235
+ s(:a, s(:b)))
236
+ end
237
+
238
+ def test_sexp_body
239
+ assert_equal [2, 3], @sexp.sexp_body
240
+ end
241
+
242
+ def test_shift
243
+ assert_equal(1, @sexp.shift)
244
+ assert_equal(2, @sexp.shift)
245
+ assert_equal(3, @sexp.shift)
246
+
247
+ assert_raise(RuntimeError) do
248
+ @sexp.shift
249
+ end
250
+ end
251
+
252
+ def test_structure
253
+ @sexp = s(:a, 1, 2, s(:b, 3, 4), 5, 6)
254
+ expected = s(:a, s(:b))
255
+
256
+ assert_equal(expected, @sexp.structure)
257
+ end
258
+
259
+ def test_sub
260
+ assert_equal s(:c), s().sub(s(), s(:c))
261
+ assert_equal s(:c), s(:b).sub(s(:b), s(:c))
262
+ assert_equal s(:a), s(:a).sub(s(:b), s(:c))
263
+ assert_equal s(:a, s(:c)), s(:a, s(:c)).sub(s(:b), s(:c))
264
+
265
+ assert_equal s(:a, s(:c), s(:b)), s(:a, s(:b), s(:b)).sub(s(:b), s(:c))
266
+
267
+ assert_equal(s(:a, s(:c), s(:a)),
268
+ s(:a, s(:b), s(:a)).sub(s(:b), s(:c)))
269
+ assert_equal(s(:a, s(:c), s(:a, s(:a))),
270
+ s(:a, s(:b), s(:a, s(:a))).sub(s(:b), s(:c)))
271
+ assert_equal(s(:a, s(:a), s(:a, s(:c), s(:b))),
272
+ s(:a, s(:a), s(:a, s(:b), s(:b))).sub(s(:b), s(:c)))
273
+ assert_equal(s(:a, s(:c, s(:b))),
274
+ s(:a, s(:b)).sub(s(:b), s(:c, s(:b))))
275
+ end
276
+
277
+ def test_to_a
278
+ assert_equal([1, 2, 3], @sexp.to_a)
279
+ end
280
+
281
+ def test_to_s
282
+ test_inspect
283
+ end
284
+ end
285
+
286
+ class TestSexpAny < SexpTestCase
287
+
288
+ def setup
289
+ super
290
+ end
291
+
292
+ def test_equals3
293
+ util_equals3 @any, s()
294
+ util_equals3 @any, s(:a)
295
+ util_equals3 @any, s(:a, :b, s(:c))
296
+ end
297
+
298
+ end
@@ -78,156 +78,6 @@ end
78
78
 
79
79
  # Real test classes:
80
80
 
81
- class TestSexp < Test::Unit::TestCase # ZenTest FULL
82
-
83
- def setup
84
- @sexp_class = Object.const_get(self.class.name[4..-1])
85
- @processor = SexpProcessor.new
86
- @sexp = @sexp_class.new(1, 2, 3)
87
- end
88
-
89
- def test_new_nested
90
- @sexp = s(:lasgn, "var", s(:str, "foo"))
91
- assert_equal('s(:lasgn, "var", s(:str, "foo"))',
92
- @sexp.inspect)
93
- end
94
-
95
- def test_equals_array
96
- # can't use assert_equals because it uses array as receiver
97
- assert_not_equal(@sexp, [1, 2, 3],
98
- "Sexp must not be equal to equivalent array")
99
- # both directions just in case
100
- # HACK - not sure why it is failing now that we split out TypedSexp
101
- # assert_not_equal([1, 2, 3], @sexp,
102
- # "Sexp must not be equal to equivalent array")
103
- end
104
-
105
- def test_equals_sexp
106
- sexp2 = s(1, 2, 3)
107
- assert_equal(@sexp, sexp2)
108
- end
109
-
110
- def test_equals_not_body
111
- sexp2 = s(1, 2, 5)
112
- assert_not_equal(@sexp, sexp2)
113
- end
114
-
115
- def test_to_a
116
- assert_equal([1, 2, 3], @sexp.to_a)
117
- end
118
-
119
- def test_accessors=
120
- a = s(:call, s(:lit, 1), "func", s(:array, s(:lit, 2)))
121
- a.accessors = [:lhs, :name, :rhs]
122
-
123
- assert_equal a.accessors, [:lhs, :name, :rhs]
124
-
125
- assert_equal s(:lit, 1), a.lhs
126
- assert_equal "func", a.name
127
- assert_equal s(:array, s(:lit, 2)), a.rhs
128
-
129
- a.accessors = []
130
-
131
- assert_raises NoMethodError do
132
- a.lhs
133
- end
134
- end
135
- def test_accessors; end # handled
136
-
137
- def test_sexp_body
138
- assert_equal [2, 3], @sexp.sexp_body
139
- end
140
-
141
- def test_array_type?
142
- assert_equal false, @sexp.array_type?
143
- @sexp.unshift :array
144
- assert_equal true, @sexp.array_type?
145
- end
146
-
147
- def test_each_of_type
148
- # TODO: huh... this tests fails if top level sexp :b is removed
149
- @sexp = s(:b, s(:a, s(:b, s(:a), :a, s(:b, :a), s(:b, s(:a)))))
150
- count = 0
151
- @sexp.each_of_type(:a) do |exp|
152
- count += 1
153
- end
154
- assert_equal(3, count, "must find 3 a's in #{@sexp.inspect}")
155
- end
156
-
157
- def test_find_and_replace_all
158
- @sexp = s(:a, s(:b, s(:a), s(:b), s(:b, s(:a))))
159
- expected = s(:a, s(:a, s(:a), s(:a), s(:a, s(:a))))
160
-
161
- @sexp.find_and_replace_all(:b, :a)
162
-
163
- assert_equal(expected, @sexp)
164
- end
165
-
166
- def test_structure
167
- @sexp = s(:a, 1, 2, s(:b, 3, 4), 5, 6)
168
- expected = s(:a, s(:b))
169
-
170
- assert_equal(expected, @sexp.structure)
171
- end
172
-
173
- def test_method_missing
174
- assert_raises NoMethodError do
175
- @sexp.no_such_method
176
- end
177
-
178
- @sexp.accessors = [:its_a_method_now]
179
-
180
- assert_nothing_raised do
181
- assert_equal 2, @sexp.its_a_method_now
182
- end
183
- end
184
-
185
- def test_inspect
186
- k = @sexp_class
187
- n = k.name[0].chr.downcase
188
- assert_equal("#{n}()",
189
- k.new().inspect)
190
- assert_equal("#{n}(:a)",
191
- k.new(:a).inspect)
192
- assert_equal("#{n}(:a, :b)",
193
- k.new(:a, :b).inspect)
194
- assert_equal("#{n}(:a, #{n}(:b))",
195
- k.new(:a, k.new(:b)).inspect)
196
- end
197
-
198
- def test_to_s
199
- test_inspect
200
- end
201
-
202
- def util_pretty_print(expect, input)
203
- io = StringIO.new
204
- PP.pp(input, io)
205
- io.rewind
206
- assert_equal(expect, io.read.chomp)
207
- end
208
-
209
- def test_pretty_print
210
- util_pretty_print("s()",
211
- s())
212
- util_pretty_print("s(:a)",
213
- s(:a))
214
- util_pretty_print("s(:a, :b)",
215
- s(:a, :b))
216
- util_pretty_print("s(:a, s(:b))",
217
- s(:a, s(:b)))
218
- end
219
-
220
- def test_shift
221
- assert_equal(1, @sexp.shift)
222
- assert_equal(2, @sexp.shift)
223
- assert_equal(3, @sexp.shift)
224
-
225
- assert_raise(RuntimeError) do
226
- @sexp.shift
227
- end
228
- end
229
- end
230
-
231
81
  class TestSexpProcessor < Test::Unit::TestCase
232
82
 
233
83
  def setup
metadata CHANGED
@@ -1,69 +1,74 @@
1
- --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.10.1
1
+ !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11.1
3
3
  specification_version: 1
4
4
  name: ParseTree
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.3.7
7
- date: 2005-07-13
6
+ version: 1.4.0
7
+ date: 2005-10-17 00:00:00 -07:00
8
8
  summary: Extract and enumerate ruby parse trees.
9
9
  require_paths:
10
- - lib
11
- - test
10
+ - lib
11
+ - test
12
12
  email: ryand-ruby@zenspider.com
13
13
  homepage: http://www.zenspider.com/ZSS/Products/ParseTree/
14
14
  rubyforge_project: parsetree
15
- description: "ParseTree is a C extension (using RubyInline) that extracts the parse tree for
16
- an entire class or a specific method and returns it as a s-expression (aka sexp)
17
- using ruby's arrays, strings, symbols, and integers."
15
+ description: 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.
18
16
  autorequire: parse_tree
19
17
  default_executable:
20
18
  bindir: bin
21
19
  has_rdoc: true
22
20
  required_ruby_version: !ruby/object:Gem::Version::Requirement
23
21
  requirements:
24
- -
25
- - ">"
26
- - !ruby/object:Gem::Version
27
- version: 0.0.0
22
+ - - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
28
25
  version:
29
26
  platform: ruby
27
+ signing_key:
28
+ cert_chain:
30
29
  authors:
31
- - Ryan Davis
30
+ - Ryan Davis
32
31
  files:
33
- - History.txt
34
- - Makefile
35
- - Manifest.txt
36
- - README.txt
37
- - bin/parse_tree_abc
38
- - bin/parse_tree_deps
39
- - bin/parse_tree_show
40
- - lib/composite_sexp_processor.rb
41
- - lib/parse_tree.rb
42
- - lib/sexp_processor.rb
43
- - test/something.rb
44
- - test/test_all.rb
45
- - test/test_composite_sexp_processor.rb
46
- - test/test_parse_tree.rb
47
- - test/test_sexp_processor.rb
48
- - validate.sh
32
+ - History.txt
33
+ - Makefile
34
+ - Manifest.txt
35
+ - README.txt
36
+ - bin/parse_tree_abc
37
+ - bin/parse_tree_deps
38
+ - bin/parse_tree_show
39
+ - demo/printer.rb
40
+ - lib/composite_sexp_processor.rb
41
+ - lib/parse_tree.rb
42
+ - lib/sexp.rb
43
+ - lib/sexp_processor.rb
44
+ - test/something.rb
45
+ - test/test_all.rb
46
+ - test/test_composite_sexp_processor.rb
47
+ - test/test_parse_tree.rb
48
+ - test/test_sexp.rb
49
+ - test/test_sexp_processor.rb
50
+ - validate.sh
49
51
  test_files:
50
- - test/test_all.rb
52
+ - test/test_all.rb
51
53
  rdoc_options: []
54
+
52
55
  extra_rdoc_files: []
56
+
53
57
  executables:
54
- - parse_tree_abc
55
- - parse_tree_deps
56
- - parse_tree_show
58
+ - parse_tree_abc
59
+ - parse_tree_deps
60
+ - parse_tree_show
57
61
  extensions: []
62
+
58
63
  requirements: []
64
+
59
65
  dependencies:
60
- - !ruby/object:Gem::Dependency
61
- name: RubyInline
62
- version_requirement:
63
- version_requirements: !ruby/object:Gem::Version::Requirement
64
- requirements:
65
- -
66
- - ">="
67
- - !ruby/object:Gem::Version
68
- version: 3.2.0
69
- version:
66
+ - !ruby/object:Gem::Dependency
67
+ name: RubyInline
68
+ version_requirement:
69
+ version_requirements: !ruby/object:Gem::Version::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 3.2.0
74
+ version: