rewrite 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,39 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require File.expand_path(File.dirname(__FILE__) +'/sequence.rb')
4
+
5
+ module Rewrite
6
+
7
+ module ByExample
8
+
9
+ #--
10
+ #
11
+ # Acts like a union of sequences but is initialized with entities. Could be better!
12
+ class UnionOfEntitiesSequence < Sequence
13
+
14
+ attr_accessor :matchers, :length_range
15
+
16
+ def initialize(*matchers)
17
+ self.matchers = matchers.map { |matcher|
18
+ LengthOne.new(ObjectToMatcher.from_object(matcher))
19
+ }
20
+ @length_range = @matchers.inject(0..0) { |range, matcher| range_union(range, matcher.length_range) }
21
+ end
22
+
23
+ def unfolders_by_length(length)
24
+ self.matchers.inject([]) { |unfolders, matcher| unfolders + matcher.unfolders_by_length(length) }
25
+ end
26
+
27
+ def range_union(range1, range2)
28
+ ([range1.begin, range2.begin].min)..([range1.end, range2.end].max)
29
+ end
30
+
31
+ def to_s
32
+ "(#{matchers.map { |m| m.to_s }.join(' | ')})"
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -1,7 +1,7 @@
1
1
  module Rewrite #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 2
4
+ MINOR = 3
5
5
  TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper.rb'
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
2
 
3
3
  require 'sexp'
4
4
 
@@ -15,13 +15,16 @@ module Rewrite
15
15
  end
16
16
 
17
17
  def test_simple_entity_matcher
18
- foo_andand_bar = SexpEntity.new( :call,
19
- s(:call,
20
- s(:vcall, :foo),
21
- :andand
22
- ),
23
- :bar
24
- )
18
+ foo_andand_bar = nil
19
+ ObjectToMatcher.quietly do
20
+ foo_andand_bar = ObjectToMatcher.binding().from_object( s(:call,
21
+ s(:call,
22
+ s(:vcall, :foo),
23
+ :andand
24
+ ),
25
+ :bar)
26
+ )
27
+ end
25
28
  assert_not_nil(foo_andand_bar.unfold(
26
29
  s(:call, s(:call, s(:vcall, :foo), :andand), :bar)
27
30
  ))
@@ -31,12 +34,12 @@ module Rewrite
31
34
  end
32
35
 
33
36
  def test_simple_bind
