algebrick 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -3
  3. data/README_FULL.md +13 -21
  4. data/VERSION +1 -1
  5. data/doc/actor.rb +21 -0
  6. data/doc/data.in.rb +99 -0
  7. data/doc/data.out.rb +103 -0
  8. data/doc/extending_behavior.in.rb +61 -0
  9. data/doc/extending_behavior.out.rb +62 -0
  10. data/doc/format.rb +75 -0
  11. data/doc/init.rb +1 -0
  12. data/doc/json.in.rb +39 -0
  13. data/doc/json.out.rb +43 -0
  14. data/doc/null.in.rb +36 -0
  15. data/doc/null.out.rb +40 -0
  16. data/doc/parametrized.in.rb +37 -0
  17. data/doc/parametrized.out.rb +41 -0
  18. data/doc/pattern_matching.in.rb +116 -0
  19. data/doc/pattern_matching.out.rb +122 -0
  20. data/doc/quick_example.in.rb +27 -0
  21. data/doc/quick_example.out.rb +27 -0
  22. data/doc/tree1.in.rb +10 -0
  23. data/doc/tree1.out.rb +10 -0
  24. data/doc/type_def.in.rb +21 -0
  25. data/doc/type_def.out.rb +21 -0
  26. data/doc/values.in.rb +52 -0
  27. data/doc/values.out.rb +58 -0
  28. data/lib/algebrick/atom.rb +49 -0
  29. data/lib/algebrick/dsl.rb +104 -0
  30. data/lib/algebrick/field_method_readers.rb +43 -0
  31. data/lib/algebrick/matcher_delegations.rb +45 -0
  32. data/lib/algebrick/matchers/abstract.rb +127 -0
  33. data/lib/algebrick/matchers/abstract_logic.rb +38 -0
  34. data/lib/algebrick/matchers/and.rb +29 -0
  35. data/lib/algebrick/matchers/any.rb +37 -0
  36. data/lib/algebrick/matchers/array.rb +57 -0
  37. data/lib/algebrick/matchers/atom.rb +28 -0
  38. data/lib/algebrick/matchers/not.rb +44 -0
  39. data/lib/algebrick/matchers/or.rb +51 -0
  40. data/lib/algebrick/matchers/product.rb +73 -0
  41. data/lib/algebrick/matchers/variant.rb +29 -0
  42. data/lib/algebrick/matchers/wrapper.rb +57 -0
  43. data/lib/algebrick/matchers.rb +31 -0
  44. data/lib/algebrick/matching.rb +62 -0
  45. data/lib/algebrick/parametrized_type.rb +122 -0
  46. data/lib/algebrick/product_constructors/abstract.rb +70 -0
  47. data/lib/algebrick/product_constructors/basic.rb +47 -0
  48. data/lib/algebrick/product_constructors/named.rb +58 -0
  49. data/lib/algebrick/product_constructors.rb +25 -0
  50. data/lib/algebrick/product_variant.rb +195 -0
  51. data/lib/algebrick/reclude.rb +39 -0
  52. data/lib/algebrick/serializer.rb +129 -0
  53. data/lib/algebrick/serializers.rb +25 -0
  54. data/lib/algebrick/type.rb +61 -0
  55. data/lib/algebrick/type_check.rb +58 -0
  56. data/lib/algebrick/types.rb +59 -0
  57. data/lib/algebrick/value.rb +41 -0
  58. data/lib/algebrick.rb +14 -1170
  59. data/spec/algebrick_test.rb +708 -0
  60. metadata +105 -27
