pattern-match 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|