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.
- 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
|