typ 0.0.6 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/typ.rb +198 -127
  3. metadata +7 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a726dc4e0d96b4f5bdad9858d10063bf818af3e5bd1293135acffa040bbde236
4
- data.tar.gz: fbc8d499fb78954604a757593e2e46a9e2af7f5fba4102783d6011aa991a10f3
3
+ metadata.gz: 3292265f2d79043b1324f8221a43926863cb039233c48d5d989109fd712a9141
4
+ data.tar.gz: d81287849ec606b02f4710dcc9d86c822ad5f162fda839c23c5a84225fa91718
5
5
  SHA512:
6
- metadata.gz: 2d3679f431008960d32befdaea22720e3a3cf49692c7a81f19463476b8cae6d67c8069d3920c1325a3c68d743058a348f2087295219f75bde0261bb780b95cdd
7
- data.tar.gz: 20af3243c88900e428928f2c770cb661ee69835187fb0834f55d7be701ab3cfbf0f848b2a854f8998e42cd85291c4551da5b6eaf7ceb7946d63f71aadc823bfb
6
+ metadata.gz: 4f6fa03315316cf839a3560dfb10197879d673a88c42823ed55a8e4daecd3c66f09a3393fc33b9b240ef9fb9a142a617a46bf03d62ead3dc5b6de662d1b53495
7
+ data.tar.gz: eba82e7d4741e2f1b489f383b4ea0423b24348a218a1e858291e7855e472b3c07c9440bd84769bd63ff8e74f88a113ebbee19ce3ebee8eddbcbf65bddfede41f
data/lib/typ.rb CHANGED
@@ -1,15 +1,80 @@
1
1
  module Typ
2
+ module ArrayPredicate
3
+ refine Array do
4
+ def predicate?
5
+ (size == 2) &&
6
+ (self[0].is_a?(Symbol) || self[1].is_a?(Symbol))
7
+ end
8
+ end
9
+ end
10
+
11
+ module ArrayToTest
12
+ refine Object do
13
+ def bad_assertion it, name
14
+ fail Typ::Error::BadAssertion.new(it, name)
15
+ end
16
+ end
17
+
18
+ refine Array do
19
+ def to_test
20
+ type = self
21
+
22
+ if type[0].is_a? Symbol
23
+ method, argument = type
24
+ -> it { it.send method, argument or bad_assertion(it, type) }
25
+ else
26
+ receiver, method = type
27
+ -> it { receiver.send method, it or bad_assertion(it, type) }
28
+ end
29
+ end
30
+ end
31
+ end
32
+
2
33
  module Gate
3
- attr_reader :it
34
+ module DSLReaders
35
+ def dsl_method
36
+ self.class.dsl_method
37
+ end
38
+
39
+ def dsl_literal
40
+ self.class.dsl_literal
41
+ end
42
+
43
+ def dsl_key
44
+ self.class.dsl_key
45
+ end
46
+ end
47
+
48
+ module New
49
+ def new
50
+ c = Class.new
51
+ c.include Gate
52
+ c.extend Singleton
53
+ c
54
+ end
55
+
56
+ end
57
+
58
+ module Singleton
59
+ attr_accessor :dsl_method, :dsl_literal, :dsl_key
60
+ end
61
+
62
+ extend New
63
+ include DSLReaders
64
+
65
+ attr_reader :it, :error
4
66
 
5
67
  def initialize it
6
68
  @it = it
7
- check
69
+ @ok = begin
70
+ check
71
+ rescue => e
72
+ @error = e
73
+ false
74
+ end
8
75
  end
9
76
 
10
- # Should set @ok to be true or false
11
77
  def check
12
- @ok = self.class.check === it
13
78
  end
14
79
 
15
80
  def ok?
@@ -17,9 +82,12 @@ module Typ
17
82
  end
18
83
  end
19
84
 
85
+ using ArrayPredicate
86
+ using ArrayToTest
87
+
20
88
  def self.included mod
21
89
  mod.extend DSL
22
- mod.extend PatternMatching
90
+ mod.extend Singleton
23
91
  end
24
92
 
25
93
  include Gate
@@ -29,165 +97,168 @@ module Typ
29
97
  def check
