pattern-match 0.0.2 → 0.1.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/README.rdoc +1 -1
- data/lib/pattern-match/version.rb +1 -1
- data/lib/pattern-match.rb +39 -30
- data/test/test_pattern-match.rb +58 -4
- metadata +6 -6
data/README.rdoc
CHANGED
data/lib/pattern-match.rb
CHANGED
@@ -9,7 +9,7 @@ module PatternMatch
|
|
9
9
|
SUPPORT_REFINEMENTS = true
|
10
10
|
else
|
11
11
|
SUPPORT_REFINEMENTS = false
|
12
|
-
Module.module_eval
|
12
|
+
Module.module_eval do
|
13
13
|
private
|
14
14
|
|
15
15
|
def refine(klass, &block)
|
@@ -18,10 +18,10 @@ module PatternMatch
|
|
18
18
|
|
19
19
|
def using(klass)
|
20
20
|
end
|
21
|
-
|
21
|
+
end
|
22
22
|
end
|
23
23
|
|
24
|
-
module
|
24
|
+
module Deconstructable
|
25
25
|
def call(*subpatterns)
|
26
26
|
if Object == self
|
27
27
|
raise MalformedPatternError unless subpatterns.length == 1
|
@@ -38,7 +38,11 @@ module PatternMatch
|
|
38
38
|
|
39
39
|
module NameSpace
|
40
40
|
refine Class do
|
41
|
-
include
|
41
|
+
include Deconstructable
|
42
|
+
|
43
|
+
def deconstruct(val)
|
44
|
+
raise NotImplementedError, "need to define `#{__method__}'"
|
45
|
+
end
|
42
46
|
|
43
47
|
private
|
44
48
|
|
@@ -48,35 +52,35 @@ module PatternMatch
|
|
48
52
|
end
|
49
53
|
|
50
54
|
refine Array.singleton_class do
|
51
|
-
def
|
55
|
+
def deconstruct(val)
|
52
56
|
accept_self_instance_only(val)
|
53
57
|
val
|
54
58
|
end
|
55
59
|
end
|
56
60
|
|
57
61
|
refine Struct.singleton_class do
|
58
|
-
def
|
62
|
+
def deconstruct(val)
|
59
63
|
accept_self_instance_only(val)
|
60
64
|
val.values
|
61
65
|
end
|
62
66
|
end
|
63
67
|
|
64
68
|
refine Complex.singleton_class do
|
65
|
-
def
|
69
|
+
def deconstruct(val)
|
66
70
|
accept_self_instance_only(val)
|
67
71
|
val.rect
|
68
72
|
end
|
69
73
|
end
|
70
74
|
|
71
75
|
refine Rational.singleton_class do
|
72
|
-
def
|
76
|
+
def deconstruct(val)
|
73
77
|
accept_self_instance_only(val)
|
74
78
|
[val.numerator, val.denominator]
|
75
79
|
end
|
76
80
|
end
|
77
81
|
|
78
82
|
refine MatchData.singleton_class do
|
79
|
-
def
|
83
|
+
def deconstruct(val)
|
80
84
|
accept_self_instance_only(val)
|
81
85
|
val.captures.empty? ? [val[0]] : val.captures
|
82
86
|
end
|
@@ -86,26 +90,26 @@ module PatternMatch
|
|
86
90
|
def Struct.method_added(name)
|
87
91
|
if name == members[0]
|
88
92
|
this = self
|
89
|
-
PatternMatch::NameSpace.module_eval
|
93
|
+
PatternMatch::NameSpace.module_eval do
|
90
94
|
refine this.singleton_class do
|
91
|
-
include
|
95
|
+
include Deconstructable
|
92
96
|
end
|
93
|
-
|
97
|
+
end
|
94
98
|
end
|
95
99
|
end
|
96
100
|
|
97
101
|
refine Proc do
|
98
|
-
include
|
102
|
+
include Deconstructable
|
99
103
|
|
100
|
-
def
|
104
|
+
def deconstruct(val)
|
101
105
|
[self === val]
|
102
106
|
end
|
103
107
|
end
|
104
108
|
|
105
109
|
refine Symbol do
|
106
|
-
include
|
110
|
+
include Deconstructable
|
107
111
|
|
108
|
-
def
|
112
|
+
def deconstruct(val)
|
109
113
|
[self.to_proc === val]
|
110
114
|
end
|
111
115
|
end
|
@@ -113,14 +117,14 @@ module PatternMatch
|
|
113
117
|
|
114
118
|
refine Symbol do
|
115
119
|
def call(*args)
|
116
|
-
Proc.new {|obj| obj.
|
120
|
+
Proc.new {|obj| obj.__send__(self, *args) }
|
117
121
|
end
|
118
122
|
end
|
119
123
|
|
120
124
|
refine Regexp do
|
121
|
-
include
|
125
|
+
include Deconstructable
|
122
126
|
|
123
|
-
def
|
127
|
+
def deconstruct(val)
|
124
128
|
m = Regexp.new("\\A#{source}\\z", options).match(val.to_s)
|
125
129
|
raise PatternNotMatch unless m
|
126
130
|
m.captures.empty? ? [m[0]] : m.captures
|
@@ -142,7 +146,7 @@ module PatternMatch
|
|
142
146
|
end
|
143
147
|
|
144
148
|
def vars
|
145
|
-
@subpatterns.map(&:vars).
|
149
|
+
@subpatterns.map(&:vars).flatten
|
146
150
|
end
|
147
151
|
|
148
152
|
def binding
|
@@ -230,7 +234,7 @@ module PatternMatch
|
|
230
234
|
end
|
231
235
|
|
232
236
|
def match(val)
|
233
|
-
extracted_vals = pattern_match_env.call_refined_method(@extractor, :
|
237
|
+
extracted_vals = pattern_match_env.call_refined_method(@extractor, :deconstruct, val)
|
234
238
|
k = extracted_vals.length - (@subpatterns.length - 2)
|
235
239
|
quantifier = @subpatterns.find {|i| i.is_a?(PatternQuantifier) }
|
236
240
|
if quantifier
|
@@ -329,7 +333,7 @@ module PatternMatch
|
|
329
333
|
end
|
330
334
|
|
331
335
|
def match(val)
|
332
|
-
@val.
|
336
|
+
@val.__send__(@compare_by, val)
|
333
337
|
end
|
334
338
|
end
|
335
339
|
|
@@ -357,10 +361,6 @@ module PatternMatch
|
|
357
361
|
end
|
358
362
|
|
359
363
|
class PatternNot < Pattern
|
360
|
-
def initialize(subpattern)
|
361
|
-
super
|
362
|
-
end
|
363
|
-
|
364
364
|
def match(val)
|
365
365
|
! @subpatterns[0].match(val)
|
366
366
|
rescue PatternNotMatch
|
@@ -446,13 +446,19 @@ module PatternMatch
|
|
446
446
|
tmpbinding_module(obj).instance_eval do
|
447
447
|
begin
|
448
448
|
binding.each do |name, val|
|
449
|
-
|
450
|
-
|
449
|
+
stack = @stacks[name]
|
450
|
+
if stack.empty?
|
451
|
+
define_method(name) { stack[-1] }
|
452
|
+
private name
|
453
|
+
end
|
454
|
+
stack.push(val)
|
451
455
|
end
|
452
456
|
obj.instance_eval(&block)
|
453
457
|
ensure
|
454
458
|
binding.each do |name, _|
|
455
|
-
|
459
|
+
if @stacks[name].tap(&:pop).empty?
|
460
|
+
remove_method(name)
|
461
|
+
end
|
456
462
|
end
|
457
463
|
end
|
458
464
|
end
|
@@ -465,6 +471,9 @@ module PatternMatch
|
|
465
471
|
m = obj.singleton_class.ancestors.find {|i| i.is_a? TmpBindingModule }
|
466
472
|
unless m
|
467
473
|
m = TmpBindingModule.new
|
474
|
+
m.instance_eval do
|
475
|
+
@stacks = ::Hash.new {|h, k| h[k] = [] }
|
476
|
+
end
|
468
477
|
obj.extend(m)
|
469
478
|
end
|
470
479
|
m
|
@@ -486,7 +495,7 @@ module Kernel
|
|
486
495
|
using ::PatternMatch::NameSpace
|
487
496
|
|
488
497
|
def call_refined_method(obj, name, *args)
|
489
|
-
obj.
|
498
|
+
obj.__send__(name, *args)
|
490
499
|
end
|
491
500
|
end
|
492
501
|
env.instance_eval(&block)
|
data/test/test_pattern-match.rb
CHANGED
@@ -38,17 +38,61 @@ class TestPatternMatch < Test::Unit::TestCase
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def test_variable_shadowing
|
41
|
-
skip 'not implemented yet'
|
42
41
|
match(0) {
|
43
42
|
with(a) {
|
44
|
-
|
45
|
-
|
43
|
+
assert_equal(0, a)
|
44
|
+
match([1, 2]) {
|
45
|
+
with(_[a, b]) {
|
46
|
+
assert_equal(1, a)
|
47
|
+
assert_equal(2, b)
|
48
|
+
match([3, 4, 5]) {
|
49
|
+
with(_[a, b, c]) {
|
50
|
+
assert_equal(3, a)
|
51
|
+
assert_equal(4, b)
|
52
|
+
assert_equal(5, c)
|
53
|
+
}
|
54
|
+
}
|
46
55
|
assert_equal(1, a)
|
56
|
+
assert_equal(2, b)
|
57
|
+
assert_raise(NameError) { c }
|
47
58
|
}
|
48
59
|
}
|
49
60
|
assert_equal(0, a)
|
61
|
+
assert_raise(NameError) { b }
|
62
|
+
assert_raise(NameError) { c }
|
50
63
|
}
|
51
64
|
}
|
65
|
+
assert_raise(NameError) { a }
|
66
|
+
assert_raise(NameError) { b }
|
67
|
+
assert_raise(NameError) { c }
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_lexical_scoping(rec_call = false, f = nil)
|
71
|
+
skip 'not supported'
|
72
|
+
unless rec_call
|
73
|
+
match(0) {
|
74
|
+
with(a) {
|
75
|
+
assert_equal(0, a)
|
76
|
+
test_lexical_scoping(true, ->{ a }) {|g|
|
77
|
+
assert_equal(0, a)
|
78
|
+
assert_equal(1, g.())
|
79
|
+
}
|
80
|
+
assert_equal(0, a)
|
81
|
+
}
|
82
|
+
}
|
83
|
+
else
|
84
|
+
assert_raise(NameError) { a }
|
85
|
+
assert_equal(0, f.())
|
86
|
+
match(1) {
|
87
|
+
with(a) {
|
88
|
+
assert_equal(1, a)
|
89
|
+
assert_equal(0, f.())
|
90
|
+
yield ->{ a }
|
91
|
+
assert_equal(1, a)
|
92
|
+
assert_equal(0, f.())
|
93
|
+
}
|
94
|
+
}
|
95
|
+
end
|
52
96
|
end
|
53
97
|
|
54
98
|
def test_uscore
|
@@ -254,6 +298,16 @@ class TestPatternMatch < Test::Unit::TestCase
|
|
254
298
|
assert_equal(1, 2.times.find(&match { with(1) { true } }))
|
255
299
|
end
|
256
300
|
|
301
|
+
def test_extractor_class
|
302
|
+
assert_raise(NotImplementedError) {
|
303
|
+
c = Class.new
|
304
|
+
match(0) {
|
305
|
+
with(c.(a)) {
|
306
|
+
}
|
307
|
+
}
|
308
|
+
}
|
309
|
+
end
|
310
|
+
|
257
311
|
def test_extractor_class_struct
|
258
312
|
s = Struct.new(:a, :b, :c)
|
259
313
|
match(s[0, 1, 2]) {
|
@@ -403,7 +457,7 @@ class TestPatternMatch < Test::Unit::TestCase
|
|
403
457
|
c = Class.new
|
404
458
|
::PatternMatch::NameSpace.module_eval {
|
405
459
|
refine c.singleton_class do
|
406
|
-
def
|
460
|
+
def deconstruct(*)
|
407
461
|
[:c]
|
408
462
|
end
|
409
463
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pattern-match
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-03-
|
12
|
+
date: 2012-03-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement: &
|
16
|
+
requirement: &8625920 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *8625920
|
25
25
|
description: A pattern matching library.
|
26
26
|
email:
|
27
27
|
- kazuki@callcc.net
|
@@ -57,7 +57,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
57
57
|
version: '0'
|
58
58
|
segments:
|
59
59
|
- 0
|
60
|
-
hash:
|
60
|
+
hash: -900071050850383955
|
61
61
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
62
|
none: false
|
63
63
|
requirements:
|
@@ -66,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
66
66
|
version: '0'
|
67
67
|
segments:
|
68
68
|
- 0
|
69
|
-
hash:
|
69
|
+
hash: -900071050850383955
|
70
70
|
requirements: []
|
71
71
|
rubyforge_project:
|
72
72
|
rubygems_version: 1.8.11
|