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.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +27 -0
  3. data/.github/workflows/rubocop.yml +2 -2
  4. data/.github/workflows/spec.yml +1 -1
  5. data/CHANGELOG.md +13 -0
  6. data/Gemfile.lock +53 -56
  7. data/README.md +54 -186
  8. data/Rakefile +0 -21
  9. data/examples/pattern_extracting.rb +4 -4
  10. data/fear.gemspec +2 -4
  11. data/lib/fear/either.rb +8 -4
  12. data/lib/fear/either_api.rb +2 -0
  13. data/lib/fear/either_pattern_match.rb +7 -8
  14. data/lib/fear/failure.rb +0 -9
  15. data/lib/fear/failure_pattern_match.rb +2 -0
  16. data/lib/fear/for_api.rb +2 -0
  17. data/lib/fear/future.rb +12 -20
  18. data/lib/fear/future_api.rb +13 -2
  19. data/lib/fear/left.rb +0 -9
  20. data/lib/fear/none.rb +7 -9
  21. data/lib/fear/option.rb +5 -1
  22. data/lib/fear/option_api.rb +2 -0
  23. data/lib/fear/option_pattern_match.rb +6 -4
  24. data/lib/fear/partial_function/empty.rb +2 -0
  25. data/lib/fear/partial_function/guard.rb +4 -4
  26. data/lib/fear/partial_function/or_else.rb +2 -0
  27. data/lib/fear/partial_function.rb +9 -8
  28. data/lib/fear/pattern_match.rb +0 -10
  29. data/lib/fear/pattern_matching_api.rb +3 -28
  30. data/lib/fear/promise.rb +3 -9
  31. data/lib/fear/right.rb +0 -10
  32. data/lib/fear/right_biased.rb +1 -1
  33. data/lib/fear/right_pattern_match.rb +2 -0
  34. data/lib/fear/some.rb +7 -10
  35. data/lib/fear/struct.rb +3 -14
  36. data/lib/fear/success.rb +0 -9
  37. data/lib/fear/success_pattern_match.rb +2 -0
  38. data/lib/fear/try.rb +6 -2
  39. data/lib/fear/try_api.rb +2 -0
  40. data/lib/fear/try_pattern_match.rb +7 -8
  41. data/lib/fear/utils.rb +0 -3
  42. data/lib/fear/version.rb +1 -1
  43. data/lib/fear.rb +8 -42
  44. data/spec/fear/awaitable_spec.rb +2 -0
  45. data/spec/fear/either_spec.rb +26 -0
  46. data/spec/fear/failure_spec.rb +8 -23
  47. data/spec/fear/for/mixin_spec.rb +15 -0
  48. data/spec/fear/future_spec.rb +17 -2
  49. data/spec/fear/guard_spec.rb +110 -0
  50. data/spec/fear/left_spec.rb +7 -22
  51. data/spec/fear/none_spec.rb +11 -17
  52. data/spec/fear/option_spec.rb +15 -1
  53. data/spec/fear/partial_function/any_spec.rb +25 -0
  54. data/spec/fear/partial_function_spec.rb +2 -24
  55. data/spec/fear/pattern_match_spec.rb +0 -34
  56. data/spec/fear/promise_spec.rb +4 -6
  57. data/spec/fear/right_spec.rb +0 -22
  58. data/spec/fear/some_spec.rb +10 -22
  59. data/spec/fear/success_spec.rb +0 -22
  60. data/spec/fear/try/mixin_spec.rb +14 -0
  61. data/spec/fear/try_api_spec.rb +23 -0
  62. data/spec/struct_spec.rb +1 -33
  63. metadata +18 -80
  64. data/examples/pattern_extracting_ruby2.7.rb +0 -15
  65. data/lib/fear/extractor/anonymous_array_splat_matcher.rb +0 -10
  66. data/lib/fear/extractor/any_matcher.rb +0 -17
  67. data/lib/fear/extractor/array_head_matcher.rb +0 -36
  68. data/lib/fear/extractor/array_matcher.rb +0 -40
  69. data/lib/fear/extractor/array_splat_matcher.rb +0 -16
  70. data/lib/fear/extractor/empty_list_matcher.rb +0 -20
  71. data/lib/fear/extractor/extractor_matcher.rb +0 -44
  72. data/lib/fear/extractor/grammar.rb +0 -203
  73. data/lib/fear/extractor/grammar.treetop +0 -129
  74. data/lib/fear/extractor/identifier_matcher.rb +0 -18
  75. data/lib/fear/extractor/matcher/and.rb +0 -38
  76. data/lib/fear/extractor/matcher.rb +0 -53
  77. data/lib/fear/extractor/named_array_splat_matcher.rb +0 -17
  78. data/lib/fear/extractor/pattern.rb +0 -58
  79. data/lib/fear/extractor/typed_identifier_matcher.rb +0 -26
  80. data/lib/fear/extractor/value_matcher.rb +0 -19
  81. data/lib/fear/extractor.rb +0 -112
  82. data/lib/fear/extractor_api.rb +0 -35
  83. data/spec/fear/extractor/array_matcher_spec.rb +0 -230
  84. data/spec/fear/extractor/extractor_matcher_spec.rb +0 -153
  85. data/spec/fear/extractor/grammar_array_spec.rb +0 -25
  86. data/spec/fear/extractor/identified_matcher_spec.rb +0 -49
  87. data/spec/fear/extractor/identifier_matcher_spec.rb +0 -68
  88. data/spec/fear/extractor/pattern_spec.rb +0 -34
  89. data/spec/fear/extractor/typed_identifier_matcher_spec.rb +0 -64
  90. data/spec/fear/extractor/value_matcher_number_spec.rb +0 -79
  91. data/spec/fear/extractor/value_matcher_string_spec.rb +0 -88
  92. data/spec/fear/extractor/value_matcher_symbol_spec.rb +0 -71
  93. data/spec/fear/extractor_api_spec.rb +0 -115
  94. data/spec/fear/extractor_spec.rb +0 -61
