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.
- data/History.txt +2 -0
- data/Manifest.txt +19 -0
- data/lib/rewrite/by_example.rb +39 -0
- data/lib/rewrite/by_example/any_entity.rb +32 -0
- data/lib/rewrite/by_example/bind.rb +41 -0
- data/lib/rewrite/by_example/bind_sequence.rb +46 -0
- data/lib/rewrite/by_example/composition.rb +104 -0
- data/lib/rewrite/by_example/entity_matcher.rb +48 -0
- data/lib/rewrite/by_example/length_one.rb +50 -0
- data/lib/rewrite/by_example/literal_entity.rb +25 -0
- data/lib/rewrite/by_example/nil_entity.rb +26 -0
- data/lib/rewrite/by_example/object_to_matcher.rb +221 -0
- data/lib/rewrite/by_example/returning.rb +29 -0
- data/lib/rewrite/by_example/sequence.rb +57 -0
- data/lib/rewrite/by_example/sexp_entity.rb +51 -0
- data/lib/rewrite/by_example/symbol_entity.rb +37 -0
- data/lib/rewrite/by_example/unhygienic.rb +57 -0
- data/lib/rewrite/by_example/union_of_entities_sequence.rb +39 -0
- data/lib/rewrite/version.rb +1 -1
- data/test/test_by_example.rb +61 -37
- data/test/test_object_to_sequence_and_matcher.rb +128 -0
- data/website/index.html +4 -2
- data/website/index.txt +2 -0
- metadata +22 -2
@@ -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
|
data/lib/rewrite/version.rb
CHANGED
data/test/test_by_example.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.dirname(__FILE__) +
|
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 =
|
19
|
-
|
20
|
-
|
21
|
-
:
|
22
|
-
|
23
|
-
|
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 =
|
37
|
+
foo_andand_bar = ObjectToMatcher.from_sexp( :call,
|
35
38
|
s(:call,
|
36
|
-
|
39
|
+
Bind.new(:receiver, AnyEntity.new),
|
37
40
|
:andand
|
38
41
|
),
|
39
|
-
|
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 =
|
54
|
-
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
161
|
+
unfolder = ObjectToMatcher.binding(/^__to_(.*)$/).from_example {
|
159
162
|
__to_receiver.andand.__to_message
|
160
163
|
}
|
161
|
-
folder =
|
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
|
-
|
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 =
|
185
|
+
unfolder = ObjectToMatcher.binding(/^__to_(.*)$/).from_example {
|
182
186
|
__to_receiver.andand.__to_message(__to_parameter)
|
183
187
|
}
|
184
|
-
folder =
|
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 =
|
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 =
|
222
|
+
unfolder = ObjectToMatcher.binding(/^__to_(.*)$/, [/^__splat_(.*)$/]).from_example {
|
219
223
|
__to_receiver.andand.__to_message(__splat_parameters)
|
220
224
|
}
|
221
|
-
|
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
|
-
|
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 =
|
245
|
+
unfolder = ObjectToMatcher.binding(:receiver, :message, [:params]).from_example {
|
242
246
|
receiver.andand.message(params)
|
243
247
|
}
|
244
|
-
folder =
|
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
|
data/website/index.html
CHANGED
@@ -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.
|
36
|
+
<a href="http://rubyforge.org/projects/rewrite" class="numbers">0.3.0</a>
|
37
37
|
</div>
|
38
38
|
<h1>→ ‘rewrite’</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>,
|
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>
|