eqq 0.0.2 → 0.0.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd093a7aa8c034327d463c56bfe120a8ecc48b52649ba7900491f05cc130cc38
4
- data.tar.gz: 13f7ca2f2f40d9be41abd4408f5486b892f345347eb07eeb3f4d936c47cc92ab
3
+ metadata.gz: becfb749a93e73ea402265899e57d3deea45bf0eb457a29a66eafa03965b1572
4
+ data.tar.gz: 3f6578bd2f0b3334369834ff1f344b4b033318172586a9324496027a057507a0
5
5
  SHA512:
6
- metadata.gz: 2e510f5313e0f890bf3c8277a413f937b0a26e2ba58e501591288556783bc5fffc944c23a1216ddf95308a111b06c6ac82557526d9f7de49ef9dbe7806f93bb6
7
- data.tar.gz: 719905cbd2f71a388e13ca0427b7db49115513ce11395a436d8ef9fc43397c9c77cc408135862147bbfc3bac3fb36615332752f56ab28e4136bc74b8db3f97dd
6
+ metadata.gz: 3d76a45da1f1e181d77b6f9cbfc6f80d88af6abed0782b1da92f6562934bf551c2f55e5691be7108d0acf0521562a042bb5cba6f54f9846af78b7ba4031d35fb
7
+ data.tar.gz: 2ec4137407dfaf6b4189255532e59669798ac9ed57be8e6ecdb07c31525d132b9246da9d9fd6b98975e31b712e002e2693f523acf285d172df1b13c7c46617d5
data/README.md CHANGED
@@ -3,9 +3,7 @@
3
3
  ![Build Status](https://github.com/kachick/eqq/actions/workflows/test_behaviors.yml/badge.svg?branch=main)
4
4
  [![Gem Version](https://badge.fury.io/rb/eqq.png)](http://badge.fury.io/rb/eqq)
5
5
 
6
- Pattern objects builder.
7
-
8
- `eqq` means `#===`
6
+ Pattern objects builder
9
7
 
10
8
  ## Usage
11
9
 
@@ -14,7 +12,7 @@ Require Ruby 2.6 or later
14
12
  Add below code into your Gemfile
15
13
 
16
14
  ```ruby
17
- gem 'eqq', '0.0.2'
15
+ gem 'eqq', '>= 0.0.7', '< 0.1.0'
18
16
  ```
19
17
 
20
18
  ### Overview
@@ -26,13 +24,133 @@ require 'eqq'
26
24
  [42, nil, true, false, '', 0].grep(Eqq.BOOLEAN) #=> [true, false]
27
25
  [42, [], {}, 'string', Object.new, nil].grep(Eqq.CAN(:to_h)) #=> [[], {}, nil]
28
26
 
29
- pattern = Eqq.define do
27
+ pattern = Eqq.build do
30
28
  OR(AND(Float, 20..50), Integer)
31
29
  end
30
+
31
+ p pattern #=> "OR(AND(Float, 20..50), Integer)"
32
32
  [4.2, 42, 42.0, 420].grep(pattern) #=> [42, 42.0, 420]
33
+
34
+ inverted = Eqq.NOT(pattern)
35
+ p inverted #=> "NOT(OR(AND(Float, 20..50), Integer))"
36
+ [4.2, 42, 42.0, 420].grep(inverted) #=> [4.2]
37
+
38
+ Eqq.SEND(:all?, pattern) === [4.2, 42, 42.0, 420] #=> false
39
+ Eqq.SEND(:any?, pattern) === [4.2, 42, 42.0, 420] #=> true
40
+
41
+ ret_in_case = (
42
+ case 42
43
+ when pattern
44
+ 'Should be matched here! :)'
45
+ when inverted
46
+ 'Should not be matched here! :<'
47
+ else
48
+ 'Should not be matched here too! :<'
49
+ end
50
+ )
51
+
52
+ p ret_in_case #=> Should be matched here! :)
53
+
54
+ ret_in_case = (
55
+ case 4.2
56
+ when pattern
57
+ 'Should not be matched here! :<'
58
+ when inverted
59
+ 'Should be matched here! :)'
60
+ else
61
+ 'Should not be matched here too! :<'
62
+ end
63
+ )
64
+
65
+ p ret_in_case #=> Should be matched here! :)
66
+
67
+ class MyClass
68
+ include Eqq::Buildable
69
+
70
+ def example
71
+ [4.2, 42, 42.0, 420].grep(OR(AND(Float, 20..50), Integer))
72
+ end
73
+ end
74
+ MyClass.new.example #=> [42, 42.0, 420]
33
75
  ```
34
76
 
77
+ ### Explanation
78
+
79
+ All products can be called as `pattern === other`.
80
+
81
+ This signature will fit in most Ruby code.
82
+
83
+ * `case ~ when` syntax
84
+ * Enumerable#grep
85
+ * Enumerable#grep_v
86
+ * Enumerable#all?
87
+ * Enumerable#any?
88
+ * Enumerable#none?
89
+ * Enumerable#one?
90
+ * Enumerable#slice_after
91
+ * Enumerable#slice_before
92
+
93
+ They can take this interface as the `pattern`.
94
+
95
+ And you already saw. All of patterns can be mixed with other patterns as a parts.
96
+ Reuse as you wish!
97
+
98
+ ### Builders
99
+
100
+ * OR(*patterns) - Product returns `true` when matched even one pattern
101
+ * AND(*patterns) - Product returns `true` when matched all patterns
102
+ * NOT(pattern) - Product returns `true` when not matched the pattern
103
+ * CAN(*method_names) - Product returns `true` when it has all of the methods (checked with `respond_to?`)
104
+ * RESCUE(exception_class/module, pattern) - Product returns `true` when the pattern raises the exception
105
+ * QUIET(*patterns) - Product returns `true` when all patterns did not raise any exception
106
+ * EQ(object) - Product returns `true` when matched with `#==`
107
+ * SAME(object) - Product returns `true` when matched with `#equal?`
108
+ * SEND(name, pattern) - Basically provided for Enumerable
109
+ * BOOLEAN() - Product returns `true` when matched to `true` or `false`
110
+ * NIL() - Product returns `true` when matched to `nil` (Not consider `nil?`)
111
+ * ANYTHING() - Product returns `true`, always `true`
112
+ * NEVER() - Product returns `false`, always `false`
113
+ * XOR(pattern1, pattern2) - Product returns `true` when matched one of the pattern, when matched both returns `false`
114
+ * NAND(*patterns) - Product is an inverted `AND`
115
+ * NOR(*patterns) - Product is an inverted `OR`
116
+
117
+ ### Best fit for RSpec's `satisfy` matcher too
118
+
119
+ All builders actually generate a `Proc (lambda)` instance.
120
+ The signature will fit for RSpec's built-in [`satisfy` matcher](https://relishapp.com/rspec/rspec-expectations/v/3-10/docs/built-in-matchers/satisfy-matcher) too.
121
+
122
+ ```ruby
123
+ RSpec.describe RSpec::Matchers::BuiltIn::Satisfy do
124
+ let(:product) { Eqq.AND(Integer, 24..42) }
125
+
126
+ it 'perfectly works' do
127
+ expect(23).not_to satisfy(&product)
128
+ expect(24).to satisfy(&product)
129
+ expect(24.0).not_to satisfy(&product)
130
+ expect(42).to satisfy(&product)
131
+ expect(42.0).not_to satisfy(&product)
132
+ expect(43).not_to satisfy(&product)
133
+ end
134
+ end
135
+ ```
136
+
137
+ ### Use builders without receiver specifying
138
+
139
+ When you felt annoy to write `Eqq` in many place, some ways exist.
140
+
141
+ * `Eqq.build(&block)` - In the block scope, all builder methods can be used without receiver
142
+ * `extend Eqq::Buildable` - In the class/module, all builders can be used as class methods
143
+ * `include Eqq::Buildable` - In the class/module, all builders can be used as instance methods
144
+
145
+ ### Signature
146
+
147
+ * This gem provides [ruby/rbs](https://github.com/ruby/rbs) signature file
148
+
35
149
  ## Links
36
150
 
37
151
  * [Repository](https://github.com/kachick/eqq)
38
152
  * [API documents](https://kachick.github.io/eqq)
153
+
154
+ ## NOTE
155
+
156
+ * [`eqq` is the implementation name of `#===` in CRuby](https://github.com/ruby/ruby/blob/2a685da1fcd928530509e99f5edb4117bc377994/range.c#L1859)
data/lib/eqq.rb CHANGED
@@ -4,21 +4,18 @@
4
4
  # Copyright (c) 2011 Kenichi Kamiya
5
5
  # Forked from https://github.com/kachick/validation at 2021
6
6
 
7
- require_relative 'eqq/buildable'
8
7
  require_relative 'eqq/version'
9
8
 
9
+ # Pattern objects builder
10
10
  module Eqq
11
- extend Buildable
12
-
11
+ # Base error of this library
13
12
  class Error < StandardError; end
14
- class InvalidProductError < Error; end
15
13
 
16
- class DSLScope
17
- include Buildable
18
- end
14
+ # Raised when found some products are invalid as a pattern object
15
+ class InvalidProductError < Error; end
19
16
 
20
17
  class << self
21
- def valid?(object)
18
+ def pattern?(object)
22
19
  case object
23
20
  when Proc, Method
24
21
  object.arity == 1
@@ -31,11 +28,41 @@ module Eqq
31
28
  end
32
29
  end
33
30
 
34
- def define(&block)
31
+ # @deprecated Use {pattern?} instead. This will be dropped since `0.1.0`
32
+ def valid?(object)
33
+ pattern?(object)
34
+ end
35
+
36
+ # @api private
37
+ def satisfy?(object)
38
+ (Proc === object) && object.lambda? && (object.arity == 1) && object.respond_to?(:inspect)
39
+ end
40
+
41
+ # @return [Proc]
42
+ # @raise [InvalidProductError] if the return value is not looks to be built with builders
43
+ def build(&block)
44
+ raise ArgumentError, 'might be mis used the `Eqq.build` in your code' unless block
45
+
35
46
  pattern = DSLScope.new.instance_exec(&block)
36
- raise InvalidProductError unless valid?(pattern)
47
+ raise InvalidProductError, 'might be mis used the `Eqq.build` in your code' unless satisfy?(pattern)
37
48
 
38
49
  pattern
39
50
  end
51
+
52
+ # @deprecated Use {build} instead. This will be dropped since `0.1.0`
53
+ def define(&block)
54
+ build(&block)
55
+ end
56
+ end
57
+ end
58
+
59
+ require_relative 'eqq/buildable'
60
+
61
+ module Eqq
62
+ extend Buildable
63
+
64
+ class DSLScope
65
+ include Buildable
40
66
  end
67
+ private_constant(:DSLScope)
41
68
  end
data/lib/eqq/buildable.rb CHANGED
@@ -2,20 +2,69 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Eqq
5
+ # Actually having definitions for the pattern builders
5
6
  module Buildable
6
- extend self
7
+ class << self
8
+ # When the inspection is failed some unexpected reasons, it will fallback to this value
9
+ # This value is not fixed as a spec, might be changed in future
10
+ INSPECTION_FALLBACK = 'UninspectableObject'
7
11
 
12
+ # @api private
13
+ # @return [String]
14
+ def safe_inspect_for(object)
15
+ String.try_convert(object.inspect) || INSPECTION_FALLBACK
16
+ rescue Exception
17
+ # This implementation used `RSpec::Support::ObjectFormatter::UninspectableObjectInspector` as a reference, thank you!
18
+ # ref: https://github.com/kachick/times_kachick/issues/97
19
+ singleton_class = class << object; self; end
20
+ begin
21
+ klass = singleton_class.ancestors.detect { |ancestor| !ancestor.equal?(singleton_class) }
22
+ native_object_id = '%#016x' % (object.__id__ << 1)
23
+ "#<#{klass}:#{native_object_id}>"
24
+ rescue Exception
25
+ INSPECTION_FALLBACK
26
+ end
27
+ end
28
+
29
+ # @api private
30
+ # @return [void]
31
+ def define_inspect_on(product, name:, arguments:)
32
+ inspect = "#{name}(#{arguments.map { |argument| safe_inspect_for(argument) }.join(', ')})".freeze
33
+ product.define_singleton_method(:inspect) do
34
+ inspect
35
+ end
36
+ end
37
+
38
+ # @api private
39
+ # @return [void]
40
+ def validate_patterns(*patterns)
41
+ invalids = patterns.reject { |pattern| Eqq.pattern?(pattern) }
42
+ invalid_inspections = invalids.map { |invalid| safe_inspect_for(invalid) }.join(', ')
43
+ raise ArgumentError, "given `#{invalid_inspections}` are invalid as pattern objects" unless invalids.empty?
44
+ end
45
+ end
46
+
47
+ # Product returns `true` when matched all patterns
48
+ #
8
49
  # @param pattern1 [Proc, Method, #===]
9
50
  # @param pattern2 [Proc, Method, #===]
10
51
  # @param patterns [Array<Proc, Method, #===>]
11
52
  # @return [Proc]
12
- # this lambda return true if match all patterns
13
53
  def AND(pattern1, pattern2, *patterns)
14
- ->v {
15
- [pattern1, pattern2, *patterns].all? { |pattern| pattern === v }
54
+ patterns = [pattern1, pattern2, *patterns].freeze
55
+ Buildable.validate_patterns(*patterns)
56
+
57
+ product = ->v {
58
+ patterns.all? { |pattern| pattern === v }
16
59
  }
60
+
61
+ Buildable.define_inspect_on(product, name: 'AND', arguments: patterns)
62
+
63
+ product
17
64
  end
18
65
 
66
+ # Product is an inverted {#AND}
67
+ #
19
68
  # @param pattern1 [Proc, Method, #===]
20
69
  # @param pattern2 [Proc, Method, #===]
21
70
  # @param patterns [Array<Proc, Method, #===>]
@@ -24,17 +73,26 @@ module Eqq
24
73
  NOT(AND(pattern1, pattern2, *patterns))
25
74
  end
26
75
 
76
+ # Product returns `true` when matched even one pattern
77
+ #
27
78
  # @param pattern1 [Proc, Method, #===]
28
79
  # @param pattern2 [Proc, Method, #===]
29
80
  # @param patterns [Array<Proc, Method, #===>]
30
81
  # @return [Proc]
31
- # this lambda return true if match a any pattern
32
82
  def OR(pattern1, pattern2, *patterns)
33
- ->v {
34
- [pattern1, pattern2, *patterns].any? { |pattern| pattern === v }
83
+ patterns = [pattern1, pattern2, *patterns].freeze
84
+ Buildable.validate_patterns(*patterns)
85
+
86
+ product = ->v {
87
+ patterns.any? { |pattern| pattern === v }
35
88
  }
89
+ Buildable.define_inspect_on(product, name: 'OR', arguments: patterns)
90
+
91
+ product
36
92
  end
37
93
 
94
+ # Product is an inverted {#OR}
95
+ #
38
96
  # @param pattern1 [Proc, Method, #===]
39
97
  # @param pattern2 [Proc, Method, #===]
40
98
  # @param patterns [Array<Proc, Method, #===>]
@@ -43,56 +101,72 @@ module Eqq
43
101
  NOT(OR(pattern1, pattern2, *patterns))
44
102
  end
45
103
 
104
+ # Product returns `true` when matched one of the pattern, when matched both returns `false`
105
+ #
46
106
  # @param pattern1 [Proc, Method, #===]
47
107
  # @param pattern2 [Proc, Method, #===]
48
- # @param patterns [Array<Proc, Method, #===>]
49
108
  # @return [Proc]
50
- def XOR(pattern1, pattern2, *patterns)
51
- ->v {
52
- [pattern1, pattern2, *patterns].one? { |pattern| pattern === v }
109
+ def XOR(pattern1, pattern2)
110
+ patterns = [pattern1, pattern2].freeze
111
+ Buildable.validate_patterns(*patterns)
112
+
113
+ product = ->v {
114
+ patterns.one? { |pattern| pattern === v }
53
115
  }
54
- end
116
+ Buildable.define_inspect_on(product, name: 'XOR', arguments: patterns)
55
117
 
56
- # @param pattern1 [Proc, Method, #===]
57
- # @param pattern2 [Proc, Method, #===]
58
- # @param patterns [Array<Proc, Method, #===>]
59
- # @return [Proc]
60
- def XNOR(pattern1, pattern2, *patterns)
61
- NOT(XOR(pattern1, pattern2, *patterns))
118
+ product
62
119
  end
63
120
 
121
+ # Product returns `true` when not matched the pattern
122
+ #
64
123
  # @param pattern [Proc, Method, #===]
65
124
  # @return [Proc]
66
125
  def NOT(pattern)
67
- raise ArgumentError, 'wrong object for pattern' unless Eqq.valid?(pattern)
126
+ Buildable.validate_patterns(pattern)
68
127
 
69
- ->v { !(pattern === v) }
128
+ product = ->v { !(pattern === v) }
129
+
130
+ Buildable.define_inspect_on(product, name: 'NOT', arguments: [pattern])
131
+
132
+ product
70
133
  end
71
134
 
72
- # A pattern builder.
135
+ # Product returns `true` when matched with `#==`
136
+ #
73
137
  # @param obj [#==]
74
138
  # @return [Proc]
75
139
  def EQ(obj)
76
- ->v { obj == v }
140
+ product = ->v { obj == v }
141
+ Buildable.define_inspect_on(product, name: 'EQ', arguments: [obj])
142
+ product
77
143
  end
78
144
 
145
+ # Product returns `true` when matched with `#equal?`
146
+ #
79
147
  # @param obj [#equal?]
80
148
  # @return [Proc]
81
149
  def SAME(obj)
82
- ->v { obj.equal?(v) }
150
+ product = ->v { obj.equal?(v) }
151
+ Buildable.define_inspect_on(product, name: 'SAME', arguments: [obj])
152
+ product
83
153
  end
84
154
 
85
- # @param message1 [Symbol, String]
86
- # @param messages [Array<Symbol, String>]
155
+ # Product returns `true` when it has all of the methods (checked with `respond_to?`)
156
+ #
157
+ # @param message1 [Symbol, String, #to_sym]
158
+ # @param messages [Array<Symbol, String, #to_sym>]
87
159
  # @return [Proc]
88
160
  def CAN(message1, *messages)
89
- messages = begin
90
- [message1, *messages].map(&:to_sym)
91
- rescue NoMethodError
92
- raise ArgumentError
93
- end
161
+ messages = (
162
+ begin
163
+ [message1, *messages].map(&:to_sym).freeze
164
+ rescue NoMethodError
165
+ raise ArgumentError
166
+ end
167
+ )
94
168
 
95
- ->v {
169
+ product = ->v {
96
170
  messages.all? { |message|
97
171
  begin
98
172
  v.respond_to?(message)
@@ -101,18 +175,22 @@ module Eqq
101
175
  end
102
176
  }
103
177
  }
178
+
179
+ Buildable.define_inspect_on(product, name: 'CAN', arguments: messages)
180
+
181
+ product
104
182
  end
105
183
 
184
+ # Product returns `true` when all patterns did not raise any exception
185
+ #
106
186
  # @param pattern1 [Proc, Method, #===]
107
187
  # @param patterns [Array<Proc, Method, #===>]
108
188
  # @return [Proc]
109
189
  def QUIET(pattern1, *patterns)
110
- patterns = [pattern1, *patterns]
111
- unless patterns.all? { |pattern| Eqq.valid?(pattern) }
112
- raise ArgumentError, 'wrong object for pattern'
113
- end
190
+ patterns = [pattern1, *patterns].freeze
191
+ Buildable.validate_patterns(*patterns)
114
192
 
115
- ->v {
193
+ product = ->v {
116
194
  patterns.all? { |pattern|
117
195
  begin
118
196
  pattern === v
@@ -123,16 +201,22 @@ module Eqq
123
201
  end
124
202
  }
125
203
  }
204
+
205
+ Buildable.define_inspect_on(product, name: 'QUIET', arguments: patterns)
206
+
207
+ product
126
208
  end
127
209
 
210
+ # Product returns `true` when the pattern raises the exception
211
+ #
128
212
  # @param mod [Module]
129
213
  # @param pattern [Proc, Method, #===]
130
214
  # @return [Proc]
131
215
  def RESCUE(mod, pattern)
132
- raise ArgumentError unless Eqq.valid?(pattern)
216
+ Buildable.validate_patterns(pattern)
133
217
  raise ArgumentError unless Module === mod
134
218
 
135
- ->v {
219
+ product = ->v {
136
220
  begin
137
221
  pattern === v
138
222
  false
@@ -142,31 +226,76 @@ module Eqq
142
226
  false
143
227
  end
144
228
  }
229
+
230
+ Buildable.define_inspect_on(product, name: 'RESCUE', arguments: [mod, pattern])
231
+
232
+ product
145
233
  end
146
234
 
147
- # @param name [Symbol, #to_sym]
235
+ # Basically provided for Enumerable
236
+ #
237
+ # @param name [Symbol, String, #to_sym]
148
238
  # @param pattern [Proc, Method, #===]
149
239
  # @return [Proc]
150
240
  def SEND(name, pattern)
151
- raise InvalidProductError unless Eqq.valid?(pattern)
241
+ name = (
242
+ begin
243
+ name.to_sym
244
+ rescue NoMethodError
245
+ raise ArgumentError
246
+ end
247
+ )
248
+ Buildable.validate_patterns(pattern)
152
249
 
153
- ->v {
250
+ product = ->v {
154
251
  v.__send__(name, pattern)
155
252
  }
253
+
254
+ Buildable.define_inspect_on(product, name: 'SEND', arguments: [name, pattern])
255
+
256
+ product
156
257
  end
157
258
 
158
- # @return [BasicObject]
259
+ EQQ_BUILTIN_ANYTHING = ->_v { true }
260
+ define_inspect_on(EQQ_BUILTIN_ANYTHING, name: 'ANYTHING', arguments: [])
261
+
262
+ # Product returns `true`, always `true`
263
+ #
264
+ # @return [Proc]
159
265
  def ANYTHING
160
- # BasicObject.=== always passing
161
- BasicObject
266
+ EQQ_BUILTIN_ANYTHING
267
+ end
268
+
269
+ EQQ_BUILTIN_NEVER = ->_v { false }
270
+ define_inspect_on(EQQ_BUILTIN_NEVER, name: 'NEVER', arguments: [])
271
+
272
+ # Product returns `false`, always `false`
273
+ #
274
+ # @return [Proc]
275
+ def NEVER
276
+ EQQ_BUILTIN_NEVER
162
277
  end
163
278
 
164
- BOOLEAN = OR(SAME(true), SAME(false))
165
- private_constant :BOOLEAN
279
+ EQQ_BUILTIN_BOOLEAN = ->v { true.equal?(v) || false.equal?(v) }
280
+ define_inspect_on(EQQ_BUILTIN_BOOLEAN, name: 'BOOLEAN', arguments: [])
166
281
 
167
- # @return [BOOLEAN]
282
+ # Product returns `true` when matched to `true` or `false`
283
+ #
284
+ # @return [Proc]
168
285
  def BOOLEAN
169
- BOOLEAN
286
+ EQQ_BUILTIN_BOOLEAN
287
+ end
288
+
289
+ EQQ_BUILTIN_NIL = ->v { nil.equal?(v) }
290
+ define_inspect_on(EQQ_BUILTIN_NIL, name: 'NIL', arguments: [])
291
+
292
+ # Product returns `true` when matched to `nil` (Not consider `nil?`)
293
+ #
294
+ # @return [Proc]
295
+ def NIL
296
+ EQQ_BUILTIN_NIL
170
297
  end
298
+
299
+ private_constant(:EQQ_BUILTIN_ANYTHING, :EQQ_BUILTIN_NEVER, :EQQ_BUILTIN_BOOLEAN, :EQQ_BUILTIN_NIL)
171
300
  end
172
301
  end
data/lib/eqq/version.rb CHANGED
@@ -2,5 +2,6 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Eqq
5
- VERSION = '0.0.2'
5
+ # This will be same as latest published gem version
6
+ VERSION = '0.0.7'
6
7
  end
data/sig/eqq.rbs CHANGED
@@ -1,3 +1,4 @@
1
+ # Pattern objects builder
1
2
  module Eqq
2
3
  interface _Patternable
3
4
  def ===: (untyped object) -> bool
@@ -7,43 +8,114 @@ module Eqq
7
8
  def to_sym: -> Symbol
8
9
  end
9
10
 
11
+ interface _Inspectable
12
+ def inspect: () -> String
13
+ end
14
+
10
15
  module Buildable
11
- # A pribate constant. Should not be used in your code.
12
- BOOLEAN: ^(untyped object) -> bool
13
-
14
- extend Buildable
15
- def OR: (_Patternable, _Patternable, *_Patternable) -> ^(untyped object) -> bool
16
- def AND: (_Patternable, _Patternable, *_Patternable) -> ^(untyped object) -> bool
17
- def NAND: (_Patternable, _Patternable, *_Patternable) -> ^(untyped object) -> bool
18
- def NOR: (_Patternable, _Patternable, *_Patternable) -> ^(untyped object) -> bool
19
- def XOR: (_Patternable, _Patternable, *_Patternable) -> ^(untyped object) -> bool
20
- def XNOR: (_Patternable, _Patternable, *_Patternable) -> ^(untyped object) -> bool
21
- def NOT: (_Patternable) -> ^(untyped object) -> bool
22
- def EQ: (untyped object) -> ^(untyped object) -> bool
23
- def SAME: (untyped object) -> ^(untyped object) -> bool
24
- def CAN: (_ToSym, *_ToSym) -> ^(untyped object) -> bool
25
- def RESCUE: (Module, _Patternable) -> ^(untyped object) -> bool
26
- def QUIET: (_Patternable, *_Patternable) -> ^(untyped object) -> bool
27
- def SEND: (Symbol | String name, _Patternable) -> ^(untyped object) -> bool
28
- def ANYTHING: () -> BasicObject
29
- def BOOLEAN: () -> ^(untyped object) -> bool
16
+ type patternable_lambda = ^(untyped object) -> bool
17
+ type product = patternable_lambda & _Inspectable
18
+
19
+ # A private constant. Should not be used in your code.
20
+ EQQ_BUILTIN_ANYTHING: product
21
+
22
+ # A private constant. Should not be used in your code.
23
+ EQQ_BUILTIN_NEVER: product
24
+
25
+ # A private constant. Should not be used in your code.
26
+ EQQ_BUILTIN_BOOLEAN: product
27
+
28
+ # A private constant. Should not be used in your code.
29
+ EQQ_BUILTIN_NIL: product
30
+
31
+ # A private API. Should not be used in your code.
32
+ def self.safe_inspect_for: (untyped object)-> String
33
+
34
+ # A private API. Should not be used in your code.
35
+ def self.define_inspect_on: (patternable_lambda product, name: String, arguments: Array[untyped])-> void
36
+
37
+ # A private API. Should not be used in your code.
38
+ def self.validate_patterns: (*untyped) -> void
39
+
40
+ # Product returns `true` when matched even one pattern
41
+ def OR: (_Patternable, _Patternable, *_Patternable) -> product
42
+
43
+ # Product returns `true` when matched all patterns
44
+ def AND: (_Patternable, _Patternable, *_Patternable) -> product
45
+
46
+ # Product is an inverted `AND`
47
+ def NAND: (_Patternable, _Patternable, *_Patternable) -> product
48
+
49
+ # Product is an inverted `OR`
50
+ def NOR: (_Patternable, _Patternable, *_Patternable) -> product
51
+
52
+ # Product returns `true` when matched one of the pattern, when matched both returns `false`
53
+ def XOR: (_Patternable, _Patternable) -> product
54
+
55
+ # Product returns `true` when not matched the pattern
56
+ def NOT: (_Patternable) -> product
57
+
58
+ # Product returns `true` when matched with `#==`
59
+ def EQ: (untyped object) -> product
60
+
61
+ # Product returns `true` when matched with `#equal?`
62
+ def SAME: (untyped object) -> product
63
+
64
+ # Product returns `true` when it has all of the methods (checked with `respond_to?`)
65
+ def CAN: (_ToSym, *_ToSym) -> product
66
+
67
+ # Product returns `true` when the pattern raises the exception
68
+ def RESCUE: (Module, _Patternable) -> product
69
+
70
+ # Product returns `true` when all patterns did not raise any exception
71
+ def QUIET: (_Patternable, *_Patternable) -> product
72
+
73
+ # Basically provided for Enumerable
74
+ def SEND: (Symbol | String name, _Patternable) -> product
75
+
76
+ # Product returns `true`, always `true`
77
+ def ANYTHING: () -> product
78
+
79
+ # Product returns `false`, always `false`
80
+ def NEVER: () -> product
81
+
82
+ # Product returns `true` when matched to `true` or `false`
83
+ def BOOLEAN: () -> product
84
+
85
+ # Product returns `true` when matched to `nil` (Not consider `nil?`)
86
+ def NIL: () -> product
30
87
  end
31
88
 
32
89
  extend Buildable
33
90
 
91
+ # Base error of this library
34
92
  class Error < StandardError
35
93
  end
36
94
 
95
+ # Raised when found some products are invalid as a pattern object
37
96
  class InvalidProductError < Error
38
97
  end
39
98
 
40
- # A pribate API. Should not be used in your code.
99
+ # A private API. Should not be used in your code.
41
100
  class DSLScope
42
101
  include Buildable
43
102
  end
44
103
 
45
104
  VERSION: String
46
105
 
106
+ # Returns `true` when given object has patternable signature
107
+ def self.pattern?: (untyped object) -> bool
108
+
109
+ # Alias of `pattern?`. But deperecated. Do not use in your code anymore.
47
110
  def self.valid?: (untyped object) -> bool
111
+
112
+ # Returns `true` when given object has correct signature as a product of builders
113
+ # Basically this is a private API. Should not be used in your code.
114
+ def self.satisfy?: (untyped object) -> bool
115
+
116
+ # In the block scope, all builder methods can be used without receiver
117
+ def self.build: { () -> _Patternable } -> _Patternable
118
+
119
+ # Alias of `build`. But deperecated. Do not use in your code anymore.
48
120
  def self.define: { () -> _Patternable } -> _Patternable
49
121
  end
metadata CHANGED
@@ -1,16 +1,23 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eqq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenichi Kamiya
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-01 00:00:00.000000000 Z
11
+ date: 2021-06-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: " [4.2, 42, 42.0, 420].grep(Eqq.AND(Integer, 20..50)) #=> [42]\n"
13
+ description: |2
14
+ Pattern objects builder.
15
+
16
+ All products can be used as `pattern === something`.
17
+
18
+ All products can be mixed with other products as a parts.
19
+
20
+ Reuse as you wish!
14
21
  email:
15
22
  - kachick1+ruby@gmail.com
16
23
  executables: []
@@ -49,5 +56,5 @@ requirements: []
49
56
  rubygems_version: 3.2.15
50
57
  signing_key:
51
58
  specification_version: 4
52
- summary: Pattern objects builder. `eqq` means `#===`
59
+ summary: Pattern objects builder
53
60
  test_files: []