30
98
  @gates = self.class.gates.map { |gate| gate.new it }
31
99
  @fails = gates.reject &:ok?
32
- @ok = fails.empty?
100
+ fails.empty?
33
101
  end
34
102
 
35
103
  module DSL
36
- def gates
37
- @gates ||= []
38
- end
39
-
40
- def is type
41
- case type
42
- when Array
43
- gates << Is::Array.new(type)
44
- when Class
45
- if type.include? Typ
46
- gates << type
47
- else
48
- fail "don't know how to create a Gate from #{type}"
104
+ class Gate
105
+ module CheckMethod
106
+ def augment_gate_with_check test
107
+ check = Module.new do
108
+ define_method :check do
109
+ test[it]
110
+ end
111
+ end
112
+
113
+ gate.include check
49
114
  end
50
- else
51
- fail "don't know how to create a Gate from #{type}"
52
115
  end
53
- end
54
116
 
55
- def is_a type, params = {}
56
- case type
57
- when Module
58
- gates << IsA.new(type, params)
59
- else
60
- fail "don't know how to create a Gate from #{type}"
61
- end
62
- end
63
- end
64
-
65
- module Is
66
-
67
- module Array
68
- class Check
69
- def initialize array
70
- @array = array
71
- @check = if array[0].is_a?(Symbol)
72
- method, *arguments = array
73
- -> it { it.send method, *arguments }
74
- elsif array[1].is_a?(Symbol)
75
- receiver, method = array
76
- -> it { receiver.send method, it }
77
- else
78
- fail "not sure how to handle #{array} yet"
117
+ module TestFor
118
+ def test_for type
119
+ case type
120
+ when Symbol
121
+ -> it { it.send type or bad_assertion(it, type) }
122
+ when Array
123
+ type.predicate? ? type.to_test : (cannot_create_gate type)
124
+ when Class
125
+ type if type.include? Typ
79
126
  end
80
127
  end
81
-
82
- def === it
83
- @check === it
84
- end
85
-
86
- def to_a
87
- @array
128
+
129
+ def cannot_create_gate type
130
+ fail Typ::Error::CannotCreateGate.new(type)
88
131
  end
89
132
  end
90
-
91
- class << self
92
- def new array
93
- check = Check.new array
94
-
95
- gate = Class.new
96
- gate.include self
97
- gate.check = check
98
- gate
99
- end
133
+
134
+ def initialize method, literal, **kwargs
135
+ @method, @literal, @kwargs = method, literal, kwargs
136
+ make
100
137
  end
101
138
 
102
- def self.included gate
103
- gate.extend Singleton
139
+ def gate
140
+ @gate ||= Typ::Gate.new
104
141
  end
105
142
 
106
- module Singleton
107
- attr_accessor :check
143
+ def make
108
144
  end
109
145
 
110
- def to_a
111
- self.class.check.to_a
112
- end
146
+ include TestFor
147
+ include CheckMethod
113
148
 
114
- include Gate
149
+ def enrich_gate
150
+ augment_gate_with_check @test
151
+ gate.dsl_method = @method
152
+ gate.dsl_literal = @literal
153
+ gate.dsl_key = @kwargs[:name]
154
+ end
155
+ end
156
+
157
+ def gates
158
+ @gates ||= []
115
159
  end
116
- end
117
-
118
- module IsA
119
- class << self
120
- def new type, params = {}
121
- type = Type.new type, params
122
160
 
123
- gate = Class.new
124
- gate.include self
125
- gate.check = type
126
- gate
127
- end
161
+ def is literal
162
+ gates << Is.new(__method__, literal).gate
128
163
  end
129
164
 
130
- def self.included gate
131
- gate.extend Singleton
165
+ def is_a literal
166
+ gates << IsA.new(__method__, literal).gate
132
167
  end
133
168
 
134
- module Singleton
135
- attr_accessor :check
169
+ def its name, literal
170
+ gates << Its.new(__method__, literal, name: name).gate
136
171
  end
137
172
 
138
- include Gate
173
+ def key name, literal
174
+ gates << Key.new(__method__, literal, name: name).gate
175
+ end
139
176
 
