rewrite 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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>
|