@@ -78,18 +78,16 @@ RSpec.describe Fear::Promise do
78
78
  end
79
79
 
80
80
  context "#future" do
81
- subject(:future) do
82
- completed_promise.to_future
83
- end
81
+ subject(:future) { Fear::Await.ready(promise.to_future, 0.01) }
82
+
83
+ let(:promise) { Fear::Promise.new.success!(value) }
84
84
 
85
85
  it "is completed" do
86
86
  expect(future).to be_completed
87
87
  end
88
88
 
89
89
  it "completed with value" do
90
- future_value = future.value
91
-
92
- expect(future_value).to eq Fear.some(Fear.success(value))
90
+ expect(future.value).to be_some_of(Fear.success(value))
93
91
  end
94
92
  end
95
93
  end
@@ -160,26 +160,4 @@ RSpec.describe Fear::Right do
160
160
 
161
161
  it { is_expected.to eq('#<Fear::Right value="value">') }
162
162
  end
163
-
164
- describe "pattern matching" do
165
- subject { Fear.xcase("Right(v : Integer)") { |v:| "matched #{v}" }.call_or_else(var) { "nothing" } }
166
-
167
- context "right of int" do
168
- let(:var) { Fear.right(42) }
169
-
170
- it { is_expected.to eq("matched 42") }
171
- end
172
-
173
- context "right of string" do
174
- let(:var) { Fear.right("42") }
175
-
176
- it { is_expected.to eq("nothing") }
177
- end
178
-
179
- context "not right" do
180
- let(:var) { "42" }
181
-
182
- it { is_expected.to eq("nothing") }
183
- end
184
- end
185
163
  end
@@ -50,6 +50,16 @@ RSpec.describe Fear::Some do
50
50
  it { is_expected.to eq(false) }
51
51
  end
52
52
 
53
+ describe "#blank?" do
54
+ subject { some.blank? }
55
+ it { is_expected.to eq(false) }
56
+ end
57
+
58
+ describe "#present?" do
59
+ subject { some.present? }
60
+ it { is_expected.to be_truthy }
61
+ end
62
+
53
63
  describe "#match" do
54
64
  context "matched" do
55
65
  subject do
@@ -92,26 +102,4 @@ RSpec.describe Fear::Some do
92
102
 
93
103
  it { is_expected.to eq("#<Fear::Some get=42>") }
94
104
  end
95
-
96
- describe "pattern matching" do
97
- subject { Fear.xcase("Some(v : Integer)") { |v:| "matched #{v}" }.call_or_else(var) { "nothing" } }
98
-
99
- context "some of int" do
100
- let(:var) { Fear.some(42) }
101
-
102
- it { is_expected.to eq("matched 42") }
103
- end
104
-
105
- context "some of string" do
106
- let(:var) { Fear.some("42") }
107
-
108
- it { is_expected.to eq("nothing") }
109
- end
110
-
111
- context "not some" do
112
- let(:var) { "42" }
113
-
114
- it { is_expected.to eq("nothing") }
115
- end
116
- end
117
105
  end
