algebrick 0.4.0 → 0.5.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.
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