@@ -0,0 +1,104 @@
1
+ # Copyright 2013 Petr Chalupa <git+algebrick@pitr.ch>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Algebrick
16
+ module DSL
17
+ module Shortcuts
18
+ def type(*variables, &block)
19
+ Algebrick.type *variables, &block
20
+ end
21
+
22
+ def atom
23
+ Algebrick.atom
24
+ end
25
+ end
26
+
27
+ class TypeDefinitionScope
28
+ include Shortcuts
29
+ include TypeCheck
30
+
31
+ attr_reader :new_type
32
+
33
+ def initialize(new_type, &block)
34
+ @new_type = Type! new_type, ProductVariant, ParametrizedType
35
+ instance_exec @new_type, &block
36
+ @new_type.kind if @new_type.is_a? ProductVariant
37
+ end
38
+
39
+ def fields(*fields)
40
+ @new_type.set_fields fields.first.is_a?(Hash) ? fields.first : fields
41
+ self
42
+ end
43
+
44
+ def fields!(*fields)
45
+ fields(*fields)
46
+ all_readers
47
+ end
48
+
49
+ def final!
50
+ @new_type.final!
51
+ self
52
+ end
53
+
54
+ def variants(*variants)
55
+ @new_type.set_variants *variants
56
+ self
57
+ end
58
+
59
+ def field_readers(*names)
60
+ @new_type.add_field_method_readers *names
61
+ self
62
+ end
63
+
64
+ alias_method :readers, :field_readers
65
+
66
+ def all_field_readers
67
+ @new_type.add_all_field_method_readers
68
+ self
69
+ end
70
+
71
+ alias_method :all_readers, :all_field_readers
72
+ end
73
+
74
+ class OuterShell
75
+ include Shortcuts
76
+
77
+ def initialize(&block)
78
+ instance_eval &block
79
+ end
80
+ end
81
+ end
82
+
83
+ def self.type(*variables, &block)
84
+ if block.nil?
85
+ raise 'Atom cannot be parametrized' unless variables.empty?
86
+ atom
87
+ else
88
+ if variables.empty?
89
+ DSL::TypeDefinitionScope.new(ProductVariant.new(nil), &block).new_type
90
+ else
91
+ DSL::TypeDefinitionScope.new(ParametrizedType.new(variables), &block).new_type
92
+ end
93
+ end
94
+ end
95
+
96
+ def self.atom
97
+ Atom.new nil
98
+ end
99
+
100
+ def self.types(&block)
101
+ DSL::OuterShell.new &block
102
+ end
103
+
104
+ end
@@ -0,0 +1,43 @@
1
+ # Copyright 2013 Petr Chalupa <git+algebrick@pitr.ch>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Algebrick
16
+ module FieldMethodReaders
17
+ def field_names
18
+ @field_names or raise TypeError, "field names not defined on #{self}"
19
+ end
20
+
21
+ def field_names?
22
+ !!@field_names
23
+ end
24
+
25
+ def add_field_method_reader(field)
26
+ raise TypeError, 'no field names' unless field_names?
27
+ raise ArgumentError, "no field name #{field}" unless field_names.include? field
28
+ raise ArgumentError, "method #{field} already defined" if instance_methods.include? field
29
+ define_method(field) { self[field] }
30
+ self
31
+ end
32
+
33
+ def add_field_method_readers(*fields)
34
+ fields.each { |f| add_field_method_reader f }
35
+ self
36
+ end
37
+
38
+ def add_all_field_method_readers
39
+ add_field_method_readers *field_names
40
+ self
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,45 @@
1
+ # Copyright 2013 Petr Chalupa <git+algebrick@pitr.ch>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Algebrick
16
+ module MatcherDelegations
17
+ def ~
18
+ ~to_m
19
+ end
20
+
21
+ def &(other)
22
+ to_m & other
23
+ end
24
+
25
+ def |(other)
26
+ to_m | other
27
+ end
28
+
29
+ def !
30
+ !to_m
31
+ end
32
+
33
+ def case(&block)
34
+ to_m.case &block
35
+ end
36
+
37
+ def >>(block)
38
+ to_m >> block
39
+ end
40
+
41
+ def >(block)
42
+ to_m > block
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,127 @@
1
+ # Copyright 2013 Petr Chalupa <git+algebrick@pitr.ch>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Algebrick
16
+ module Matchers
17
+ class Abstract
18
+ include TypeCheck
19
+ attr_reader :value
20
+
21
+ def initialize
22
+ @assign, @value, @matched = nil
23
+ end
24
+
25
+ def case(&block)
26
+ return self, block
27
+ end
28
+
29
+ alias_method :when, :case
30
+
31
+ def >(block)
32
+ return self, block
33
+ end
34
+
35
+ alias_method :>>, :>
36
+
37
+ def ~
38
+ @assign = true
39
+ self
40
+ end
41
+
42
+ def &(matcher)
43
+ And.new self, matcher
44
+ end
45
+
46
+ def |(matcher)
47
+ Or.new self, matcher
48
+ end
49
+
50
+ def !
51
+ Not.new self
52
+ end
53
+
54
+ def assign?
55
+ @assign
56
+ end
57
+
58
+ def matched?
59
+ @matched
60
+ end
61
+
62
+ def children_including_self
63
+ children.unshift self
64
+ end
65
+
66
+ def assigns
67
+ collect_assigns.tap do
68
+ return yield *assigns if block_given?
69
+ end
70
+ end
71
+
72
+ def to_a
73
+ assigns
74
+ end
75
+
76
+ def ===(other)
77
+ matching?(other).tap { |matched| @value = other if (@matched = matched) }
78
+ end
79
+
80
+ def assign_to_s
81
+ assign? ? '~' : ''
82
+ end
83
+
84
+ def inspect
85
+ to_s
86
+ end
87
+
88
+ def children
89
+ raise NotImplementedError
90
+ end
91
+
92
+ def to_s
93
+ raise NotImplementedError
94
+ end
95
+
96
+ def ==(other)
97
+ raise NotImplementedError
98
+ end
99
+
100
+ # TODO pretty_print for all matchers
101
+
102
+ protected
103
+
104
+ def matching?(other)
105
+ raise NotImplementedError
106
+ end
107
+
108
+ private
109
+
110
+ def collect_assigns
111
+ mine = @assign ? [@value] : []
112
+ children.inject(mine) { |assigns, child| assigns + child.assigns }
113
+ end
114
+
115
+ def matchable!(obj)
116
+ raise ArgumentError, 'object does not respond to :===' unless obj.respond_to? :===
117
+ obj
118
+ end
119
+
120
+ def find_children(collection)
121
+ collection.map do |matcher|
122
+ matcher if matcher.kind_of? Abstract
123
+ end.compact
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,38 @@
1
+ # Copyright 2013 Petr Chalupa <git+algebrick@pitr.ch>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Algebrick
16
+ module Matchers
17
+ class AbstractLogic < Abstract
18
+ def self.call(*matchers)
19
+ new *matchers
20
+ end
21
+
22
+ attr_reader :matchers
23
+
24
+ def initialize(*matchers)
25
+ @matchers = matchers.each { |m| matchable! m }
26
+ end
27
+
28
+ def children
29
+ find_children matchers
30
+ end
31
+
32
+ def ==(other)
33
+ other.kind_of? self.class and
34
+ self.matchers == other.matchers
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,29 @@
1
+ # Copyright 2013 Petr Chalupa <git+algebrick@pitr.ch>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Algebrick
16
+ module Matchers
17
+ class And < AbstractLogic
18
+ def to_s
19
+ matchers.join ' & '
20
+ end
21
+
22
+ protected
23
+
24
+ def matching?(other)
25
+ matchers.all? { |m| m === other }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright 2013 Petr Chalupa <git+algebrick@pitr.ch>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Algebrick
16
+ module Matchers
17
+ class Any < Abstract
18
+ def children
19
+ []
20
+ end
21
+
22
+ def to_s
23
+ assign_to_s + 'any'
24
+ end
25
+
26
+ def ==(other)
27
+ other.kind_of? self.class
28
+ end
29
+
30
+ protected
31
+
32
+ def matching?(other)
33
+ true
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,57 @@
1
+ # Copyright 2013 Petr Chalupa <git+algebrick@pitr.ch>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Algebrick
16
+ module Matchers
17
+ class Array < Abstract
18
+ def self.call(*matchers)
19
+ new *matchers
20
+ end
21
+
22
+ attr_reader :matchers
23
+
24
+ def initialize(*matchers)
25
+ super()
26
+ @matchers = matchers
27
+ end
28
+
29
+ def children
30
+ find_children @matchers
31
+ end
32
+
33
+ def to_s
34
+ "#{assign_to_s}#{"Array.(#{matchers.join(',')})" if matchers}"
35
+ end
36
+
37
+ def ==(other)
38
+ other.kind_of? self.class and
39
+ self.matchers == other.matchers
40
+ end
41
+
42
+ protected
43
+
44
+ def matching?(other)
45
+ other.kind_of? ::Array and
46
+ matchers.size == other.size and
47
+ matchers.each_with_index.all? { |m, i| m === other[i] }
48
+ end
49
+ end
50
+
51
+ class ::Array
52
+ def self.call(*matchers)
53
+ Matchers::Array.new *matchers
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,28 @@
1
+ # Copyright 2013 Petr Chalupa <git+algebrick@pitr.ch>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Algebrick
16
+ module Matchers
17
+ class Atom < Wrapper
18
+ def initialize(something)
19
+ Type! something, Algebrick::Atom
20
+ super something
21
+ end
22
+
23
+ def to_s
24
+ assign_to_s + "#{@something.name}.to_m"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,44 @@
1
+ # Copyright 2013 Petr Chalupa <git+algebrick@pitr.ch>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Algebrick
16
+ module Matchers
17
+ class Not < Abstract
18
+ attr_reader :matcher
19
+
20
+ def initialize(matcher)
21
+ @matcher = matcher
22
+ end
23
+
24
+ def children
25
+ []
26
+ end
27
+
28
+ def to_s
29
+ '!' + matcher.to_s
30
+ end
31
+
32
+ def ==(other)
33
+ other.kind_of? self.class and
34
+ self.matcher == other.matcher
35
+ end
36
+
37
+ protected
38
+
39
+ def matching?(other)
40
+ not matcher === other
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,51 @@
1
+ # Copyright 2013 Petr Chalupa <git+algebrick@pitr.ch>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Algebrick
16
+ module Matchers
17
+ #noinspection RubyClassModuleNamingConvention
18
+ class Or < AbstractLogic
19
+ def to_s
20
+ matchers.join ' | '
21
+ end
22
+
23
+ protected
24
+
25
+ def matching?(other)
26
+ matchers.any? { |m| m === other }
27
+ end
28
+
29
+ alias_method :super_children, :children
30
+ private :super_children
31
+
32
+ def children
33
+ super.select &:matched?
34
+ end
35
+
36
+ private
37
+
38
+ def collect_assigns
39
+ super.tap do |assigns|
40
+ missing = assigns_size - assigns.size
41
+ assigns.push(*::Array.new(missing))
42
+ end
43
+ end
44
+
45
+ def assigns_size
46
+ # TODO is it efficient?
47
+ super_children.map { |ch| ch.assigns.size }.max
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,73 @@
1
+ # Copyright 2013 Petr Chalupa <git+algebrick@pitr.ch>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Algebrick
16
+ module Matchers
17
+ class Product < Abstract
18
+ attr_reader :algebraic_type, :field_matchers
19
+
20
+ def initialize(algebraic_type, *field_matchers)
21
+ super()
22
+ @algebraic_type = Type! algebraic_type, Algebrick::ProductVariant, Algebrick::ParametrizedType
23
+ raise ArgumentError unless algebraic_type.fields
24
+ @field_matchers = case
25
+
26
+ # AProduct.()
27
+ when field_matchers.empty?
28
+ ::Array.new(algebraic_type.fields.size) { Algebrick.any }
29
+
30
+ # AProduct.(field_name: a_matcher)
31
+ when field_matchers.size == 1 && field_matchers.first.is_a?(Hash)
32
+ field_matchers = field_matchers.first
33
+ unless (dif = field_matchers.keys - algebraic_type.field_names).empty?
34
+ raise ArgumentError, "no #{dif} fields in #{algebraic_type}"
35
+ end
36
+ algebraic_type.field_names.map do |field|
37
+ field_matchers.key?(field) ? field_matchers[field] : Algebrick.any
38
+ end
39
+
40
+ # normal
41
+ else
42
+ field_matchers
43
+ end
44
+ unless algebraic_type.fields.size == @field_matchers.size
45
+ raise ArgumentError
46
+ end
47
+ end
48
+
49
+ def children
50
+ find_children @field_matchers
51
+ end
52
+
53
+ def to_s
54
+ assign_to_s + "#{@algebraic_type.name}.(#{@field_matchers.join(', ')})"
55
+ end
56
+
57
+ def ==(other)
58
+ other.kind_of? self.class and
59
+ self.algebraic_type == other.algebraic_type and
60
+ self.field_matchers == other.field_matchers
61
+ end
62
+
63
+ protected
64
+
65
+ def matching?(other)
66
+ other.kind_of?(@algebraic_type) and other.kind_of?(ProductConstructors::Abstract) and
67
+ @field_matchers.zip(other.fields).all? do |matcher, field|
68
+ matcher === field
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end