pattern-match 0.5.0 → 0.5.1
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +1 -0
- data/BSDL +1 -1
- data/COPYING +1 -1
- data/README.rdoc +13 -7
- data/lib/pattern-match.rb +3 -828
- data/lib/pattern-match/core.rb +710 -0
- data/lib/pattern-match/deconstructor.rb +60 -0
- data/lib/pattern-match/experimental.rb +46 -0
- data/lib/pattern-match/version.rb +1 -1
- data/pattern-match.gemspec +1 -0
- data/test/helper.rb +9 -0
- data/test/test_experimental.rb +92 -0
- data/test/{test_pattern-match.rb → test_standard.rb} +29 -81
- metadata +30 -11
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'pattern-match/core'
|
2
|
+
|
3
|
+
class Class
|
4
|
+
include PatternMatch::Deconstructable
|
5
|
+
|
6
|
+
def deconstruct(val)
|
7
|
+
raise NotImplementedError, "need to define `#{__method__}'"
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def accept_self_instance_only(val)
|
13
|
+
raise PatternMatch::PatternNotMatch unless val.kind_of?(self)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class << Array
|
18
|
+
def deconstruct(val)
|
19
|
+
accept_self_instance_only(val)
|
20
|
+
val
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class << Struct
|
25
|
+
def deconstruct(val)
|
26
|
+
accept_self_instance_only(val)
|
27
|
+
val.values
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class << Complex
|
32
|
+
def deconstruct(val)
|
33
|
+
accept_self_instance_only(val)
|
34
|
+
val.rect
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class << Rational
|
39
|
+
def deconstruct(val)
|
40
|
+
accept_self_instance_only(val)
|
41
|
+
[val.numerator, val.denominator]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class << MatchData
|
46
|
+
def deconstruct(val)
|
47
|
+
accept_self_instance_only(val)
|
48
|
+
val.captures.empty? ? [val[0]] : val.captures
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Regexp
|
53
|
+
include PatternMatch::Deconstructable
|
54
|
+
|
55
|
+
def deconstruct(val)
|
56
|
+
m = Regexp.new("\\A#{source}\\z", options).match(val.to_s)
|
57
|
+
raise PatternMatch::PatternNotMatch unless m
|
58
|
+
m.captures.empty? ? [m[0]] : m.captures
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'pattern-match/core'
|
2
|
+
|
3
|
+
module PatternMatch
|
4
|
+
module Deconstructable
|
5
|
+
remove_method :call
|
6
|
+
def call(*subpatterns)
|
7
|
+
if Object == self
|
8
|
+
PatternKeywordArgStyleDeconstructor.new(Object, :respond_to?, :__send__, *subpatterns)
|
9
|
+
else
|
10
|
+
pattern_matcher(*subpatterns)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module AttributeMatcher
|
16
|
+
def self.included(klass)
|
17
|
+
class << klass
|
18
|
+
def pattern_matcher(*subpatterns)
|
19
|
+
PatternKeywordArgStyleDeconstructor.new(self, :respond_to?, :__send__, *subpatterns)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module KeyMatcher
|
26
|
+
def self.included(klass)
|
27
|
+
class << klass
|
28
|
+
def pattern_matcher(*subpatterns)
|
29
|
+
PatternKeywordArgStyleDeconstructor.new(self, :has_key?, :[], *subpatterns)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Hash
|
37
|
+
include PatternMatch::KeyMatcher
|
38
|
+
end
|
39
|
+
|
40
|
+
class Object
|
41
|
+
def assert_pattern(pattern)
|
42
|
+
match(self) do
|
43
|
+
Kernel.eval("with(#{pattern}) { self }", Kernel.binding)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/pattern-match.gemspec
CHANGED
@@ -17,6 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f) }
|
18
18
|
s.require_paths = ['lib']
|
19
19
|
s.add_development_dependency 'rake'
|
20
|
+
s.add_development_dependency 'simplecov'
|
20
21
|
s.extra_rdoc_files = ['README.rdoc']
|
21
22
|
s.rdoc_options = ['--main', 'README.rdoc']
|
22
23
|
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require_relative 'helper'
|
2
|
+
require 'test/unit'
|
3
|
+
require_relative '../lib/pattern-match'
|
4
|
+
require_relative '../lib/pattern-match/experimental'
|
5
|
+
|
6
|
+
class TestExperimental < Test::Unit::TestCase
|
7
|
+
def test_matcher_attribute_matcher
|
8
|
+
person_class = Struct.new(:name, :age) do
|
9
|
+
include PatternMatch::AttributeMatcher
|
10
|
+
end
|
11
|
+
|
12
|
+
company_class = Struct.new(:name) do
|
13
|
+
include PatternMatch::AttributeMatcher
|
14
|
+
end
|
15
|
+
|
16
|
+
match([person_class.new("Mary", 50), company_class.new("C")]) do
|
17
|
+
with(_[company_class.(:name => "Mary"), company_class.(:name => "C")]) { flunk }
|
18
|
+
with(_[person_class.(:age, :name => person_name), company_class.(:name => company_name)]) do
|
19
|
+
assert_equal("Mary", person_name)
|
20
|
+
assert_equal(50, age)
|
21
|
+
assert_equal("C", company_name)
|
22
|
+
end
|
23
|
+
with(_) { flunk }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_matcher_class_hash
|
28
|
+
match({a: 0, b: 1}) do
|
29
|
+
with(Hash.(a: a, b: b, c: c)) { flunk }
|
30
|
+
with(Hash.(a: a, b: b)) do
|
31
|
+
assert_equal(0, a)
|
32
|
+
assert_equal(1, b)
|
33
|
+
end
|
34
|
+
with(_) { flunk }
|
35
|
+
end
|
36
|
+
|
37
|
+
match({a: 0, b: 1}) do
|
38
|
+
with(Hash.(a: a)) do
|
39
|
+
assert_equal(0, a)
|
40
|
+
end
|
41
|
+
with(_) { flunk }
|
42
|
+
end
|
43
|
+
|
44
|
+
match({a: 0}) do
|
45
|
+
with(Hash.(a: 0)) { pass }
|
46
|
+
with(_) { flunk }
|
47
|
+
end
|
48
|
+
|
49
|
+
match({a: 0, b: 1}) do
|
50
|
+
with(Hash.(:a, :b, :c)) { flunk }
|
51
|
+
with(Hash.(:a, :b)) do
|
52
|
+
assert_equal(0, a)
|
53
|
+
assert_equal(1, b)
|
54
|
+
end
|
55
|
+
with(_) { flunk }
|
56
|
+
end
|
57
|
+
|
58
|
+
match({a: 0, b: 1}) do
|
59
|
+
with(Hash.(:a, :b, b: b2)) do
|
60
|
+
assert_equal(0, a)
|
61
|
+
assert_raise(NameError) { b }
|
62
|
+
assert_equal(1, b2)
|
63
|
+
end
|
64
|
+
with(_) { flunk }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_matcher_class_object
|
69
|
+
match(0) do
|
70
|
+
with(Object.(:to_s, :to_i => i & 1)) { flunk }
|
71
|
+
with(Object.(:to_s, :to_i => i & 0)) do
|
72
|
+
assert_equal('0', to_s)
|
73
|
+
assert_equal(0, i)
|
74
|
+
end
|
75
|
+
with(_) { flunk }
|
76
|
+
end
|
77
|
+
|
78
|
+
assert_raise(PatternMatch::MalformedPatternError) do
|
79
|
+
match(0) do
|
80
|
+
with(Object.(a, b)) {}
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_object_assert_pattern
|
86
|
+
assert_equal([0], [0].assert_pattern('_[Fixnum]'))
|
87
|
+
assert_equal([0], [0].assert_pattern('_[a & Fixnum], guard { a.even? }'))
|
88
|
+
assert_raise(PatternMatch::NoMatchingPatternError) do
|
89
|
+
[0, 1].assert_pattern('_[Fixnum]')
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -1,11 +1,13 @@
|
|
1
|
+
require_relative 'helper'
|
1
2
|
require 'test/unit'
|
2
3
|
require_relative '../lib/pattern-match'
|
3
4
|
|
4
|
-
class
|
5
|
+
class TestStandard < Test::Unit::TestCase
|
5
6
|
def test_basic
|
6
7
|
this = self
|
7
8
|
ret = match([0, 1, 2, 3]) do
|
8
9
|
with(nil) { flunk }
|
10
|
+
with(_[]) { flunk }
|
9
11
|
with(_[a, 0, 0, b]) { flunk }
|
10
12
|
with(_[a, Fixnum , 2, b]) do
|
11
13
|
assert_equal(this, self)
|
@@ -31,6 +33,17 @@ class TestPatternMatch < Test::Unit::TestCase
|
|
31
33
|
with(i, guard { i.even? }) { pass }
|
32
34
|
with(_) { flunk }
|
33
35
|
end
|
36
|
+
|
37
|
+
match([]) do
|
38
|
+
with(_[]) { pass }
|
39
|
+
with(_) { flunk }
|
40
|
+
end
|
41
|
+
|
42
|
+
assert_raise(ArgumentError) do
|
43
|
+
match(0) do
|
44
|
+
p 1
|
45
|
+
end
|
46
|
+
end
|
34
47
|
end
|
35
48
|
|
36
49
|
def test_variable_shadowing
|
@@ -92,7 +105,7 @@ class TestPatternMatch < Test::Unit::TestCase
|
|
92
105
|
end
|
93
106
|
|
94
107
|
def test_override_singleton_method
|
95
|
-
skip 'Module#prepend not supported' unless Module.
|
108
|
+
skip 'Module#prepend not supported' unless Module.respond_to?(:prepend, true)
|
96
109
|
match(0) do
|
97
110
|
with(_test_override_singleton_method) do
|
98
111
|
def self._test_override_singleton_method
|
@@ -110,6 +123,12 @@ class TestPatternMatch < Test::Unit::TestCase
|
|
110
123
|
end
|
111
124
|
with(_) { flunk }
|
112
125
|
end
|
126
|
+
|
127
|
+
assert_raise(PatternMatch::MalformedPatternError) do
|
128
|
+
match(0) do
|
129
|
+
with(_(0, :==, nil)) {}
|
130
|
+
end
|
131
|
+
end
|
113
132
|
end
|
114
133
|
|
115
134
|
def test_splat
|
@@ -498,10 +517,17 @@ class TestPatternMatch < Test::Unit::TestCase
|
|
498
517
|
end
|
499
518
|
end
|
500
519
|
|
501
|
-
def
|
520
|
+
def test_match_without_arguments
|
502
521
|
assert_equal(1, 2.times.find(&match { with(1) { true }; with(_) { false } }))
|
503
522
|
end
|
504
523
|
|
524
|
+
def test_match_too_many_arguments
|
525
|
+
assert_raise(ArgumentError) do
|
526
|
+
match(0, 1) do
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
505
531
|
def test_deconstructor_class
|
506
532
|
assert_raise(NotImplementedError) do
|
507
533
|
c = Class.new
|
@@ -524,26 +550,6 @@ class TestPatternMatch < Test::Unit::TestCase
|
|
524
550
|
end
|
525
551
|
end
|
526
552
|
|
527
|
-
def test_deconstructor_class_attributes_with_hash
|
528
|
-
person_class = Struct.new(:name, :age) do
|
529
|
-
include PatternMatch::AttributeMatcher
|
530
|
-
end
|
531
|
-
|
532
|
-
company_class = Struct.new(:name) do
|
533
|
-
include PatternMatch::AttributeMatcher
|
534
|
-
end
|
535
|
-
|
536
|
-
match([person_class.new("Mary", 50), company_class.new("C")]) do
|
537
|
-
with(_[company_class.(:name => "Mary"), company_class.(:name => "C")]) { flunk }
|
538
|
-
with(_[person_class.(:age, :name => person_name), company_class.(:name => company_name)]) do
|
539
|
-
assert_equal("Mary", person_name)
|
540
|
-
assert_equal(50, age)
|
541
|
-
assert_equal("C", company_name)
|
542
|
-
end
|
543
|
-
with(_) { flunk }
|
544
|
-
end
|
545
|
-
end
|
546
|
-
|
547
553
|
def test_deconstructor_class_complex
|
548
554
|
match(Complex(0, 1)) do
|
549
555
|
with(Complex.(a, b)) do
|
@@ -604,62 +610,4 @@ class TestPatternMatch < Test::Unit::TestCase
|
|
604
610
|
with(_) { flunk }
|
605
611
|
end
|
606
612
|
end
|
607
|
-
|
608
|
-
def test_deconstructor_class_hash
|
609
|
-
match({a: 0, b: 1}) do
|
610
|
-
with(Hash.(a: a, b: b, c: c)) { flunk }
|
611
|
-
with(Hash.(a: a, b: b)) do
|
612
|
-
assert_equal(0, a)
|
613
|
-
assert_equal(1, b)
|
614
|
-
end
|
615
|
-
with(_) { flunk }
|
616
|
-
end
|
617
|
-
|
618
|
-
match({a: 0, b: 1}) do
|
619
|
-
with(Hash.(a: a)) do
|
620
|
-
assert_equal(0, a)
|
621
|
-
end
|
622
|
-
with(_) { flunk }
|
623
|
-
end
|
624
|
-
|
625
|
-
match({a: 0}) do
|
626
|
-
with(Hash.(a: 0)) { pass }
|
627
|
-
with(_) { flunk }
|
628
|
-
end
|
629
|
-
|
630
|
-
match({a: 0, b: 1}) do
|
631
|
-
with(Hash.(:a, :b, :c)) { flunk }
|
632
|
-
with(Hash.(:a, :b)) do
|
633
|
-
assert_equal(0, a)
|
634
|
-
assert_equal(1, b)
|
635
|
-
end
|
636
|
-
with(_) { flunk }
|
637
|
-
end
|
638
|
-
|
639
|
-
match({a: 0, b: 1}) do
|
640
|
-
with(Hash.(:a, :b, b: b2)) do
|
641
|
-
assert_equal(0, a)
|
642
|
-
assert_raise(NameError) { b }
|
643
|
-
assert_equal(1, b2)
|
644
|
-
end
|
645
|
-
with(_) { flunk }
|
646
|
-
end
|
647
|
-
end
|
648
|
-
|
649
|
-
def test_object
|
650
|
-
match(0) do
|
651
|
-
with(Object.(:to_s, :to_i => i & 1)) { flunk }
|
652
|
-
with(Object.(:to_s, :to_i => i & 0)) do
|
653
|
-
assert_equal('0', to_s)
|
654
|
-
assert_equal(0, i)
|
655
|
-
end
|
656
|
-
with(_) { flunk }
|
657
|
-
end
|
658
|
-
|
659
|
-
assert_raise(PatternMatch::MalformedPatternError) do
|
660
|
-
match(0) do
|
661
|
-
with(Object.(a, b)) {}
|
662
|
-
end
|
663
|
-
end
|
664
|
-
end
|
665
613
|
end
|
metadata
CHANGED
@@ -1,27 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pattern-match
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kazuki Tsujimoto
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: simplecov
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '0'
|
27
41
|
description: A pattern matching library.
|
@@ -32,39 +46,44 @@ extensions: []
|
|
32
46
|
extra_rdoc_files:
|
33
47
|
- README.rdoc
|
34
48
|
files:
|
35
|
-
- .gitignore
|
36
|
-
- .travis.yml
|
49
|
+
- ".gitignore"
|
50
|
+
- ".travis.yml"
|
37
51
|
- BSDL
|
38
52
|
- COPYING
|
39
53
|
- Gemfile
|
40
54
|
- README.rdoc
|
41
55
|
- Rakefile
|
42
56
|
- lib/pattern-match.rb
|
57
|
+
- lib/pattern-match/core.rb
|
58
|
+
- lib/pattern-match/deconstructor.rb
|
59
|
+
- lib/pattern-match/experimental.rb
|
43
60
|
- lib/pattern-match/version.rb
|
44
61
|
- pattern-match.gemspec
|
45
|
-
- test/
|
62
|
+
- test/helper.rb
|
63
|
+
- test/test_experimental.rb
|
64
|
+
- test/test_standard.rb
|
46
65
|
homepage: https://github.com/k-tsj/pattern-match
|
47
66
|
licenses: []
|
48
67
|
metadata: {}
|
49
68
|
post_install_message:
|
50
69
|
rdoc_options:
|
51
|
-
- --main
|
70
|
+
- "--main"
|
52
71
|
- README.rdoc
|
53
72
|
require_paths:
|
54
73
|
- lib
|
55
74
|
required_ruby_version: !ruby/object:Gem::Requirement
|
56
75
|
requirements:
|
57
|
-
- -
|
76
|
+
- - ">="
|
58
77
|
- !ruby/object:Gem::Version
|
59
78
|
version: '0'
|
60
79
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
80
|
requirements:
|
62
|
-
- -
|
81
|
+
- - ">="
|
63
82
|
- !ruby/object:Gem::Version
|
64
83
|
version: '0'
|
65
84
|
requirements: []
|
66
85
|
rubyforge_project:
|
67
|
-
rubygems_version: 2.
|
86
|
+
rubygems_version: 2.2.0
|
68
87
|
signing_key:
|
69
88
|
specification_version: 4
|
70
89
|
summary: A pattern matching library
|