fear 1.2.0 → 2.0.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/.github/dependabot.yml +27 -0
- data/.github/workflows/rubocop.yml +2 -2
- data/.github/workflows/spec.yml +1 -1
- data/CHANGELOG.md +13 -0
- data/Gemfile.lock +53 -56
- data/README.md +54 -186
- data/Rakefile +0 -21
- data/examples/pattern_extracting.rb +4 -4
- data/fear.gemspec +2 -4
- data/lib/fear/either.rb +8 -4
- data/lib/fear/either_api.rb +2 -0
- data/lib/fear/either_pattern_match.rb +7 -8
- data/lib/fear/failure.rb +0 -9
- data/lib/fear/failure_pattern_match.rb +2 -0
- data/lib/fear/for_api.rb +2 -0
- data/lib/fear/future.rb +12 -20
- data/lib/fear/future_api.rb +13 -2
- data/lib/fear/left.rb +0 -9
- data/lib/fear/none.rb +7 -9
- data/lib/fear/option.rb +5 -1
- data/lib/fear/option_api.rb +2 -0
- data/lib/fear/option_pattern_match.rb +6 -4
- data/lib/fear/partial_function/empty.rb +2 -0
- data/lib/fear/partial_function/guard.rb +4 -4
- data/lib/fear/partial_function/or_else.rb +2 -0
- data/lib/fear/partial_function.rb +9 -8
- data/lib/fear/pattern_match.rb +0 -10
- data/lib/fear/pattern_matching_api.rb +3 -28
- data/lib/fear/promise.rb +3 -9
- data/lib/fear/right.rb +0 -10
- data/lib/fear/right_biased.rb +1 -1
- data/lib/fear/right_pattern_match.rb +2 -0
- data/lib/fear/some.rb +7 -10
- data/lib/fear/struct.rb +3 -14
- data/lib/fear/success.rb +0 -9
- data/lib/fear/success_pattern_match.rb +2 -0
- data/lib/fear/try.rb +6 -2
- data/lib/fear/try_api.rb +2 -0
- data/lib/fear/try_pattern_match.rb +7 -8
- data/lib/fear/utils.rb +0 -3
- data/lib/fear/version.rb +1 -1
- data/lib/fear.rb +8 -42
- data/spec/fear/awaitable_spec.rb +2 -0
- data/spec/fear/either_spec.rb +26 -0
- data/spec/fear/failure_spec.rb +8 -23
- data/spec/fear/for/mixin_spec.rb +15 -0
- data/spec/fear/future_spec.rb +17 -2
- data/spec/fear/guard_spec.rb +110 -0
- data/spec/fear/left_spec.rb +7 -22
- data/spec/fear/none_spec.rb +11 -17
- data/spec/fear/option_spec.rb +15 -1
- data/spec/fear/partial_function/any_spec.rb +25 -0
- data/spec/fear/partial_function_spec.rb +2 -24
- data/spec/fear/pattern_match_spec.rb +0 -34
- data/spec/fear/promise_spec.rb +4 -6
- data/spec/fear/right_spec.rb +0 -22
- data/spec/fear/some_spec.rb +10 -22
- data/spec/fear/success_spec.rb +0 -22
- data/spec/fear/try/mixin_spec.rb +14 -0
- data/spec/fear/try_api_spec.rb +23 -0
- data/spec/struct_spec.rb +1 -33
- metadata +18 -80
- data/examples/pattern_extracting_ruby2.7.rb +0 -15
- data/lib/fear/extractor/anonymous_array_splat_matcher.rb +0 -10
- data/lib/fear/extractor/any_matcher.rb +0 -17
- data/lib/fear/extractor/array_head_matcher.rb +0 -36
- data/lib/fear/extractor/array_matcher.rb +0 -40
- data/lib/fear/extractor/array_splat_matcher.rb +0 -16
- data/lib/fear/extractor/empty_list_matcher.rb +0 -20
- data/lib/fear/extractor/extractor_matcher.rb +0 -44
- data/lib/fear/extractor/grammar.rb +0 -203
- data/lib/fear/extractor/grammar.treetop +0 -129
- data/lib/fear/extractor/identifier_matcher.rb +0 -18
- data/lib/fear/extractor/matcher/and.rb +0 -38
- data/lib/fear/extractor/matcher.rb +0 -53
- data/lib/fear/extractor/named_array_splat_matcher.rb +0 -17
- data/lib/fear/extractor/pattern.rb +0 -58
- data/lib/fear/extractor/typed_identifier_matcher.rb +0 -26
- data/lib/fear/extractor/value_matcher.rb +0 -19
- data/lib/fear/extractor.rb +0 -112
- data/lib/fear/extractor_api.rb +0 -35
- data/spec/fear/extractor/array_matcher_spec.rb +0 -230
- data/spec/fear/extractor/extractor_matcher_spec.rb +0 -153
- data/spec/fear/extractor/grammar_array_spec.rb +0 -25
- data/spec/fear/extractor/identified_matcher_spec.rb +0 -49
- data/spec/fear/extractor/identifier_matcher_spec.rb +0 -68
- data/spec/fear/extractor/pattern_spec.rb +0 -34
- data/spec/fear/extractor/typed_identifier_matcher_spec.rb +0 -64
- data/spec/fear/extractor/value_matcher_number_spec.rb +0 -79
- data/spec/fear/extractor/value_matcher_string_spec.rb +0 -88
- data/spec/fear/extractor/value_matcher_symbol_spec.rb +0 -71
- data/spec/fear/extractor_api_spec.rb +0 -115
- data/spec/fear/extractor_spec.rb +0 -61
data/lib/fear/extractor_api.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Fear
|
4
|
-
module ExtractorApi
|
5
|
-
# Allows to pattern match and extract matcher variables
|
6
|
-
#
|
7
|
-
# @param pattern [String]
|
8
|
-
# @return [Extractor::Pattern]
|
9
|
-
# @note it is not intended to be used by itself, rather then with partial functions
|
10
|
-
def [](pattern)
|
11
|
-
Extractor::Pattern.new(pattern)
|
12
|
-
end
|
13
|
-
|
14
|
-
# Register extractor for given class
|
15
|
-
# @!method register_extractor(*names, extractor)
|
16
|
-
# @param names [<Class, String>, Class, String] name of a class. You can also pass alias for the name
|
17
|
-
# @param extractor [Proc<any => Fear::Option>] proc taking any argument and returned Option
|
18
|
-
# of extracted value('s)
|
19
|
-
#
|
20
|
-
# @example
|
21
|
-
# register_extractor(Fear::Some, Fear.case(Fear::Some) { |some| some.get }.lift)
|
22
|
-
#
|
23
|
-
# register_extractor(User, Fear.case(User) { |user|} [user.id, user.email] , )
|
24
|
-
#
|
25
|
-
# @example registering an alias. Alias should be CamelCased string
|
26
|
-
# register_extractor(Fear::Some, 'Some', Fear.case(Fear::Some) { |some| some.get }.lift)
|
27
|
-
#
|
28
|
-
# # no you can extract Fear::Some's using Some alias
|
29
|
-
# m.case(Fear['Some(value : Integer)']) { |value:| value * 2 }
|
30
|
-
#
|
31
|
-
def register_extractor(*args)
|
32
|
-
Extractor.register_extractor(*args)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,230 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe Fear::Extractor::ArrayMatcher do
|
4
|
-
let(:parser) { Fear::Extractor::GrammarParser.new }
|
5
|
-
let(:matcher) { parser.parse(pattern).to_matcher }
|
6
|
-
|
7
|
-
describe "#defined_at?" do
|
8
|
-
subject { matcher }
|
9
|
-
|
10
|
-
context "empty array" do
|
11
|
-
let(:pattern) { "[]" }
|
12
|
-
|
13
|
-
it { is_expected.to be_defined_at([]) }
|
14
|
-
it { is_expected.not_to be_defined_at([1]) }
|
15
|
-
end
|
16
|
-
|
17
|
-
context "empty array with splat" do
|
18
|
-
let(:pattern) { "[*]" }
|
19
|
-
|
20
|
-
it { is_expected.to be_defined_at([]) }
|
21
|
-
it { is_expected.to be_defined_at([1]) }
|
22
|
-
it { is_expected.to be_defined_at([1, 2]) }
|
23
|
-
end
|
24
|
-
|
25
|
-
context "empty array with named splat" do
|
26
|
-
let(:pattern) { "[*var]" }
|
27
|
-
|
28
|
-
it { is_expected.to be_defined_at([]) }
|
29
|
-
it { is_expected.to be_defined_at([1]) }
|
30
|
-
it { is_expected.to be_defined_at([1, 2]) }
|
31
|
-
end
|
32
|
-
|
33
|
-
context "one element array" do
|
34
|
-
let(:pattern) { "[1]" }
|
35
|
-
|
36
|
-
it { is_expected.not_to be_defined_at([]) }
|
37
|
-
it { is_expected.to be_defined_at([1]) }
|
38
|
-
it { is_expected.not_to be_defined_at([1, 2]) }
|
39
|
-
it { is_expected.not_to be_defined_at([2, 1]) }
|
40
|
-
|
41
|
-
context "identifier" do
|
42
|
-
let(:pattern) { "[var]" }
|
43
|
-
|
44
|
-
it { is_expected.not_to be_defined_at([]) }
|
45
|
-
it { is_expected.to be_defined_at([1]) }
|
46
|
-
it { is_expected.to be_defined_at([[1]]) }
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
context "two elements array with nested matcher" do
|
51
|
-
let(:pattern) { "[[1, *], 1]" }
|
52
|
-
|
53
|
-
it { is_expected.not_to be_defined_at([]) }
|
54
|
-
it { is_expected.to be_defined_at([[1], 1]) }
|
55
|
-
it { is_expected.to be_defined_at([[1, 2], 1]) }
|
56
|
-
it { is_expected.not_to be_defined_at([[1, 2], 2]) }
|
57
|
-
it { is_expected.not_to be_defined_at([2, 1]) }
|
58
|
-
end
|
59
|
-
|
60
|
-
context "one element array with splat" do
|
61
|
-
let(:pattern) { "[1, *]" }
|
62
|
-
|
63
|
-
it { is_expected.not_to be_defined_at([]) }
|
64
|
-
it { is_expected.to be_defined_at([1]) }
|
65
|
-
it { is_expected.to be_defined_at([1, 2]) }
|
66
|
-
it { is_expected.to be_defined_at([1, 2, 3]) }
|
67
|
-
it { is_expected.not_to be_defined_at([2, 1]) }
|
68
|
-
end
|
69
|
-
|
70
|
-
context "one element array with named splat" do
|
71
|
-
let(:pattern) { "[1, *var]" }
|
72
|
-
|
73
|
-
it { is_expected.not_to be_defined_at([]) }
|
74
|
-
it { is_expected.to be_defined_at([1]) }
|
75
|
-
it { is_expected.to be_defined_at([1, 2]) }
|
76
|
-
it { is_expected.to be_defined_at([1, 2, 3]) }
|
77
|
-
it { is_expected.not_to be_defined_at([2, 1]) }
|
78
|
-
end
|
79
|
-
|
80
|
-
context "three elements array" do
|
81
|
-
context "with identifier in the middle" do
|
82
|
-
let(:pattern) { "[1, var, 2]" }
|
83
|
-
|
84
|
-
it { is_expected.not_to be_defined_at([]) }
|
85
|
-
it { is_expected.to be_defined_at([1, 3, 2]) }
|
86
|
-
it { is_expected.not_to be_defined_at([1, 2, 3]) }
|
87
|
-
it { is_expected.not_to be_defined_at([1, 2, 3, 4]) }
|
88
|
-
it { is_expected.not_to be_defined_at([1]) }
|
89
|
-
it { is_expected.not_to be_defined_at([2]) }
|
90
|
-
end
|
91
|
-
|
92
|
-
context "head and tail" do
|
93
|
-
let(:pattern) { "[head, *tail]" }
|
94
|
-
|
95
|
-
it { is_expected.not_to be_defined_at([]) }
|
96
|
-
it { is_expected.to be_defined_at([1, 3, 2]) }
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
context "two element array" do
|
101
|
-
let(:pattern) { "[ 1, 2 ]" }
|
102
|
-
|
103
|
-
it { is_expected.not_to be_defined_at([]) }
|
104
|
-
it { is_expected.to be_defined_at([1, 2]) }
|
105
|
-
it { is_expected.not_to be_defined_at([1]) }
|
106
|
-
it { is_expected.not_to be_defined_at([2]) }
|
107
|
-
it { is_expected.not_to be_defined_at([1, 3]) }
|
108
|
-
it { is_expected.not_to be_defined_at([2, 2]) }
|
109
|
-
it { is_expected.not_to be_defined_at([1, 2, 3]) }
|
110
|
-
|
111
|
-
context "with identifier at the beginning" do
|
112
|
-
let(:pattern) { "[var, 2]" }
|
113
|
-
|
114
|
-
it { is_expected.not_to be_defined_at([]) }
|
115
|
-
it { is_expected.to be_defined_at([1, 2]) }
|
116
|
-
it { is_expected.not_to be_defined_at([1, 3]) }
|
117
|
-
it { is_expected.not_to be_defined_at([1]) }
|
118
|
-
it { is_expected.not_to be_defined_at([2]) }
|
119
|
-
it { is_expected.not_to be_defined_at([1, 2, 3]) }
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
describe "#call" do
|
125
|
-
subject { matcher.(other) }
|
126
|
-
|
127
|
-
context "on the same array" do
|
128
|
-
let(:other) { [1] }
|
129
|
-
let(:pattern) { "[1]" }
|
130
|
-
|
131
|
-
it { is_expected.to eq({}) }
|
132
|
-
end
|
133
|
-
|
134
|
-
context "with splat on another array" do
|
135
|
-
let(:other) { [2, 1] }
|
136
|
-
let(:pattern) { "[2, *]" }
|
137
|
-
|
138
|
-
it { is_expected.to eq({}) }
|
139
|
-
end
|
140
|
-
|
141
|
-
context "with identifier at the middle of an array" do
|
142
|
-
let(:other) { [2, 1, 3] }
|
143
|
-
let(:pattern) { "[2, var, 3]" }
|
144
|
-
|
145
|
-
it { is_expected.to eq(var: 1) }
|
146
|
-
end
|
147
|
-
|
148
|
-
context "with identifier at the end of an array" do
|
149
|
-
let(:other) { [2, 1, 3] }
|
150
|
-
let(:pattern) { "[2, 1, var]" }
|
151
|
-
|
152
|
-
it { is_expected.to eq(var: 3) }
|
153
|
-
end
|
154
|
-
|
155
|
-
context "with named splat matching all the array" do
|
156
|
-
let(:other) { [2, 1, 3, 4] }
|
157
|
-
let(:pattern) { "[*var]" }
|
158
|
-
|
159
|
-
it { is_expected.to eq(var: [2, 1, 3, 4]) }
|
160
|
-
end
|
161
|
-
|
162
|
-
context "with named splat matching tail of an array" do
|
163
|
-
let(:other) { [2, 1, 3, 4] }
|
164
|
-
let(:pattern) { "[2, 1, *var]" }
|
165
|
-
|
166
|
-
it { is_expected.to eq(var: [3, 4]) }
|
167
|
-
end
|
168
|
-
|
169
|
-
context "with named splat at the end of an array" do
|
170
|
-
let(:other) { [2, 1] }
|
171
|
-
let(:pattern) { "[2, 1, *var]" }
|
172
|
-
|
173
|
-
it { is_expected.to eq(var: []) }
|
174
|
-
end
|
175
|
-
|
176
|
-
context "with several identifiers in an array" do
|
177
|
-
let(:other) { [2, 1, 3] }
|
178
|
-
let(:pattern) { "[a, 1, b]" }
|
179
|
-
|
180
|
-
it { is_expected.to eq(a: 2, b: 3) }
|
181
|
-
end
|
182
|
-
|
183
|
-
context "head and tail" do
|
184
|
-
let(:other) { [2, 1, 3] }
|
185
|
-
let(:pattern) { "[head, *tail]" }
|
186
|
-
|
187
|
-
it { is_expected.to eq(head: 2, tail: [1, 3]) }
|
188
|
-
end
|
189
|
-
|
190
|
-
context "ignore head, capture tail" do
|
191
|
-
let(:other) { [2, 1, 3] }
|
192
|
-
let(:pattern) { "[_, *tail]" }
|
193
|
-
|
194
|
-
it { is_expected.to eq(tail: [1, 3]) }
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
describe "#failure_reason" do
|
199
|
-
subject { matcher.failure_reason(other) }
|
200
|
-
|
201
|
-
context "on the same array" do
|
202
|
-
let(:other) { [1] }
|
203
|
-
let(:pattern) { "[1]" }
|
204
|
-
|
205
|
-
it { is_expected.to eq(Fear.none) }
|
206
|
-
end
|
207
|
-
|
208
|
-
context "on another array" do
|
209
|
-
let(:other) { [2, 1] }
|
210
|
-
let(:pattern) { "[2, 2]" }
|
211
|
-
|
212
|
-
it { is_expected.to eq(Fear.some(<<~ERROR.strip)) }
|
213
|
-
Expected `1` to match:
|
214
|
-
[2, 2]
|
215
|
-
~~~~^
|
216
|
-
ERROR
|
217
|
-
end
|
218
|
-
|
219
|
-
context "element type mismatch" do
|
220
|
-
let(:other) { [2, 1] }
|
221
|
-
let(:pattern) { "[[2], 1]" }
|
222
|
-
|
223
|
-
it { is_expected.to eq(Fear.some(<<~ERROR.strip)) }
|
224
|
-
Expected `2` to match:
|
225
|
-
[[2], 1]
|
226
|
-
~~^
|
227
|
-
ERROR
|
228
|
-
end
|
229
|
-
end
|
230
|
-
end
|
@@ -1,153 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe Fear::Extractor::ExtractorMatcher do
|
4
|
-
let(:parser) { Fear::Extractor::GrammarParser.new }
|
5
|
-
let(:matcher) { parser.parse(pattern).to_matcher }
|
6
|
-
|
7
|
-
describe "#defined_at?" do
|
8
|
-
subject { matcher }
|
9
|
-
|
10
|
-
context "boolean extractor" do
|
11
|
-
let(:pattern) { "IsEven()" }
|
12
|
-
|
13
|
-
it { is_expected.to be_defined_at(42) }
|
14
|
-
it { is_expected.not_to be_defined_at(43) }
|
15
|
-
it { is_expected.not_to be_defined_at("foo") }
|
16
|
-
end
|
17
|
-
|
18
|
-
context "single argument extractor" do
|
19
|
-
let(:pattern) { "Fear::Some(a : Integer)" }
|
20
|
-
|
21
|
-
it { is_expected.to be_defined_at(Fear.some(42)) }
|
22
|
-
it { is_expected.not_to be_defined_at("foo") }
|
23
|
-
it { is_expected.not_to be_defined_at(Fear.some("foo")) }
|
24
|
-
end
|
25
|
-
|
26
|
-
context "single argument extractor with array as an argument" do
|
27
|
-
let(:pattern) { "Fear::Some([1, 2])" }
|
28
|
-
|
29
|
-
it { is_expected.to be_defined_at(Fear.some([1, 2])) }
|
30
|
-
it { is_expected.not_to be_defined_at(Fear.some([1, 1])) }
|
31
|
-
it { is_expected.not_to be_defined_at(Fear.some("foo")) }
|
32
|
-
end
|
33
|
-
|
34
|
-
context "multiple arguments extractor" do
|
35
|
-
let(:pattern) { "Date(2017, month, _)" }
|
36
|
-
|
37
|
-
it { is_expected.to be_defined_at(Date.parse("2017-02-15")) }
|
38
|
-
it { is_expected.not_to be_defined_at(Date.parse("2018-02-15")) }
|
39
|
-
it { is_expected.not_to be_defined_at("foo") }
|
40
|
-
end
|
41
|
-
|
42
|
-
context "Struct" do
|
43
|
-
StructDate = ::Struct.new(:year, :month, :day)
|
44
|
-
|
45
|
-
let(:pattern) { "StructDate(2017, month, _)" }
|
46
|
-
|
47
|
-
it { is_expected.to be_defined_at(StructDate.new(2017, 2, 15)) }
|
48
|
-
it { is_expected.not_to be_defined_at(StructDate.new(2018, 2, 15)) }
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
describe "#call" do
|
53
|
-
subject { matcher.(other) }
|
54
|
-
|
55
|
-
context "single argument extractor" do
|
56
|
-
let(:pattern) { "Fear::Some(a : Integer)" }
|
57
|
-
let(:other) { Fear.some(42) }
|
58
|
-
|
59
|
-
it { is_expected.to eq(a: 42) }
|
60
|
-
end
|
61
|
-
|
62
|
-
context "multiple arguments extractor" do
|
63
|
-
let(:pattern) { "Date(2017, month, day)" }
|
64
|
-
let(:other) { Date.parse("2017-02-15") }
|
65
|
-
|
66
|
-
it { is_expected.to eq(month: 2, day: 15) }
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe "#failure_reason" do
|
71
|
-
subject { matcher.failure_reason(other) }
|
72
|
-
|
73
|
-
context "no argument extractor" do
|
74
|
-
let(:pattern) { "IsEven()" }
|
75
|
-
|
76
|
-
context "defined" do
|
77
|
-
let(:other) { 42 }
|
78
|
-
|
79
|
-
it { is_expected.to eq(Fear.none) }
|
80
|
-
end
|
81
|
-
|
82
|
-
context "not defined" do
|
83
|
-
let(:other) { 43 }
|
84
|
-
|
85
|
-
it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
|
86
|
-
Expected `43` to match:
|
87
|
-
IsEven()
|
88
|
-
^
|
89
|
-
MSG
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
context "single argument extractor" do
|
94
|
-
let(:pattern) { "Fear::Some(a : Integer)" }
|
95
|
-
|
96
|
-
context "defined" do
|
97
|
-
let(:other) { Fear.some(42) }
|
98
|
-
|
99
|
-
it { is_expected.to eq(Fear.none) }
|
100
|
-
end
|
101
|
-
|
102
|
-
context "not defined" do
|
103
|
-
let(:other) { Fear.some("42") }
|
104
|
-
|
105
|
-
it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
|
106
|
-
Expected `"42"` to match:
|
107
|
-
Fear::Some(a : Integer)
|
108
|
-
~~~~~~~~~~~~~~~^
|
109
|
-
MSG
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
context "single argument extractor, array argument" do
|
114
|
-
let(:pattern) { "Fear::Some([1, 2])" }
|
115
|
-
|
116
|
-
context "defined" do
|
117
|
-
let(:other) { Fear.some([1, 2]) }
|
118
|
-
|
119
|
-
it { is_expected.to eq(Fear.none) }
|
120
|
-
end
|
121
|
-
|
122
|
-
context "not defined" do
|
123
|
-
let(:other) { Fear.some([1, 1]) }
|
124
|
-
|
125
|
-
it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
|
126
|
-
Expected `1` to match:
|
127
|
-
Fear::Some([1, 2])
|
128
|
-
~~~~~~~~~~~~~~~^
|
129
|
-
MSG
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
context "multiple arguments extractor" do
|
134
|
-
let(:pattern) { "Date(year, 02, day)" }
|
135
|
-
|
136
|
-
context "defined" do
|
137
|
-
let(:other) { Date.parse("2017-02-15") }
|
138
|
-
|
139
|
-
it { is_expected.to eq(Fear.none) }
|
140
|
-
end
|
141
|
-
|
142
|
-
context "not defined" do
|
143
|
-
let(:other) { Date.parse("2017-04-15") }
|
144
|
-
|
145
|
-
it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
|
146
|
-
Expected `4` to match:
|
147
|
-
Date(year, 02, day)
|
148
|
-
~~~~~~~~~~~^
|
149
|
-
MSG
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe Fear::Extractor::Grammar, "Array" do
|
4
|
-
let(:parser) { Fear::Extractor::GrammarParser.new }
|
5
|
-
let(:matcher) { parser.parse(pattern).to_matcher }
|
6
|
-
|
7
|
-
context "non empty array" do
|
8
|
-
let(:pattern) { "[1, 2, 3, 4]" }
|
9
|
-
|
10
|
-
it do
|
11
|
-
first = matcher.head
|
12
|
-
rest_after_first = matcher.tail
|
13
|
-
|
14
|
-
expect(first).to be_kind_of(Fear::Extractor::ArrayHeadMatcher)
|
15
|
-
expect(first.matcher.value).to eq(1)
|
16
|
-
expect(rest_after_first).to be_kind_of(Fear::Extractor::ArrayMatcher)
|
17
|
-
|
18
|
-
second = rest_after_first.head
|
19
|
-
rest_after_second = rest_after_first.tail
|
20
|
-
expect(second).to be_kind_of(Fear::Extractor::ArrayHeadMatcher)
|
21
|
-
expect(second.matcher.value).to eq(2)
|
22
|
-
expect(rest_after_second).to be_kind_of(Fear::Extractor::ArrayMatcher)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe "Fear::Extractor::IdentifiedMatcher" do
|
4
|
-
let(:parser) { Fear::Extractor::GrammarParser.new }
|
5
|
-
let(:matcher) { parser.parse(pattern).to_matcher }
|
6
|
-
|
7
|
-
describe "#defined_at?" do
|
8
|
-
subject { matcher }
|
9
|
-
|
10
|
-
let(:pattern) { "array @ [1, *tail]" }
|
11
|
-
|
12
|
-
it { is_expected.to be_defined_at([1, 2]) }
|
13
|
-
it { is_expected.not_to be_defined_at("foo") }
|
14
|
-
it { is_expected.not_to be_defined_at([2, 1]) }
|
15
|
-
end
|
16
|
-
|
17
|
-
describe "#call" do
|
18
|
-
subject { matcher.(other) }
|
19
|
-
|
20
|
-
context "defined" do
|
21
|
-
let(:other) { [1, 2] }
|
22
|
-
let(:pattern) { "array @ [1, *tail]" }
|
23
|
-
|
24
|
-
it { is_expected.to eq(array: [1, 2], tail: [2]) }
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe "#failure_reason" do
|
29
|
-
subject { matcher.failure_reason(other) }
|
30
|
-
|
31
|
-
let(:pattern) { "array @ [1, *tail]" }
|
32
|
-
|
33
|
-
context "match integer" do
|
34
|
-
let(:other) { [1, 2] }
|
35
|
-
|
36
|
-
it { is_expected.to eq(Fear.none) }
|
37
|
-
end
|
38
|
-
|
39
|
-
context "does not match float" do
|
40
|
-
let(:other) { [2, 2] }
|
41
|
-
|
42
|
-
it { is_expected.to eq(Fear.some(<<~ERROR.strip)) }
|
43
|
-
Expected `2` to match:
|
44
|
-
array @ [1, *tail]
|
45
|
-
~~~~~~~~~^
|
46
|
-
ERROR
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe Fear::Extractor::IdentifierMatcher do
|
4
|
-
let(:parser) { Fear::Extractor::GrammarParser.new }
|
5
|
-
let(:matcher) { parser.parse(pattern).to_matcher }
|
6
|
-
|
7
|
-
describe "#defined_at?" do
|
8
|
-
subject { matcher }
|
9
|
-
|
10
|
-
let(:pattern) { "number" }
|
11
|
-
|
12
|
-
it { is_expected.to be_defined_at(1) }
|
13
|
-
it { is_expected.to be_defined_at("foo") }
|
14
|
-
it { is_expected.to be_defined_at(1.2) }
|
15
|
-
it { is_expected.to be_defined_at([1, "2"]) }
|
16
|
-
|
17
|
-
context "within array" do
|
18
|
-
let(:pattern) { "[1, n, 2]" }
|
19
|
-
|
20
|
-
it { is_expected.to be_defined_at([1, 2, 2]) }
|
21
|
-
it { is_expected.to be_defined_at([1, "foo", 2]) }
|
22
|
-
it { is_expected.not_to be_defined_at([1, "foo"]) }
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
describe "#call" do
|
27
|
-
subject { matcher.(other) }
|
28
|
-
|
29
|
-
let(:pattern) { "1.0" }
|
30
|
-
|
31
|
-
context "defined" do
|
32
|
-
let(:other) { 1 }
|
33
|
-
|
34
|
-
it { is_expected.to eq({}) }
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe "#failure_reason" do
|
39
|
-
subject { matcher.failure_reason(other) }
|
40
|
-
|
41
|
-
let(:pattern) { "1.0" }
|
42
|
-
|
43
|
-
context "match integer" do
|
44
|
-
let(:other) { 1 }
|
45
|
-
let(:pattern) { "1" }
|
46
|
-
|
47
|
-
it { is_expected.to eq(Fear.none) }
|
48
|
-
end
|
49
|
-
|
50
|
-
context "match float" do
|
51
|
-
let(:other) { 1.0 }
|
52
|
-
let(:pattern) { "1" }
|
53
|
-
|
54
|
-
it { is_expected.to eq(Fear.none) }
|
55
|
-
end
|
56
|
-
|
57
|
-
context "does not match another integer" do
|
58
|
-
let(:other) { 2 }
|
59
|
-
let(:pattern) { "1" }
|
60
|
-
|
61
|
-
it { is_expected.to eq(Fear.some(<<~ERROR.strip)) }
|
62
|
-
Expected `2` to match:
|
63
|
-
1
|
64
|
-
^
|
65
|
-
ERROR
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe Fear::Extractor::Pattern do
|
4
|
-
describe ".new" do
|
5
|
-
context "invalid syntax" do
|
6
|
-
subject { -> { described_class.new("[1, 2, 3") } }
|
7
|
-
|
8
|
-
it "shows where the error happens" do
|
9
|
-
is_expected.to raise_error(Fear::PatternSyntaxError) { |error|
|
10
|
-
lines = error.message.split("\n")
|
11
|
-
expect(lines[0]).to start_with("Expected one of")
|
12
|
-
.and(end_with("at line 1, column 9 (byte 9):"))
|
13
|
-
|
14
|
-
expect(lines[1]).to eq("[1, 2, 3")
|
15
|
-
expect(lines[2]).to eq("~~~~~~~~^")
|
16
|
-
}
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe "#failure_reason" do
|
22
|
-
let(:pattern) { described_class.new("Some([:err, 444])") }
|
23
|
-
|
24
|
-
context "not defined" do
|
25
|
-
subject { pattern.failure_reason(Fear.some([:err, 445])) }
|
26
|
-
|
27
|
-
it { is_expected.to eq(<<~MSG.strip) }
|
28
|
-
Expected `445` to match:
|
29
|
-
Some([:err, 444])
|
30
|
-
~~~~~~~~~~~~^
|
31
|
-
MSG
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe Fear::Extractor::TypedIdentifierMatcher do
|
4
|
-
let(:parser) { Fear::Extractor::GrammarParser.new }
|
5
|
-
let(:matcher) { parser.parse(pattern).to_matcher }
|
6
|
-
|
7
|
-
describe "#defined_at?" do
|
8
|
-
subject { matcher }
|
9
|
-
|
10
|
-
let(:pattern) { "var : Integer" }
|
11
|
-
|
12
|
-
it { is_expected.to be_defined_at(1) }
|
13
|
-
it { is_expected.not_to be_defined_at("foo") }
|
14
|
-
it { is_expected.not_to be_defined_at(1.2) }
|
15
|
-
|
16
|
-
context "within array" do
|
17
|
-
let(:pattern) { "[1, n : String, 2]" }
|
18
|
-
|
19
|
-
it { is_expected.to be_defined_at([1, "foo", 2]) }
|
20
|
-
it { is_expected.not_to be_defined_at([1, 2, 2]) }
|
21
|
-
it { is_expected.not_to be_defined_at([1, "foo"]) }
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
describe "#call" do
|
26
|
-
subject { matcher.(other) }
|
27
|
-
|
28
|
-
context "defined" do
|
29
|
-
let(:other) { 1 }
|
30
|
-
let(:pattern) { "var : Integer" }
|
31
|
-
|
32
|
-
it { is_expected.to eq(var: 1) }
|
33
|
-
end
|
34
|
-
|
35
|
-
context "defined within array" do
|
36
|
-
let(:other) { [4, 2, 1, 6] }
|
37
|
-
let(:pattern) { "[head : Integer, *tail]" }
|
38
|
-
|
39
|
-
it { is_expected.to eq(head: 4, tail: [2, 1, 6]) }
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe "#" do
|
44
|
-
subject { matcher.failure_reason(other) }
|
45
|
-
|
46
|
-
let(:pattern) { "var : Integer" }
|
47
|
-
|
48
|
-
context "match integer" do
|
49
|
-
let(:other) { 1 }
|
50
|
-
|
51
|
-
it { is_expected.to eq(Fear.none) }
|
52
|
-
end
|
53
|
-
|
54
|
-
context "does not match float" do
|
55
|
-
let(:other) { 1.0 }
|
56
|
-
|
57
|
-
it { is_expected.to eq(Fear.some(<<~ERROR.strip)) }
|
58
|
-
Expected `1.0` to match:
|
59
|
-
var : Integer
|
60
|
-
~~~~~~^
|
61
|
-
ERROR
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|