34
- foo_andand_bar = SexpEntity.new( :call,
37
+ foo_andand_bar = ObjectToMatcher.from_sexp( :call,
35
38
  s(:call,
36
- BindEntity.new(:receiver),
39
+ Bind.new(:receiver, AnyEntity.new),
37
40
  :andand
38
41
  ),
39
- BindEntity.new(:message)
42
+ Bind.new(:message, AnyEntity.new)
40
43
  )
41
44
  assert_equal(
42
45
  {
@@ -50,8 +53,8 @@ module Rewrite
50
53
  end
51
54
 
52
55
  def test_any
53
- any = SexpEntity.new(
54
- Any.new(:foo, :bar)
56
+ any = ObjectToMatcher.from_sexp(
57
+ UnionOfEntitiesSequence.new(:foo, :bar)
55
58
  )
56
59
  assert_not_nil(any.unfold(
57
60
  s(:foo)
@@ -65,7 +68,7 @@ module Rewrite
65
68
  end
66
69
 
67
70
  def test_bind_expression_by_example
68
- something_andand_bar = SexpEntity.new(:bind => [/__to_(.*)$/]) { __to_something.andand.bar }
71
+ something_andand_bar = ObjectToMatcher.binding(/__to_(.*)$/).from_example { __to_something.andand.bar }
69
72
  assert_equal(
70
73
  { :something => [:vcall, :foo] },
71
74
  something_andand_bar.unfold( sexp { foo.andand.bar } )
@@ -73,7 +76,7 @@ module Rewrite
73
76
  end
74
77
 
75
78
  def test_bind_consistency_by_example
76
- something_plus_something = SexpEntity.new(:bind => [:__to_something]) {__to_something + __to_something }
79
+ something_plus_something = ObjectToMatcher.binding(:__to_something).from_example {__to_something + __to_something }
77
80
  assert_nil(
78
81
  something_plus_something.unfold(sexp { foo + bar })
79
82
  )
@@ -89,7 +92,7 @@ module Rewrite
89
92
  end
90
93
 
91
94
  def test_bind_method_name
92
- foo_andand_something = SexpEntity.new(:bind => [/__to_(.*)$/]) { foo.andand.__to_something }
95
+ foo_andand_something = ObjectToMatcher.binding(/__to_(.*)$/).from_example { foo.andand.__to_something }
93
96
  assert_equal(
94
97
  { :something => :bar },
95
98
  foo_andand_something.unfold( sexp { foo.andand.bar } )
@@ -97,7 +100,7 @@ module Rewrite
97
100
  end
98
101
 
99
102
  def test_bind_one_parameter
100
- foo_andand_bar_something = SexpEntity.new(:bind => [/__to_(.*)$/]) { foo.andand.bar(__to_something) }
103
+ foo_andand_bar_something = ObjectToMatcher.binding(/__to_(.*)$/).from_example { foo.andand.bar(__to_something) }
101
104
  assert_equal(
102
105
  { :something => [:lit, :bash] },
103
106
  foo_andand_bar_something.unfold( sexp { foo.andand.bar(:bash) } )
@@ -105,7 +108,7 @@ module Rewrite
105
108
  end
106
109
 
107
110
  def test_bind_sequence
108
- unfolder = SexpEntity.new(:array, BindSequence.new(:something))
111
+ unfolder = ObjectToMatcher.from_object(s(:array, BindSequence.new(:something)))
109
112
  assert_equal(
110
113
  { :something => [[:lit, :bash], [:lit, :blitz]] },
111
114
  unfolder.unfold(
@@ -115,7 +118,7 @@ module Rewrite
115
118
  end
116
119
 
117
120
  def test_bind_parameter_list
118
- foo_andand_bar_somethings = SexpEntity.new(:bind => [[/__splat_(.*)$/]]) { foo.andand.bar(__splat_something) }
121
+ foo_andand_bar_somethings = ObjectToMatcher.binding([/__splat_(.*)$/]).from_example { foo.andand.bar(__splat_something) }
119
122
  assert_equal(
120
123
  { :something => [[:lit, :bash], [:lit, :blitz]] },
121
124
  foo_andand_bar_somethings.unfold( sexp { foo.andand.bar(:bash, :blitz) } )
@@ -123,7 +126,7 @@ module Rewrite
123
126
  end
124
127
 
125
128
  def test_refolding_entities
126
- foo_andand_bar_something = SexpEntity.new(:bind => [/__to_(.*)$/]) { foo.andand.bar(__to_something) }
129
+ foo_andand_bar_something = ObjectToMatcher.binding(/__to_(.*)$/).from_example { foo.andand.bar(__to_something) }
127
130
  assert_equal(
128
131
  sexp { foo.andand.bar(:bash) },
129
132
  foo_andand_bar_something.fold( { :something => [:lit, :bash] } )
@@ -131,7 +134,7 @@ module Rewrite
131
134
  end
132
135
 
133
136
  def test_refolding_sequences
134
- foo_andand_bar_somethings = SexpEntity.new(:bind => [[/__splat_(.*)$/]]) { foo.andand.bar(__splat_something) }
137
+ foo_andand_bar_somethings = ObjectToMatcher.binding([/__splat_(.*)$/]).from_example { foo.andand.bar(__splat_something) }
135
138
  assert_equal(
136
139
  sexp { foo.andand.bar(:bash, :blitz) },
137
140
  foo_andand_bar_somethings.fold( { :something => [[:lit, :bash], [:lit, :blitz]] } )
@@ -139,7 +142,7 @@ module Rewrite
139
142
  end
140
143
 
141
144
  def test_simple_andand_refold
142
- folder = SexpEntity.new(:bind => [/^__to_(.*)$/]) {
145
+ folder = ObjectToMatcher.binding(/^__to_(.*)$/).from_example {
143
146
  lambda { |__G12345__|
144
147
  __G12345__ && __G12345__.__to_message
145
148
  }.call(__to_receiver)
@@ -155,10 +158,10 @@ module Rewrite
155
158
  end
156
159
 
157
160
  def test_simple_andand_hylomorphism
158
- unfolder = SexpEntity.new(:bind => [/^__to_(.*)$/]) {
161
+ unfolder = ObjectToMatcher.binding(/^__to_(.*)$/).from_example {
159
162
  __to_receiver.andand.__to_message
160
163
  }
161
- folder = SexpEntity.new(:bind => [/^__to_(.*)$/]) {
164
+ folder = ObjectToMatcher.binding(/^__to_(.*)$/).from_example {
162
165
  lambda { |__G12345__|
163
166
  __G12345__ && __G12345__.__to_message
164
167
  }.call(__to_receiver)
@@ -169,19 +172,20 @@ module Rewrite
169
172
  __G12345__ && __G12345__.age
170
173
  }.call(Person.find_by_name('Otto'))
171
174
  },
172
- folder.fold(
173
- unfolder.unfold(
175
+ begin
176
+ unfolded = unfolder.unfold(
174
177
  sexp { Person.find_by_name('Otto').andand.age }
175
178
  )
176
- )
179
+ folder.fold(unfolded)
180
+ end
177
181
  )
178
182
  end
179
183
 
180
184
  def test_andand_hylomorphism_with_a_parameter
181
- unfolder = SexpEntity.new(:bind => [/^__to_(.*)$/]) {
185
+ unfolder = ObjectToMatcher.binding(/^__to_(.*)$/).from_example {
182
186
  __to_receiver.andand.__to_message(__to_parameter)
183
187
  }
184
- folder = SexpEntity.new(:bind => [/^__to_(.*)$/]) {
188
+ folder = ObjectToMatcher.binding(/^__to_(.*)$/).from_example {
185
189
  lambda { |__G12345__|
186
190
  __G12345__ && __G12345__.__to_message(__to_parameter)
187
191
  }.call(__to_receiver)
@@ -201,7 +205,7 @@ module Rewrite
201
205
  end
202
206
 
203
207
  def test_alternate_folder
204
- folder = SexpEntity.new(:bind => [/^__to_(.*)$/]) {
208
+ folder = ObjectToMatcher.binding(/^__to_(.*)$/).from_example {
205
209
  lambda { |__G12345__|
206
210
  __G12345__.__to_message unless __G12345__.nil?
207
211
  }.call(__to_receiver)
@@ -215,10 +219,12 @@ module Rewrite
215
219
  end
216
220
 
217
221
  def test_andand_hylomorphism_with_a_parameter_list
218
- unfolder = SexpEntity.new(:bind => [/^__to_(.*)$/, [/^__splat_(.*)$/]]) {
222
+ unfolder = ObjectToMatcher.binding(/^__to_(.*)$/, [/^__splat_(.*)$/]).from_example {
219
223
  __to_receiver.andand.__to_message(__splat_parameters)
220
224
  }
221
- folder = SexpEntity.new(:bind => [/^__to_(.*)$/, [/^__splat_(.*)$/]]) {
225
+ subject = sexp { Person.andand.find(1,2,3) }
226
+ unfolded = unfolder.unfold(subject)
227
+ folder = ObjectToMatcher.binding(/^__to_(.*)$/, [/^__splat_(.*)$/]).from_example {
222
228
  lambda { |__G12345__|
223
229
  __G12345__ && __G12345__.__to_message(__splat_parameters)
224
230
  }.call(__to_receiver)
@@ -230,18 +236,16 @@ module Rewrite
230
236
  }.call(Person)
231
237
  },
232
238
  folder.fold(
233
- unfolder.unfold(
234
- sexp { Person.andand.find(1,2,3) }
235
- )
239
+ unfolded
236
240
  )
237
241
  )
238
242
  end
239
243
 
240
244
  def test_alternate_andand_hylomorphism_with_a_parameter_list
241
- unfolder = SexpEntity.new(:bind => [:receiver, :message, [:params]]) {
245
+ unfolder = ObjectToMatcher.binding(:receiver, :message, [:params]).from_example {
242
246
  receiver.andand.message(params)
243
247
  }
244
- folder = SexpEntity.new(:bind => [:receiver, :message, [:params]]) {
248
+ folder = ObjectToMatcher.binding(:receiver, :message, [:params]).from_example {
245
249
  lambda { |__G12345__|
246
250
  __G12345__.message(params) unless __G12345__.nil?
247
251
  }.call(receiver)
@@ -285,6 +289,26 @@ module Rewrite
285
289
  end
286
290
  )
287
291
  end
292
+
293
+ def test_literal_symbol
294
+ litsym = LiteralEntity.new
295
+ assert_not_nil(
296
+ litsym.unfold(s(:lit, :foo))
297
+ )
298
+ assert_not_nil(
299
+ litsym.unfold(sexp { :foo })
300
+ )
301
+ assert_nil(
302
+ litsym.unfold(sexp { 'bar' })
303
+ )
304
+ assert_nil(
305
+ litsym.unfold(sexp { 'bas'.to_sym })
306
+ )
307
+ end
308
+
309
+ def test_symbol_to_proc
310
+
311
+ end
288
312
 
289
313
  end
290
314
 
@@ -0,0 +1,128 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ require 'sexp'
4
+
5
+ module Rewrite
6
+
7
+ module ByExample
8
+
9
+ class TestObjectToPattern < Test::Unit::TestCase
10
+
11
+ include Rewrite::With
12
+
13
+ def sexp &proc
14
+ proc.to_sexp[2]
15
+ end
16
+
17
+ def test_object_matcher_proc_capturer_integrity
18
+ assert_nothing_raised(Exception) do
19
+ ObjectToMatcher.proc_capturer
20
+ end
21
+ end
22
+
23
+ def test_symbol_like_expression_matcher_integrity
24
+ assert_equal(
25
+ "s( (<:gvar> | <:dvar> | <:vcall> | <:lcall> | <:lit>), <__ => :variable_symbol> )",
26
+ ObjectToMatcher.symbol_like_expression_matcher.to_s
27
+ )
28
+ end
29
+
30
+ def test_object_to_pattern
31
+ assert_equal(/^(foo)$/, ObjectToMatcher.object_to_pattern(:foo))
32
+ assert_equal(/^(foo)$/, ObjectToMatcher.object_to_pattern('foo'))
33
+ end
34
+
35
+ def test_internal_binder
36
+ o2m = ObjectToMatcher.binding(:foo)
37
+ result = nil
38
+ ObjectToMatcher.quietly do
39
+ result = o2m.from_object(
40
+ s(:vcall, :foo)
41
+ )
42
+ end
43
+ assert_equal("__ => :foo", result.to_s)
44
+ end
45
+
46
+ def test_splatter
47
+ result = nil
48
+ ObjectToMatcher.quietly do
49
+ result = ObjectToMatcher.binding([:splat]).from_object(
50
+ s(
51
+ :array,
52
+ s(:vcall, :splat)
53
+ )
54
+ )
55
+ end
56
+ assert_equal("s( <:array>, __* => :splat )", result.to_s)
57
+ end
58
+
59
+ def test_binder_at_top_level
60
+ assert_equal(
61
+ ObjectToMatcher.binding('foo', :bar).from_object(
62
+ s(:vcall, :foo)
63
+ ).to_s,
64
+ ObjectToMatcher.binding('foo', :bar).from_example { foo }.to_s
65
+ )
66
+ assert_equal(
67
+ "__ => :foo",
68
+ ObjectToMatcher.binding('foo', :bar).from_object(
69
+ s(:vcall, :foo)
70
+ ).to_s
71
+ )
72
+ assert_equal(
73
+ "__ => :foo",
74
+ ObjectToMatcher.binding('foo', :bar).from_example { foo }.to_s
75
+ )
76
+ assert_equal(
77
+ "s( <:call>, <__ => :foo>, <__ => :bar> )",
78
+ ObjectToMatcher.binding('foo', :bar).from_example { foo.bar }.to_s
79
+ )
80
+ end
81
+
82
+ def test_proc_extraction
83
+ entity = ObjectToMatcher.from_object([:proc, nil, Bind.new(:sexp, AnyEntity.new)])
84
+ assert_equal("s( <:proc>, <nil>, <__ => :sexp> )", entity.to_s)
85
+ end
86
+
87
+ def test_proc_to_sexp
88
+ entity = ObjectToMatcher.from_example { a }
89
+ assert_equal("s( <:vcall>, <:a> )", entity.to_s)
90
+ end
91
+
92
+ def test_unfold_simplest
93
+ unfolder = ObjectToMatcher.binding('foo', :bar).from_example { foo }
94
+ assert_not_nil(unfolder.unfold(sexp { a }), "top-level expression is not a match")
95
+ end
96
+
97
+ def test_method_call
98
+ unfolder = ObjectToMatcher.binding('foo', :bar).from_example { foo.bar }
99
+ assert_not_nil(unfolder.unfold(sexp { a.b }))
100
+ end
101
+
102
+ def test_unfolding_and_refolding
103
+ unfolder = ObjectToMatcher.binding(/^__to_(.*)$/).from_example {
104
+ __to_receiver.andand.__to_message
105
+ }
106
+ subject = sexp { foo.andand.bar }
107
+ unfolded = unfolder.unfold(subject)
108
+ assert_equal(
109
+ {:message=>:bar, :receiver=>[:vcall, :foo]},
110
+ unfolded
111
+ )
112
+ refolder = ObjectToMatcher.binding(/^__to_(.*)$/).from_example {
113
+ lambda { |andand_helper|
114
+ andand_helper.__to_message if andand_helper
115
+ }.call(__to_receiver)
116
+ }
117
+ rewritten = eval(refolder.fold(unfolded).to_s)
118
+ assert_equal(
119
+ "lambda { |andand_helper| andand_helper.bar if andand_helper }.call(foo)",
120
+ Ruby2Ruby.new.process(rewritten)
121
+ )
122
+ end
123
+
124
+ end
125
+
126
+ end
127
+
128
+ end
@@ -33,7 +33,7 @@
33
33
  <h1>rewrite</h1>
34
34
  <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/rewrite"; return false'>
35
35
  <p>Get Version</p>
36
- <a href="http://rubyforge.org/projects/rewrite" class="numbers">0.2.0</a>
36
+ <a href="http://rubyforge.org/projects/rewrite" class="numbers">0.3.0</a>
37
37
  </div>
38
38
  <h1>&#x2192; &#8216;rewrite&#8217;</h1>
39
39
 
@@ -140,9 +140,11 @@
140
140
 
141
141
 
142
142
  <p><pre class='syntax'>
143
+ <span class="comment"># ...</span>
143
144
  <span class="ident">lambda</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">andand_temp</span><span class="punct">|</span>
144
145
  <span class="ident">andand_temp</span><span class="punct">.</span><span class="ident">bar</span><span class="punct">(</span><span class="symbol">:bash</span><span class="punct">,</span> <span class="ident">blitz</span><span class="punct">(</span><span class="number">5</span><span class="punct">))</span> <span class="keyword">if</span> <span class="ident">andand_temp</span>
145
146
  <span class="punct">}.</span><span class="ident">call</span><span class="punct">(</span><span class="ident">foo</span><span class="punct">)</span>
147
+ <span class="comment"># ...</span>
146
148
  </pre></p>
147
149
 
148
150
 
@@ -268,7 +270,7 @@ rake install_gem</pre>
268
270
 
269
271
  <p>Comments are welcome. Send an email to <a href="mailto:raganwald+rewrite@gmail.com">Reg Braithwaite</a> email via the <a href="http://groups.google.com/group/rewrite">forum</a></p>
270
272
  <p class="coda">
271
- <a href="http://weblog.raganwald.com/">Reginald Braithwaite</a>, 11th July 2008<br>
273
+ <a href="http://weblog.raganwald.com/">Reginald Braithwaite</a>, 18th July 2008<br>
272
274
  Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
273
275
  </p>
274
276
  </div>
@@ -85,9 +85,11 @@ end
85
85
  becomes:
86
86
 
87
87
  <pre syntax="ruby">
88
+ # ...
88
89
  lambda { |andand_temp|
89
90
  andand_temp.bar(:bash, blitz(5)) if andand_temp
90
91
  }.call(foo)
92
+ # ...
91
93
  </pre>
92
94
 
93
95
  h2. How does it work?