algebrick 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -3
- data/README_FULL.md +13 -21
- data/VERSION +1 -1
- data/doc/actor.rb +21 -0
- data/doc/data.in.rb +99 -0
- data/doc/data.out.rb +103 -0
- data/doc/extending_behavior.in.rb +61 -0
- data/doc/extending_behavior.out.rb +62 -0
- data/doc/format.rb +75 -0
- data/doc/init.rb +1 -0
- data/doc/json.in.rb +39 -0
- data/doc/json.out.rb +43 -0
- data/doc/null.in.rb +36 -0
- data/doc/null.out.rb +40 -0
- data/doc/parametrized.in.rb +37 -0
- data/doc/parametrized.out.rb +41 -0
- data/doc/pattern_matching.in.rb +116 -0
- data/doc/pattern_matching.out.rb +122 -0
- data/doc/quick_example.in.rb +27 -0
- data/doc/quick_example.out.rb +27 -0
- data/doc/tree1.in.rb +10 -0
- data/doc/tree1.out.rb +10 -0
- data/doc/type_def.in.rb +21 -0
- data/doc/type_def.out.rb +21 -0
- data/doc/values.in.rb +52 -0
- data/doc/values.out.rb +58 -0
- data/lib/algebrick/atom.rb +49 -0
- data/lib/algebrick/dsl.rb +104 -0
- data/lib/algebrick/field_method_readers.rb +43 -0
- data/lib/algebrick/matcher_delegations.rb +45 -0
- data/lib/algebrick/matchers/abstract.rb +127 -0
- data/lib/algebrick/matchers/abstract_logic.rb +38 -0
- data/lib/algebrick/matchers/and.rb +29 -0
- data/lib/algebrick/matchers/any.rb +37 -0
- data/lib/algebrick/matchers/array.rb +57 -0
- data/lib/algebrick/matchers/atom.rb +28 -0
- data/lib/algebrick/matchers/not.rb +44 -0
- data/lib/algebrick/matchers/or.rb +51 -0
- data/lib/algebrick/matchers/product.rb +73 -0
- data/lib/algebrick/matchers/variant.rb +29 -0
- data/lib/algebrick/matchers/wrapper.rb +57 -0
- data/lib/algebrick/matchers.rb +31 -0
- data/lib/algebrick/matching.rb +62 -0
- data/lib/algebrick/parametrized_type.rb +122 -0
- data/lib/algebrick/product_constructors/abstract.rb +70 -0
- data/lib/algebrick/product_constructors/basic.rb +47 -0
- data/lib/algebrick/product_constructors/named.rb +58 -0
- data/lib/algebrick/product_constructors.rb +25 -0
- data/lib/algebrick/product_variant.rb +195 -0
- data/lib/algebrick/reclude.rb +39 -0
- data/lib/algebrick/serializer.rb +129 -0
- data/lib/algebrick/serializers.rb +25 -0
- data/lib/algebrick/type.rb +61 -0
- data/lib/algebrick/type_check.rb +58 -0
- data/lib/algebrick/types.rb +59 -0
- data/lib/algebrick/value.rb +41 -0
- data/lib/algebrick.rb +14 -1170
- data/spec/algebrick_test.rb +708 -0
- 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
|