@@ -135,26 +135,4 @@ RSpec.describe Fear::Success do
135
135
 
136
136
  it { is_expected.to eq('#<Fear::Success value="value">') }
137
137
  end
138
-
139
- describe "pattern matching" do
140
- subject { Fear.xcase("Success(v : Integer)") { |v:| "matched #{v}" }.call_or_else(var) { "nothing" } }
141
-
142
- context "success of int" do
143
- let(:var) { Fear.success(42) }
144
-
145
- it { is_expected.to eq("matched 42") }
146
- end
147
-
148
- context "success of string" do
149
- let(:var) { Fear.success("42") }
150
-
151
- it { is_expected.to eq("nothing") }
152
- end
153
-
154
- context "not success" do
155
- let(:var) { "42" }
156
-
157
- it { is_expected.to eq("nothing") }
158
- end
159
- end
160
138
  end
@@ -16,4 +16,18 @@ RSpec.describe Fear::Try::Mixin do
16
16
  it { is_expected.to be_kind_of(Fear::Failure) }
17
17
  end
18
18
  end
19
+
20
+ describe "Success()" do
21
+ subject { Success(42) }
22
+
23
+ it { is_expected.to be_success_of(42) }
24
+ end
25
+
26
+ describe "Failure()" do
27
+ subject { Failure(error) }
28
+
29
+ let(:error) { StandardError.new }
30
+
31
+ it { is_expected.to be_failure_of(error) }
32
+ end
19
33
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Fear::TryApi do
4
+ describe "Fear.try" do
5
+ context "when success" do
6
+ subject { Fear.try { 42 } }
7
+
8
+ it { is_expected.to be_success_of(42) }
9
+ end
10
+
11
+ context "when failure" do
12
+ subject { Fear.try { raise RuntimeError } }
13
+
14
+ it { is_expected.to be_failure_of(RuntimeError) }
15
+ end
16
+
17
+ context "when low level error happened" do
18
+ subject(:try) { Fear.try { raise Exception } }
19
+
20
+ it { expect { try }.to raise_error(Exception) }
21
+ end
22
+ end
23
+ end
data/spec/struct_spec.rb CHANGED
@@ -168,7 +168,7 @@ RSpec.describe Fear::Struct do
168
168
  context "string attributes" do
169
169
  subject { -> { struct.copy("a" => 44) } }
170
170
 
171
- it { is_expected.to raise_error(ArgumentError, "wrong number of arguments (given 1, expected 0)") }
171
+ it { is_expected.to raise_error(ArgumentError) }
172
172
  end
173
173
 
174
174
  context "no attributes given" do
@@ -191,36 +191,4 @@ RSpec.describe Fear::Struct do
191
191
 
192
192
  it { is_expected.to eq("<#Fear::Struct StrToS a=2, b=nil>") }
193
193
  end
194
-
195
- context "extract" do
196
- Str = Fear::Struct.with_attributes(:a, :b)
197
- let(:struct) { Str.new(b: 43, a: 42) }
198
-
199
- context "Fear::Struct subclass" do
200
- context "match by one member" do
201
- subject do
202
- proc do |effect|
203
- struct.match do |m|
204
- m.xcase("Str(a, 43)", &effect)
205
- end
206
- end
207
- end
208
-
209
- it { is_expected.to yield_with_args(a: 42) }
210
- end
211
-
212
- context "does not match" do
213
- subject do
214
- proc do |effect|
215
- struct.match do |m|
216
- m.xcase("Str(_, 40)", &effect)
217
- m.else {}
218
- end
219
- end
220
- end
221
-
222
- it { is_expected.not_to yield_control }
223
- end
224
- end
225
- end
226
194
  end
metadata CHANGED
@@ -1,43 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fear
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tema Bolshakov
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-15 00:00:00.000000000 Z
11
+ date: 2022-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: lru_redux
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: treetop
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
13
  - !ruby/object:Gem::Dependency
42
14
  name: benchmark-ips
43
15
  requirement: !ruby/object:Gem::Requirement
@@ -170,14 +142,14 @@ dependencies:
170
142
  requirements:
171
143
  - - '='
172
144
  - !ruby/object:Gem::Version
