ParseTree 1.3.7 → 1.4.0

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