rewrite 0.2.0 → 0.3.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.
@@ -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?