173
- version: 1.0.0
145
+ version: 1.32.0
174
146
  type: :development
175
147
  prerelease: false
176
148
  version_requirements: !ruby/object:Gem::Requirement
177
149
  requirements:
178
150
  - - '='
179
151
  - !ruby/object:Gem::Version
180
- version: 1.0.0
152
+ version: 1.32.0
181
153
  - !ruby/object:Gem::Dependency
182
154
  name: ruby_coding_standard
183
155
  requirement: !ruby/object:Gem::Requirement
@@ -269,6 +241,7 @@ executables: []
269
241
  extensions: []
270
242
  extra_rdoc_files: []
271
243
  files:
244
+ - ".github/dependabot.yml"
272
245
  - ".github/workflows/rubocop.yml"
273
246
  - ".github/workflows/spec.yml"
274
247
  - ".gitignore"
@@ -295,7 +268,6 @@ files:
295
268
  - benchmarks/pattern_matching_qo_vs_fear_pattern_extraction.txt
296
269
  - benchmarks/pattern_matching_qo_vs_fear_try_execution.txt
297
270
  - examples/pattern_extracting.rb
298
- - examples/pattern_extracting_ruby2.7.rb
299
271
  - examples/pattern_matching_binary_tree_set.rb
300
272
  - examples/pattern_matching_number_in_words.rb
301
273
  - fear.gemspec
@@ -308,24 +280,6 @@ files:
308
280
  - lib/fear/either_api.rb
309
281
  - lib/fear/either_pattern_match.rb
310
282
  - lib/fear/empty_partial_function.rb
311
- - lib/fear/extractor.rb
312
- - lib/fear/extractor/anonymous_array_splat_matcher.rb
313
- - lib/fear/extractor/any_matcher.rb
314
- - lib/fear/extractor/array_head_matcher.rb
315
- - lib/fear/extractor/array_matcher.rb
316
- - lib/fear/extractor/array_splat_matcher.rb
317
- - lib/fear/extractor/empty_list_matcher.rb
318
- - lib/fear/extractor/extractor_matcher.rb
319
- - lib/fear/extractor/grammar.rb
320
- - lib/fear/extractor/grammar.treetop
321
- - lib/fear/extractor/identifier_matcher.rb
322
- - lib/fear/extractor/matcher.rb
323
- - lib/fear/extractor/matcher/and.rb
324
- - lib/fear/extractor/named_array_splat_matcher.rb
325
- - lib/fear/extractor/pattern.rb
326
- - lib/fear/extractor/typed_identifier_matcher.rb
327
- - lib/fear/extractor/value_matcher.rb
328
- - lib/fear/extractor_api.rb
329
283
  - lib/fear/failure.rb
330
284
  - lib/fear/failure_pattern_match.rb
331
285
  - lib/fear/for.rb
@@ -378,19 +332,9 @@ files:
378
332
  - spec/fear/either/mixin_spec.rb
379
333
  - spec/fear/either_pattern_match_spec.rb
380
334
  - spec/fear/either_pattern_matching_spec.rb
381
- - spec/fear/extractor/array_matcher_spec.rb
382
- - spec/fear/extractor/extractor_matcher_spec.rb
383
- - spec/fear/extractor/grammar_array_spec.rb
384
- - spec/fear/extractor/identified_matcher_spec.rb
385
- - spec/fear/extractor/identifier_matcher_spec.rb
386
- - spec/fear/extractor/pattern_spec.rb
387
- - spec/fear/extractor/typed_identifier_matcher_spec.rb
388
- - spec/fear/extractor/value_matcher_number_spec.rb
389
- - spec/fear/extractor/value_matcher_string_spec.rb
390
- - spec/fear/extractor/value_matcher_symbol_spec.rb
391
- - spec/fear/extractor_api_spec.rb
392
- - spec/fear/extractor_spec.rb
335
+ - spec/fear/either_spec.rb
393
336
  - spec/fear/failure_spec.rb
337
+ - spec/fear/for/mixin_spec.rb
394
338
  - spec/fear/for_spec.rb
395
339
  - spec/fear/future_spec.rb
396
340
  - spec/fear/guard_spec.rb
@@ -400,6 +344,7 @@ files:
400
344
  - spec/fear/option_pattern_match_spec.rb
401
345
  - spec/fear/option_pattern_matching_spec.rb
402
346
  - spec/fear/option_spec.rb
347
+ - spec/fear/partial_function/any_spec.rb
403
348
  - spec/fear/partial_function/empty_spec.rb