140
- class Type
141
- def initialize type, params = {}
142
- @type, @params = type, params
143
-
144
- @param = params[:of]
145
-
146
- @check = if @params.empty?
147
- -> it { it.is_a? @type }
148
- else
149
- if @param
150
- check_Array
151
- else
152
- check_Hash
153
- end
154
- end
177
+ class FetchGate < Gate
178
+ def make
179
+ type_check = test_for @literal
180
+ @test = fetch_check >> type_check
181
+ enrich_gate
155
182
  end
156
183
 
157
- def === it
158
- @check === it
159
- end
160
-
161
- def to_s
162
- if @params.empty?
163
- @type.to_s
184
+ def test_for literal
185
+ case literal
186
+ when Symbol
187
+ literal.end_with?(??) ? super : (super [:eql?, literal])
188
+ when Array
189
+ literal.predicate? ? literal.to_test : (super [:eql?, literal])
190
+ when Class
191
+ literal.include?(Typ) ? super : (super [:eql?, literal])
164
192
  else
165
- "#{@type}, #{@params}"
193
+ super [:eql?, literal]
166
194
  end
167
195
  end
196
+ end
197
+
198
+ class Is < Gate
199
+ def make
200
+ @test = test_for @literal
168
201
 
169
- private
170
- def check_Array
171
- -> it {
172
- it.is_a?(@type) &&
173
- it.all? { |element| element.is_a? @param }
174
- }
175
- end
176
-
177
- def check_Hash
178
- key_type, value_type = @params.first
179
- -> it {
180
- it.is_a?(@type) &&
181
- it.keys.all? {|k| k.is_a? key_type } &&
182
- it.values.all? {|v| v.is_a? value_type }
183
- }
202
+ if @test
203
+ if Class === @literal
204
+ @gate = @literal
205
+ else
206
+ enrich_gate
207
+ end
208
+ else
209
+ cannot_create_gate @literal
184
210
  end
211
+ end
212
+ end
213
+
214
+ class IsA < Gate
215
+ def make
216
+ @test = test_for [:is_a?, @literal]
217
+ enrich_gate
218
+ end
219
+ end
220
+
221
+ class Its < FetchGate
222
+ def fetch_check
223
+ @fetch_check ||= begin
224
+ name = @kwargs[:name]
225
+ -> it { it.send name }
226
+ end
227
+ end
228
+ end
229
+
230
+ class Key < FetchGate
231
+ def fetch_check
232
+ @fetch_check ||= begin
233
+ name = @kwargs[:name]
234
+ -> it { it[name] }
235
+ end
236
+ end
185
237
  end
186
238
  end
187
239
 
188
- module PatternMatching
189
- def === it
240
+ class Error < StandardError
241
+
242
+ class BadAssertion < self
243
+ def initialize it, method_name
244
+ message = "#{it.inspect} is #{method_name}"
245
+ super message
246
+ end
247
+ end
248
+
249
+ class CannotCreateGate < self
250
+ def initialize object
251
+ message = "Don't know how to create a gate from #{object.inspect}:#{object.class}."
252
+ super message
253
+ end
254
+ end
255
+ end
256
+
257
+ module Singleton
258
+ def call it
190
259
  new(it).ok?
191
260
  end
261
+
262
+ alias_method :===, :call
192
263
  end
193
264
  end
metadata CHANGED
@@ -1,17 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typ
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
- - Anatoly Chernow
7
+ - Anatoly Chernov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-03 00:00:00.000000000 Z
11
+ date: 2023-08-07 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
- email:
14
+ email:
15
+ - chertoly@gmail.com
15
16
  executables: []
16
17
  extensions: []
17
18
  extra_rdoc_files: []
@@ -35,9 +36,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
35
36
  - !ruby/object:Gem::Version
36
37
  version: '0'
37
38
  requirements: []
38
- rubyforge_project:
39
- rubygems_version: 2.7.6
39
+ rubygems_version: 3.4.15
40
40
  signing_key:
41
41
  specification_version: 4
42
- summary: A tool for defining and enforcing types of Ruby objects.
42
+ summary: To type Ruby objects.
43
43
  test_files: []