literal 1.1.0 → 1.3.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/lib/literal/array.rb +544 -0
- data/lib/literal/data_structure.rb +0 -10
- data/lib/literal/deferred_type.rb +23 -0
- data/lib/literal/flags.rb +17 -4
- data/lib/literal/hash.rb +48 -0
- data/lib/literal/properties/schema.rb +2 -2
- data/lib/literal/properties.rb +5 -0
- data/lib/literal/property.rb +1 -1
- data/lib/literal/rails/flags_type.rb +41 -0
- data/lib/literal/rails.rb +1 -0
- data/lib/literal/railtie.rb +8 -0
- data/lib/literal/set.rb +48 -0
- data/lib/literal/struct.rb +26 -0
- data/lib/literal/transforms.rb +142 -0
- data/lib/literal/type.rb +7 -0
- data/lib/literal/types/any_type.rb +13 -3
- data/lib/literal/types/array_type.rb +18 -1
- data/lib/literal/types/boolean_type.rb +18 -3
- data/lib/literal/types/class_type.rb +20 -1
- data/lib/literal/types/constraint_type.rb +42 -1
- data/lib/literal/types/descendant_type.rb +18 -1
- data/lib/literal/types/enumerable_type.rb +18 -1
- data/lib/literal/types/falsy_type.rb +22 -3
- data/lib/literal/types/frozen_type.rb +35 -1
- data/lib/literal/types/hash_type.rb +22 -1
- data/lib/literal/types/interface_type.rb +31 -1
- data/lib/literal/types/intersection_type.rb +27 -0
- data/lib/literal/types/json_data_type.rb +49 -3
- data/lib/literal/types/map_type.rb +23 -5
- data/lib/literal/types/never_type.rb +18 -3
- data/lib/literal/types/nilable_type.rb +24 -1
- data/lib/literal/types/not_type.rb +22 -1
- data/lib/literal/types/range_type.rb +18 -1
- data/lib/literal/types/set_type.rb +28 -1
- data/lib/literal/types/truthy_type.rb +17 -3
- data/lib/literal/types/tuple_type.rb +19 -2
- data/lib/literal/types/union_type.rb +27 -3
- data/lib/literal/types/void_type.rb +13 -3
- data/lib/literal/types.rb +58 -51
- data/lib/literal/version.rb +1 -1
- data/lib/literal.rb +38 -5
- metadata +9 -9
- data/lib/literal/types/callable_type.rb +0 -12
- data/lib/literal/types/float_type.rb +0 -10
- data/lib/literal/types/integer_type.rb +0 -10
- data/lib/literal/types/lambda_type.rb +0 -12
- data/lib/literal/types/procable_type.rb +0 -12
- data/lib/literal/types/string_type.rb +0 -10
- data/lib/literal/types/symbol_type.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9721432521677aa431dda4e94240521a54a8ac21ece07fef009393544d19214d
|
4
|
+
data.tar.gz: c5b41c95f4c24ff4fad28869bf61ff93174118a2d3e5890928961b382bf9b285
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 715a03576aed152e2fd5737236eb227dd98da9f02b421a14722395a3b9992dc667302574490955f0f9d81192dc5f64f793d916b196bc4509244afad5daa8a37b
|
7
|
+
data.tar.gz: 475df2645d537e5c8151ba6431e1469fdcfdd1a80d766489bfa00b135f3c3e57a86b0c09c7e6738c6033609a69864a596660a0b5498bd6762e314588a67bac35
|
@@ -0,0 +1,544 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Literal::Array
|
4
|
+
class Generic
|
5
|
+
include Literal::Type
|
6
|
+
|
7
|
+
def initialize(type)
|
8
|
+
@type = type
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :type
|
12
|
+
|
13
|
+
def new(*value)
|
14
|
+
Literal::Array.new(value, type: @type)
|
15
|
+
end
|
16
|
+
|
17
|
+
alias_method :[], :new
|
18
|
+
|
19
|
+
def ===(value)
|
20
|
+
Literal::Array === value && Literal.subtype?(value.__type__, of: @type)
|
21
|
+
end
|
22
|
+
|
23
|
+
def >=(other)
|
24
|
+
case other
|
25
|
+
when Literal::Array::Generic
|
26
|
+
@type >= other.type
|
27
|
+
else
|
28
|
+
false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def inspect
|
33
|
+
"Literal::Array(#{@type.inspect})"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
include Enumerable
|
38
|
+
include Literal::Types
|
39
|
+
|
40
|
+
def initialize(value, type:)
|
41
|
+
Literal.check(actual: value, expected: _Array(type)) do |c|
|
42
|
+
c.fill_receiver(receiver: self, method: "#initialize")
|
43
|
+
end
|
44
|
+
|
45
|
+
@__type__ = type
|
46
|
+
@__value__ = value
|
47
|
+
end
|
48
|
+
|
49
|
+
def __initialize_without_check__(value, type:)
|
50
|
+
@__type__ = type
|
51
|
+
@__value__ = value
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
# Used to create a new Literal::Array with the same type and collection type but a new value. The value is not checked.
|
56
|
+
def __with__(value)
|
57
|
+
Literal::Array.allocate.__initialize_without_check__(
|
58
|
+
value,
|
59
|
+
type: @__type__,
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
attr_reader :__type__, :__value__
|
64
|
+
|
65
|
+
def &(other)
|
66
|
+
case other
|
67
|
+
when ::Array
|
68
|
+
__with__(@__value__ & other)
|
69
|
+
when Literal::Array
|
70
|
+
__with__(@__value__ & other.__value__)
|
71
|
+
else
|
72
|
+
raise ArgumentError.new("Cannot perform bitwise AND with #{other.class.name}.")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def *(times)
|
77
|
+
case times
|
78
|
+
when String
|
79
|
+
@__value__ * times
|
80
|
+
else
|
81
|
+
__with__(@__value__ * times)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def +(other)
|
86
|
+
case other
|
87
|
+
when ::Array
|
88
|
+
Literal.check(actual: other, expected: _Array(@__type__)) do |c|
|
89
|
+
c.fill_receiver(receiver: self, method: "#+")
|
90
|
+
end
|
91
|
+
|
92
|
+
__with__(@__value__ + other)
|
93
|
+
when Literal::Array(@__type__)
|
94
|
+
__with__(@__value__ + other.__value__)
|
95
|
+
when Literal::Array
|
96
|
+
raise Literal::TypeError.new(
|
97
|
+
context: Literal::TypeError::Context.new(
|
98
|
+
expected: Literal::Array(@__type__),
|
99
|
+
actual: other
|
100
|
+
)
|
101
|
+
)
|
102
|
+
else
|
103
|
+
raise ArgumentError.new("Cannot perform `+` with #{other.class.name}.")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def -(other)
|
108
|
+
case other
|
109
|
+
when ::Array
|
110
|
+
__with__(@__value__ - other)
|
111
|
+
when Literal::Array
|
112
|
+
__with__(@__value__ - other.__value__)
|
113
|
+
else
|
114
|
+
raise ArgumentError.new("Cannot perform `-` with #{other.class.name}.")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def <<(value)
|
119
|
+
Literal.check(actual: value, expected: @__type__) do |c|
|
120
|
+
c.fill_receiver(receiver: self, method: "#<<")
|
121
|
+
end
|
122
|
+
|
123
|
+
@__value__ << value
|
124
|
+
self
|
125
|
+
end
|
126
|
+
|
127
|
+
def <=>(other)
|
128
|
+
case other
|
129
|
+
when ::Array
|
130
|
+
@__value__ <=> other
|
131
|
+
when Literal::Array
|
132
|
+
@__value__ <=> other.__value__
|
133
|
+
else
|
134
|
+
raise ArgumentError.new("Cannot perform `<=>` with #{other.class.name}.")
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def ==(other)
|
139
|
+
Literal::Array === other && @__value__ == other.__value__
|
140
|
+
end
|
141
|
+
|
142
|
+
def [](index)
|
143
|
+
@__value__[index]
|
144
|
+
end
|
145
|
+
|
146
|
+
def []=(index, value)
|
147
|
+
Literal.check(actual: value, expected: @__type__) do |c|
|
148
|
+
c.fill_receiver(receiver: self, method: "#[]=")
|
149
|
+
end
|
150
|
+
|
151
|
+
@__value__[index] = value
|
152
|
+
end
|
153
|
+
|
154
|
+
def all?(...)
|
155
|
+
@__value__.all?(...)
|
156
|
+
end
|
157
|
+
|
158
|
+
def any?(...)
|
159
|
+
@__value__.any?(...)
|
160
|
+
end
|
161
|
+
|
162
|
+
def assoc(...)
|
163
|
+
@__value__.assoc(...)
|
164
|
+
end
|
165
|
+
|
166
|
+
def at(...)
|
167
|
+
@__value__.at(...)
|
168
|
+
end
|
169
|
+
|
170
|
+
def bsearch(...)
|
171
|
+
@__value__.bsearch(...)
|
172
|
+
end
|
173
|
+
|
174
|
+
def clear(...)
|
175
|
+
@__value__.clear(...)
|
176
|
+
self
|
177
|
+
end
|
178
|
+
|
179
|
+
def combination(...)
|
180
|
+
@__value__.combination(...)
|
181
|
+
self
|
182
|
+
end
|
183
|
+
|
184
|
+
def compact
|
185
|
+
# @TODO if this is an array of nils, we should return an emtpy array
|
186
|
+
__with__(@__value__)
|
187
|
+
end
|
188
|
+
|
189
|
+
def compact!
|
190
|
+
# @TODO if this is an array of nils, we should set @__value__ = [] and return self
|
191
|
+
nil
|
192
|
+
end
|
193
|
+
|
194
|
+
def count(...)
|
195
|
+
@__value__.count(...)
|
196
|
+
end
|
197
|
+
|
198
|
+
def delete(...)
|
199
|
+
@__value__.delete(...)
|
200
|
+
end
|
201
|
+
|
202
|
+
def delete_at(...)
|
203
|
+
@__value__.delete_at(...)
|
204
|
+
end
|
205
|
+
|
206
|
+
def delete_if(...)
|
207
|
+
@__value__.delete_if(...)
|
208
|
+
self
|
209
|
+
end
|
210
|
+
|
211
|
+
def dig(...)
|
212
|
+
@__value__.dig(...)
|
213
|
+
end
|
214
|
+
|
215
|
+
def drop(...)
|
216
|
+
__with__(@__value__.drop(...))
|
217
|
+
end
|
218
|
+
|
219
|
+
def drop_while(...)
|
220
|
+
__with__(@__value__.drop_while(...))
|
221
|
+
end
|
222
|
+
|
223
|
+
def each(...)
|
224
|
+
@__value__.each(...)
|
225
|
+
end
|
226
|
+
|
227
|
+
def empty?
|
228
|
+
@__value__.empty?
|
229
|
+
end
|
230
|
+
|
231
|
+
alias_method :eql?, :==
|
232
|
+
|
233
|
+
def filter(...)
|
234
|
+
__with__(@__value__.filter(...))
|
235
|
+
end
|
236
|
+
|
237
|
+
def filter!(...)
|
238
|
+
@__value__.filter!(...)
|
239
|
+
self
|
240
|
+
end
|
241
|
+
|
242
|
+
def flatten(...)
|
243
|
+
__with__(@__value__.flatten(...))
|
244
|
+
end
|
245
|
+
|
246
|
+
def first(...)
|
247
|
+
@__value__.first(...)
|
248
|
+
end
|
249
|
+
|
250
|
+
def flatten!(...)
|
251
|
+
@__value__.flatten!(...) ? self : nil
|
252
|
+
end
|
253
|
+
|
254
|
+
def freeze
|
255
|
+
@__value__.freeze
|
256
|
+
super
|
257
|
+
end
|
258
|
+
|
259
|
+
alias_method :index, :find_index
|
260
|
+
|
261
|
+
def insert(index, *value)
|
262
|
+
Literal.check(actual: value, expected: _Array(@__type__)) do |c|
|
263
|
+
c.fill_receiver(receiver: self, method: "#insert")
|
264
|
+
end
|
265
|
+
|
266
|
+
@__value__.insert(index, *value)
|
267
|
+
self
|
268
|
+
end
|
269
|
+
|
270
|
+
def inspect
|
271
|
+
@__value__.inspect
|
272
|
+
end
|
273
|
+
|
274
|
+
def intersect?(other)
|
275
|
+
case other
|
276
|
+
when ::Array
|
277
|
+
@__value__.intersect?(other)
|
278
|
+
when Literal::Array
|
279
|
+
@__value__.intersect?(other.__value__)
|
280
|
+
else
|
281
|
+
raise ArgumentError.new("Cannot perform `intersect?` with #{other.class.name}.")
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
def intersection(*values)
|
286
|
+
values.map! do |value|
|
287
|
+
case value
|
288
|
+
when Literal::Array
|
289
|
+
value.__value__
|
290
|
+
else
|
291
|
+
value
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
__with__(@__value__.intersection(*values))
|
296
|
+
end
|
297
|
+
|
298
|
+
def join(...)
|
299
|
+
@__value__.join(...)
|
300
|
+
end
|
301
|
+
|
302
|
+
def keep_if(...)
|
303
|
+
return_value = @__value__.keep_if(...)
|
304
|
+
case return_value
|
305
|
+
when Array
|
306
|
+
self
|
307
|
+
else
|
308
|
+
return_value
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
def last(...)
|
313
|
+
@__value__.last(...)
|
314
|
+
end
|
315
|
+
|
316
|
+
def length(...)
|
317
|
+
@__value__.length(...)
|
318
|
+
end
|
319
|
+
|
320
|
+
def map(type, &block)
|
321
|
+
my_type = @__type__
|
322
|
+
transform_type = Literal::TRANSFORMS.dig(my_type, block)
|
323
|
+
|
324
|
+
if transform_type && Literal.subtype?(transform_type, of: my_type)
|
325
|
+
Literal::Array.allocate.__initialize_without_check__(
|
326
|
+
@__value__.map(&block),
|
327
|
+
type:,
|
328
|
+
)
|
329
|
+
else
|
330
|
+
Literal::Array.new(@__value__.map(&block), type:)
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
alias_method :collect, :map
|
335
|
+
|
336
|
+
# TODO: we can make this faster
|
337
|
+
def map!(&)
|
338
|
+
new_array = map(@__type__, &)
|
339
|
+
@__value__ = new_array.__value__
|
340
|
+
self
|
341
|
+
end
|
342
|
+
|
343
|
+
alias_method :collect!, :map!
|
344
|
+
|
345
|
+
def sum(...)
|
346
|
+
@__value__.sum(...)
|
347
|
+
end
|
348
|
+
|
349
|
+
def max(n = nil, &)
|
350
|
+
if n
|
351
|
+
__with__(@__value__.max(n, &))
|
352
|
+
else
|
353
|
+
@__value__.max(&)
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
def min(n = nil, &)
|
358
|
+
if n
|
359
|
+
__with__(@__value__.min(n, &))
|
360
|
+
else
|
361
|
+
@__value__.min(&)
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
def minmax(...)
|
366
|
+
__with__(@__value__.minmax(...))
|
367
|
+
end
|
368
|
+
|
369
|
+
def narrow(type)
|
370
|
+
unless Literal.subtype?(type, of: @__type__)
|
371
|
+
raise ArgumentError.new("Cannot narrow #{@__type__} to #{type}")
|
372
|
+
end
|
373
|
+
|
374
|
+
if __type__ != type
|
375
|
+
@__value__.each do |item|
|
376
|
+
Literal.check(actual: item, expected: type) do |c|
|
377
|
+
c.fill_receiver(receiver: self, method: "#narrow")
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
Literal::Array.allocate.__initialize_without_check__(
|
383
|
+
@__value__,
|
384
|
+
type:,
|
385
|
+
)
|
386
|
+
end
|
387
|
+
|
388
|
+
def one?(...)
|
389
|
+
@__value__.one?(...)
|
390
|
+
end
|
391
|
+
|
392
|
+
def pop(...)
|
393
|
+
@__value__.pop(...)
|
394
|
+
end
|
395
|
+
|
396
|
+
def push(*value)
|
397
|
+
Literal.check(actual: value, expected: _Array(@__type__)) do |c|
|
398
|
+
c.fill_receiver(receiver: self, method: "#push")
|
399
|
+
end
|
400
|
+
|
401
|
+
@__value__.push(*value)
|
402
|
+
self
|
403
|
+
end
|
404
|
+
|
405
|
+
alias_method :append, :push
|
406
|
+
|
407
|
+
def reject(...)
|
408
|
+
__with__(@__value__.reject(...))
|
409
|
+
end
|
410
|
+
|
411
|
+
def reject!(...)
|
412
|
+
@__value__.reject!(...)
|
413
|
+
self
|
414
|
+
end
|
415
|
+
|
416
|
+
def replace(value)
|
417
|
+
case value
|
418
|
+
when Array
|
419
|
+
Literal.check(actual: value, expected: _Array(@__type__)) do |c|
|
420
|
+
c.fill_receiver(receiver: self, method: "#replace")
|
421
|
+
end
|
422
|
+
|
423
|
+
@__value__.replace(value)
|
424
|
+
when Literal::Array(@__type__)
|
425
|
+
@__value__.replace(value.__value__)
|
426
|
+
when Literal::Array
|
427
|
+
raise Literal::TypeError.new(
|
428
|
+
context: Literal::TypeError::Context.new(expected: @__type__, actual: value.__type__)
|
429
|
+
)
|
430
|
+
else
|
431
|
+
raise ArgumentError.new("#replace expects Array argument")
|
432
|
+
end
|
433
|
+
|
434
|
+
self
|
435
|
+
end
|
436
|
+
|
437
|
+
def sample(...)
|
438
|
+
@__value__.sample(...)
|
439
|
+
end
|
440
|
+
|
441
|
+
def select(...)
|
442
|
+
__with__(@__value__.select(...))
|
443
|
+
end
|
444
|
+
|
445
|
+
def select!(...)
|
446
|
+
@__value__.select!(...)
|
447
|
+
end
|
448
|
+
|
449
|
+
def shift(...)
|
450
|
+
@__value__.shift(...)
|
451
|
+
end
|
452
|
+
|
453
|
+
def size(...)
|
454
|
+
@__value__.size(...)
|
455
|
+
end
|
456
|
+
|
457
|
+
def sort(...)
|
458
|
+
__with__(@__value__.sort(...))
|
459
|
+
end
|
460
|
+
|
461
|
+
def sort!(...)
|
462
|
+
@__value__.sort!(...)
|
463
|
+
self
|
464
|
+
end
|
465
|
+
|
466
|
+
def to_a
|
467
|
+
@__value__.dup
|
468
|
+
end
|
469
|
+
|
470
|
+
alias_method :to_ary, :to_a
|
471
|
+
|
472
|
+
alias_method :to_s, :inspect
|
473
|
+
|
474
|
+
def uniq
|
475
|
+
__with__(@__value__.uniq)
|
476
|
+
end
|
477
|
+
|
478
|
+
def uniq!(...)
|
479
|
+
@__value__.uniq!(...) ? self : nil
|
480
|
+
end
|
481
|
+
|
482
|
+
def unshift(value)
|
483
|
+
Literal.check(actual: value, expected: @__type__) do |c|
|
484
|
+
c.fill_receiver(receiver: self, method: "#unshift")
|
485
|
+
end
|
486
|
+
|
487
|
+
@__value__.unshift(value)
|
488
|
+
self
|
489
|
+
end
|
490
|
+
|
491
|
+
alias_method :prepend, :unshift
|
492
|
+
|
493
|
+
def values_at(*indexes)
|
494
|
+
unless @__type__ === nil
|
495
|
+
max_value = length - 1
|
496
|
+
min_value = -length
|
497
|
+
|
498
|
+
indexes.each do |index|
|
499
|
+
case index
|
500
|
+
when Integer
|
501
|
+
if index < min_value || index > max_value
|
502
|
+
raise IndexError.new("index #{index} out of range")
|
503
|
+
end
|
504
|
+
when Range
|
505
|
+
if index.begin < min_value || index.end > max_value
|
506
|
+
raise IndexError.new("index #{index} out of range")
|
507
|
+
end
|
508
|
+
else
|
509
|
+
raise ArgumentError.new("Invalid index: #{index.inspect}")
|
510
|
+
end
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
__with__(
|
515
|
+
@__value__.values_at(*indexes)
|
516
|
+
)
|
517
|
+
end
|
518
|
+
|
519
|
+
def |(other)
|
520
|
+
case other
|
521
|
+
when ::Array
|
522
|
+
Literal.check(actual: other, expected: _Array(@__type__)) do |c|
|
523
|
+
c.fill_receiver(receiver: self, method: "#|")
|
524
|
+
end
|
525
|
+
|
526
|
+
__with__(@__value__ | other)
|
527
|
+
when Literal::Array(@__type__)
|
528
|
+
__with__(@__value__ | other.__value__)
|
529
|
+
when Literal::Array
|
530
|
+
raise Literal::TypeError.new(
|
531
|
+
context: Literal::TypeError::Context.new(
|
532
|
+
expected: Literal::Array(@__type__),
|
533
|
+
actual: other
|
534
|
+
)
|
535
|
+
)
|
536
|
+
else
|
537
|
+
raise ArgumentError.new("Cannot perform `|` with #{other.class.name}.")
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
541
|
+
def fetch(...)
|
542
|
+
@__value__.fetch(...)
|
543
|
+
end
|
544
|
+
end
|
@@ -10,16 +10,6 @@ class Literal::DataStructure
|
|
10
10
|
object
|
11
11
|
end
|
12
12
|
|
13
|
-
def [](key)
|
14
|
-
instance_variable_get(:"@#{key}")
|
15
|
-
end
|
16
|
-
|
17
|
-
def []=(key, value)
|
18
|
-
# TODO: Sync error array w/ generated setter
|
19
|
-
@literal_properties[key].check(value) { |c| raise NotImplementedError }
|
20
|
-
instance_variable_set(:"@#{key}", value)
|
21
|
-
end
|
22
|
-
|
23
13
|
def to_h
|
24
14
|
{}
|
25
15
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Literal::Types::DeferredType
|
4
|
+
include Literal::Type
|
5
|
+
|
6
|
+
def initialize(&block)
|
7
|
+
@block = block
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :block
|
11
|
+
|
12
|
+
def inspect
|
13
|
+
"_Deferred"
|
14
|
+
end
|
15
|
+
|
16
|
+
def ===(other)
|
17
|
+
@block.call === other
|
18
|
+
end
|
19
|
+
|
20
|
+
def >=(other)
|
21
|
+
Literal.subtype?(other, of: @block.call)
|
22
|
+
end
|
23
|
+
end
|
data/lib/literal/flags.rb
CHANGED
@@ -9,7 +9,6 @@ class Literal::Flags
|
|
9
9
|
end
|
10
10
|
|
11
11
|
@value = value
|
12
|
-
|
13
12
|
freeze
|
14
13
|
end
|
15
14
|
|
@@ -138,6 +137,15 @@ class Literal::Flags
|
|
138
137
|
[@value].pack(self.class::PACKER)
|
139
138
|
end
|
140
139
|
|
140
|
+
def with(**attributes)
|
141
|
+
new_val = attributes.reduce(value) do |value, (k, v)|
|
142
|
+
v ? value |= bitmap(k) : value &= ~(bitmap(k))
|
143
|
+
value
|
144
|
+
end
|
145
|
+
|
146
|
+
self.class.allocate.__initialize_from_value__(new_val)
|
147
|
+
end
|
148
|
+
|
141
149
|
# () -> String
|
142
150
|
def inspect
|
143
151
|
to_h.inspect
|
@@ -156,7 +164,7 @@ class Literal::Flags
|
|
156
164
|
|
157
165
|
# (Symbol) -> Boolean
|
158
166
|
def [](key)
|
159
|
-
@value & (
|
167
|
+
@value & (bitmap(key)) > 0
|
160
168
|
end
|
161
169
|
|
162
170
|
def |(other)
|
@@ -197,14 +205,19 @@ class Literal::Flags
|
|
197
205
|
|
198
206
|
def deconstruct_keys(keys = nil)
|
199
207
|
if keys
|
200
|
-
flags = self.class::FLAGS
|
201
208
|
keys.to_h do |key|
|
202
|
-
[key, @value & (
|
209
|
+
[key, @value & (bitmap(key)) > 0]
|
203
210
|
end
|
204
211
|
else
|
205
212
|
to_h
|
206
213
|
end
|
207
214
|
end
|
215
|
+
|
216
|
+
private
|
217
|
+
|
218
|
+
def bitmap(key)
|
219
|
+
2 ** self.class::FLAGS.fetch(key)
|
220
|
+
end
|
208
221
|
end
|
209
222
|
|
210
223
|
class Literal::Flags8 < Literal::Flags
|
data/lib/literal/hash.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Literal::Hash
|
4
|
+
class Generic
|
5
|
+
def initialize(key_type, value_type)
|
6
|
+
@key_type = key_type
|
7
|
+
@value_type = value_type
|
8
|
+
end
|
9
|
+
|
10
|
+
def new(**value)
|
11
|
+
Literal::Hash.new(value, key_type: @key_type, value_type: @value_type)
|
12
|
+
end
|
13
|
+
|
14
|
+
def ===(value)
|
15
|
+
Literal::Hash === value && @type == value.__type__
|
16
|
+
end
|
17
|
+
|
18
|
+
def inspect
|
19
|
+
"Literal::Hash(#{@type.inspect})"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
include Enumerable
|
24
|
+
|
25
|
+
def initialize(value, key_type:, value_type:)
|
26
|
+
collection_type = Literal::Types::HashType.new(key_type, value_type)
|
27
|
+
|
28
|
+
Literal.check(actual: value, expected: collection_type) do |c|
|
29
|
+
c.fill_receiver(receiver: self, method: "#initialize")
|
30
|
+
end
|
31
|
+
|
32
|
+
@__key_type__ = key_type
|
33
|
+
@__value_type__ = value_type
|
34
|
+
@__value__ = value
|
35
|
+
@__collection_type__ = collection_type
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_reader :__key_type__, :__value_type__, :__value__
|
39
|
+
|
40
|
+
def freeze
|
41
|
+
@__value__.freeze
|
42
|
+
super
|
43
|
+
end
|
44
|
+
|
45
|
+
def each(...)
|
46
|
+
@__value__.each(...)
|
47
|
+
end
|
48
|
+
end
|
@@ -102,7 +102,7 @@ class Literal::Properties::Schema
|
|
102
102
|
i, n = 0, sorted_properties.size
|
103
103
|
while i < n
|
104
104
|
property = sorted_properties[i]
|
105
|
-
buffer << " @" << property.name.name << " == other." << property.
|
105
|
+
buffer << " @" << property.name.name << " == other." << property.name.name
|
106
106
|
buffer << " &&\n " if i < n - 1
|
107
107
|
i += 1
|
108
108
|
end
|
@@ -154,7 +154,7 @@ class Literal::Properties::Schema
|
|
154
154
|
end
|
155
155
|
|
156
156
|
def generate_initializer_body(buffer = +"")
|
157
|
-
buffer << "
|
157
|
+
buffer << " __properties__ = self.class.literal_properties.properties_index\n"
|
158
158
|
generate_initializer_handle_properties(@sorted_properties, buffer)
|
159
159
|
end
|
160
160
|
|
data/lib/literal/properties.rb
CHANGED