404
349
  - spec/fear/partial_function_and_then_spec.rb
405
350
  - spec/fear/partial_function_composition_spec.rb
@@ -414,6 +359,7 @@ files:
414
359
  - spec/fear/some_spec.rb
415
360
  - spec/fear/success_spec.rb
416
361
  - spec/fear/try/mixin_spec.rb
362
+ - spec/fear/try_api_spec.rb
417
363
  - spec/fear/try_pattern_match_spec.rb
418
364
  - spec/fear/try_pattern_matching_spec.rb
419
365
  - spec/fear/utils_spec.rb
@@ -425,7 +371,7 @@ homepage: https://github.com/bolshakov/fear
425
371
  licenses:
426
372
  - MIT
427
373
  metadata: {}
428
- post_install_message:
374
+ post_install_message:
429
375
  rdoc_options: []
430
376
  require_paths:
431
377
  - lib
@@ -433,15 +379,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
433
379
  requirements:
434
380
  - - ">="
435
381
  - !ruby/object:Gem::Version
436
- version: '0'
382
+ version: 2.6.0
437
383
  required_rubygems_version: !ruby/object:Gem::Requirement
438
384
  requirements:
439
385
  - - ">="
440
386
  - !ruby/object:Gem::Version
441
387
  version: '0'
442
388
  requirements: []
443
- rubygems_version: 3.1.4
444
- signing_key:
389
+ rubygems_version: 3.3.7
390
+ signing_key:
445
391
  specification_version: 4
446
392
  summary: "%q{Ruby port of some Scala's monads.}"
447
393
  test_files:
@@ -455,19 +401,9 @@ test_files:
455
401
  - spec/fear/either/mixin_spec.rb
456
402
  - spec/fear/either_pattern_match_spec.rb
457
403
  - spec/fear/either_pattern_matching_spec.rb
458
- - spec/fear/extractor/array_matcher_spec.rb
459
- - spec/fear/extractor/extractor_matcher_spec.rb
460
- - spec/fear/extractor/grammar_array_spec.rb
461
- - spec/fear/extractor/identified_matcher_spec.rb
462
- - spec/fear/extractor/identifier_matcher_spec.rb
463
- - spec/fear/extractor/pattern_spec.rb
464
- - spec/fear/extractor/typed_identifier_matcher_spec.rb
465
- - spec/fear/extractor/value_matcher_number_spec.rb
466
- - spec/fear/extractor/value_matcher_string_spec.rb
467
- - spec/fear/extractor/value_matcher_symbol_spec.rb
468
- - spec/fear/extractor_api_spec.rb
469
- - spec/fear/extractor_spec.rb
404
+ - spec/fear/either_spec.rb
470
405
  - spec/fear/failure_spec.rb
406
+ - spec/fear/for/mixin_spec.rb
471
407
  - spec/fear/for_spec.rb
472
408
  - spec/fear/future_spec.rb
473
409
  - spec/fear/guard_spec.rb
@@ -477,6 +413,7 @@ test_files:
477
413
  - spec/fear/option_pattern_match_spec.rb
478
414
  - spec/fear/option_pattern_matching_spec.rb
479
415
  - spec/fear/option_spec.rb
416
+ - spec/fear/partial_function/any_spec.rb
480
417
  - spec/fear/partial_function/empty_spec.rb
481
418
  - spec/fear/partial_function_and_then_spec.rb
482
419
  - spec/fear/partial_function_composition_spec.rb
@@ -491,6 +428,7 @@ test_files:
491
428
  - spec/fear/some_spec.rb
492
429
  - spec/fear/success_spec.rb
493
430
  - spec/fear/try/mixin_spec.rb
431
+ - spec/fear/try_api_spec.rb
494
432
  - spec/fear/try_pattern_match_spec.rb
495
433
  - spec/fear/try_pattern_matching_spec.rb
496
434
  - spec/fear/utils_spec.rb
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "fear"
4
-
5
- matcher = proc do |value|
6
- case value
7
- in User(admin: true, name:)
8
- puts "Hi #{name}, you are welcome"
9
- in User(admin: false)
10
- puts "Only admins are allowed here"
11
- end
12
- end
13
-
14
- matcher.(User.new(1, "Jane", true))
15
- matcher.(User.new(1, "John", false))
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fear
4
- module Extractor
5
- # Match against array splat, E.g. `[1, 2, *]` or `[1, 2, *_]`
6
- #
7
- class AnonymousArraySplatMatcher < ArraySplatMatcher
8
- end
9
- end
10
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fear
4
- module Extractor
5
- # Always match, E.g. `_ : Integer` without capturing variable
6
- #
7
- class AnyMatcher < Matcher
8
- def defined_at?(_other)
9
- true
10
- end
11
-
12
- def bindings(_)
13
- Utils::EMPTY_HASH
14
- end
15
- end
16
- end
17
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fear
4
- module Extractor
5
- # Part of recursive array matcher. Match against its head.
6
- # @see ArrayMatcher
7
- class ArrayHeadMatcher < Matcher
8
- # @!attribute matcher
9
- # @return [Matcher]
10
- # @!attribute index
11
- # @return [Types::Strict::Integer]
12
-
13
- # @param other [<>]
14
- def defined_at?(other)
15
- if other.empty?
16
- false
17
- else
18
- matcher.defined_at?(other.first)
19
- end
20
- end
21
-
22
- # @param other [<>]
23
- def bindings(other)
24
- if other.empty?
25
- super
26
- else
27
- matcher.bindings(other.first)
28
- end
29
- end
30
-
31
- def failure_reason(other)
32
- matcher.failure_reason(other.first)
33
- end
34
- end
35
- end
36
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fear
4
- module Extractor
5
- # Recursive array matcher. Match against its head and tail
6
- #
7
- class ArrayMatcher < Matcher
8
- # @!attribute head
9
- # @return [ArrayHeadMatcher]
10
- # @!attribute tail
11
- # @return [ArrayMatcher | EmptyListMatcher]
12
-
13
- def defined_at?(other)
14
- if other.is_a?(Array)
15
- head.defined_at?(other) && tail.defined_at?(other.slice(1..-1))
16
- end
17
- end
18
-
19
- def bindings(other)
20
- if head.is_a?(ArraySplatMatcher)
21
- head.bindings(other)
22
- else
23
- head.bindings(other).merge(tail.bindings(other.slice(1..-1)))
24
- end
25
- end
26
-
27
- def failure_reason(other)
28
- if other.is_a?(Array)
29
- if head.defined_at?(other)
30
- tail.failure_reason(other.slice(1..-1))
31
- else
32
- head.failure_reason(other)
33
- end
34
- else
35
- super
36
- end
37
- end
38
- end
39
- end
40
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fear
4
- module Extractor
5
- # @abstract
6
- class ArraySplatMatcher < Matcher
7
- def defined_at?(_other)
8
- true
9
- end
10
-
11
- def bindings(_)
12
- Utils::EMPTY_HASH
13
- end
14
- end
15
- end
16
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fear
4
- module Extractor
5
- # Match only if array is empty
6
- #
7
- class EmptyListMatcher < Matcher
8
- # @!attribute index
9
- # @return [Types::Strict::Integer]
10
- #
11
- def defined_at?(other)
12
- other.empty?
13
- end
14
-
15
- def bindings(_)
16
- Utils::EMPTY_HASH
17
- end
18
- end
19
- end
20
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fear
4
- module Extractor
5
- # Match and extract pattern using registered extractor objects
6
- # E.g. +Some(a : Integer)+
7
- # @see Extractor.register_extractor
8
- class ExtractorMatcher < Matcher
9
- # @!attribute name
10
- # @return [Types::Strict::String]
11
- # @!attribute arguments_matcher
12
- # @return [ArrayMatcher | EmptyListMatcher]
13
- #
14
-
15
- def initialize(*)
16
- super
17
- @extractor = Extractor.find_extractor(name)
18
- end
19
- attr_reader :extractor
20
- private :extractor
21
-
22
- def defined_at?(other)
23
- extractor
24
- .(other)
25
- .map { |v| arguments_matcher.defined_at?(v) }
26
- .get_or_else(false)
27
- end
28
-
29
- def call_or_else(arg)
30
- extractor.(arg)
31
- .map { |v| arguments_matcher.call_or_else(v) { yield arg } }
32
- .get_or_else { yield arg }
33
- end
34
-
35
- def failure_reason(other)
36
- extractor.(other).match do |m|
37
- m.some(->(v) { arguments_matcher.defined_at?(v) }) { Fear.none }
38
- m.some { |v| arguments_matcher.failure_reason(v) }
39
- m.none { super }
40
- end
41
- end
42
- end
43
- end
44
- end