literal 1.3.0 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9721432521677aa431dda4e94240521a54a8ac21ece07fef009393544d19214d
4
- data.tar.gz: c5b41c95f4c24ff4fad28869bf61ff93174118a2d3e5890928961b382bf9b285
3
+ metadata.gz: 8ee13d939895155fc3ce4ae1717036b565b0a59d7a4e87b50ea0a1390cc40bf3
4
+ data.tar.gz: 42df47f2efce39eb14976d226645adb7a9dacc681948a71a9254ca44e19d8d1f
5
5
  SHA512:
6
- metadata.gz: 715a03576aed152e2fd5737236eb227dd98da9f02b421a14722395a3b9992dc667302574490955f0f9d81192dc5f64f793d916b196bc4509244afad5daa8a37b
7
- data.tar.gz: 475df2645d537e5c8151ba6431e1469fdcfdd1a80d766489bfa00b135f3c3e57a86b0c09c7e6738c6033609a69864a596660a0b5498bd6762e314588a67bac35
6
+ metadata.gz: f3a9b286744de95185baea476e8d7387238912aeb7f956eeef4e7b203bd0a55313885baaf6c5e71e27eb6d252961d44f850ede7e09abbc05c323c88a099be6f6
7
+ data.tar.gz: f2cc33927ce452c94b3146dc7714cd9078cd532da5523afbbae5372ec2a5aa0319460db07525d9d7a5d709deb9ff929b804d0f3a86425f3d4844bf641a5a669b
data/lib/literal/array.rb CHANGED
@@ -23,7 +23,7 @@ class Literal::Array
23
23
  def >=(other)
24
24
  case other
25
25
  when Literal::Array::Generic
26
- @type >= other.type
26
+ Literal.subtype?(other.type, of: @type)
27
27
  else
28
28
  false
29
29
  end
@@ -256,6 +256,14 @@ class Literal::Array
256
256
  super
257
257
  end
258
258
 
259
+ def hash
260
+ [self.class, @__value__].hash
261
+ end
262
+
263
+ def include?(...)
264
+ @__value__.include?(...)
265
+ end
266
+
259
267
  alias_method :index, :find_index
260
268
 
261
269
  def insert(index, *value)
@@ -389,10 +397,44 @@ class Literal::Array
389
397
  @__value__.one?(...)
390
398
  end
391
399
 
400
+ def pack(...)
401
+ @__value__.pack(...)
402
+ end
403
+
392
404
  def pop(...)
393
405
  @__value__.pop(...)
394
406
  end
395
407
 
408
+ def product(*others, &)
409
+ if block_given?
410
+ @__value__.product(
411
+ *others.map do |other|
412
+ case other
413
+ when Array
414
+ other
415
+ when Literal::Array
416
+ other.__value__
417
+ end
418
+ end, &
419
+ )
420
+
421
+ self
422
+ elsif others.all?(Literal::Array)
423
+ tuple_type = Literal::Tuple(
424
+ @__type__,
425
+ *others.map(&:__type__)
426
+ )
427
+
428
+ values = @__value__.product(*others.map(&:__value__)).map do |tuple_values|
429
+ tuple_type.new(*tuple_values)
430
+ end
431
+
432
+ Literal::Array(tuple_type).new(*values)
433
+ else
434
+ @__value__.product(*others)
435
+ end
436
+ end
437
+
396
438
  def push(*value)
397
439
  Literal.check(actual: value, expected: _Array(@__type__)) do |c|
398
440
  c.fill_receiver(receiver: self, method: "#push")
@@ -434,6 +476,17 @@ class Literal::Array
434
476
  self
435
477
  end
436
478
 
479
+ alias_method :initialize_copy, :replace
480
+
481
+ def rotate(...)
482
+ __with__(@__value__.rotate(...))
483
+ end
484
+
485
+ def rotate!(...)
486
+ @__value__.rotate!(...)
487
+ self
488
+ end
489
+
437
490
  def sample(...)
438
491
  @__value__.sample(...)
439
492
  end
@@ -450,6 +503,15 @@ class Literal::Array
450
503
  @__value__.shift(...)
451
504
  end
452
505
 
506
+ def shuffle(...)
507
+ __with__(@__value__.shuffle(...))
508
+ end
509
+
510
+ def shuffle!(...)
511
+ @__value__.shuffle!(...)
512
+ self
513
+ end
514
+
453
515
  def size(...)
454
516
  @__value__.size(...)
455
517
  end
@@ -463,6 +525,10 @@ class Literal::Array
463
525
  self
464
526
  end
465
527
 
528
+ def take(...)
529
+ __with__(@__value__.take(...))
530
+ end
531
+
466
532
  def to_a
467
533
  @__value__.dup
468
534
  end
data/lib/literal/data.rb CHANGED
@@ -9,17 +9,11 @@ class Literal::Data < Literal::DataStructure
9
9
  def literal_properties
10
10
  return @literal_properties if defined?(@literal_properties)
11
11
 
12
- if superclass.is_a?(Literal::Data)
12
+ if superclass < Literal::Data
13
13
  @literal_properties = superclass.literal_properties.dup
14
14
  else
15
15
  @literal_properties = Literal::Properties::DataSchema.new
16
16
  end
17
17
  end
18
-
19
- private
20
-
21
- def __literal_property_class__
22
- Literal::DataProperty
23
- end
24
18
  end
25
19
  end
data/lib/literal/enum.rb CHANGED
@@ -77,6 +77,9 @@ class Literal::Enum
77
77
  object = const_get(name)
78
78
 
79
79
  if self === object
80
+ if @values.key?(object.value)
81
+ raise ArgumentError.new("The value #{object.value} is already used by #{@values[object.value].name}.")
82
+ end
80
83
  object.instance_variable_set(:@name, name)
81
84
  @values[object.value] = object
82
85
  @members << object
@@ -155,8 +158,12 @@ class Literal::Enum
155
158
  method(:coerce).to_proc
156
159
  end
157
160
 
158
- def to_h(*args)
159
- @values.dup
161
+ def to_h(&)
162
+ if block_given?
163
+ @members.to_h(&)
164
+ else
165
+ @members.to_h { |it| [it, it.value] }
166
+ end
160
167
  end
161
168
  end
162
169
 
@@ -157,7 +157,7 @@ class Literal::Property
157
157
 
158
158
  def generate_initializer_handle_property(buffer = +"")
159
159
  buffer << " # " << @name.name << "\n" <<
160
- " property = __properties__[:" << @name.name << "]\n"
160
+ " __property__ = __properties__[:" << @name.name << "]\n"
161
161
 
162
162
  if @kind == :keyword && ruby_keyword?
163
163
  generate_initializer_escape_keyword(buffer)
@@ -191,7 +191,7 @@ class Literal::Property
191
191
  def generate_initializer_coerce_property(buffer = +"")
192
192
  buffer <<
193
193
  escaped_name <<
194
- "= property.coerce(" <<
194
+ "= __property__.coerce(" <<
195
195
  escaped_name <<
196
196
  ", context: self)\n"
197
197
  end
@@ -204,12 +204,12 @@ class Literal::Property
204
204
  escaped_name <<
205
205
  "\n " <<
206
206
  escaped_name <<
207
- " = property.default_value\n end\n"
207
+ " = __property__.default_value\n end\n"
208
208
  end
209
209
 
210
210
  def generate_initializer_check_type(buffer = +"")
211
211
  buffer <<
212
- " property.check_initializer(self, " << escaped_name << ")\n"
212
+ " __property__.check_initializer(self, " << escaped_name << ")\n"
213
213
  end
214
214
 
215
215
  def generate_initializer_assign_value(buffer = +"")
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Literal::Tuple
4
+ class Generic
5
+ include Literal::Type
6
+
7
+ def initialize(*types)
8
+ @types = types
9
+ end
10
+
11
+ attr_reader :types
12
+
13
+ def ===(other)
14
+ return false unless Literal::Tuple === other
15
+ types = @types
16
+ other_types = other.__types__
17
+
18
+ return false unless types.size == other_types.size
19
+
20
+ i, len = 0, types.size
21
+ while i < len
22
+ return false unless Literal.subtype?(other_types[i], of: types[i])
23
+ i += 1
24
+ end
25
+
26
+ true
27
+ end
28
+
29
+ def >=(other)
30
+ case other
31
+ when Literal::Tuple::Generic
32
+ types = @types
33
+ other_types = other.types
34
+
35
+ return false unless types.size == other_types.size
36
+
37
+ i, len = 0, types.size
38
+ while i < len
39
+ return false unless Literal.subtype?(other_types[i], of: types[i])
40
+ i += 1
41
+ end
42
+
43
+ true
44
+ else
45
+ false
46
+ end
47
+ end
48
+
49
+ def new(*values)
50
+ Literal::Tuple.new(values, @types)
51
+ end
52
+ end
53
+
54
+ def initialize(values, types)
55
+ @__values__ = values
56
+ @__types__ = types
57
+ end
58
+
59
+ attr_reader :__values__, :__types__
60
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Literal
4
- VERSION = "1.3.0"
4
+ VERSION = "1.4.0"
5
5
  end
data/lib/literal.rb CHANGED
@@ -22,6 +22,7 @@ module Literal
22
22
  autoload :Struct, "literal/struct"
23
23
  autoload :Type, "literal/type"
24
24
  autoload :Types, "literal/types"
25
+ autoload :Tuple, "literal/tuple"
25
26
 
26
27
  # Errors
27
28
  autoload :Error, "literal/errors/error"
@@ -48,6 +49,10 @@ module Literal
48
49
  Literal::Hash::Generic.new(key_type, value_type)
49
50
  end
50
51
 
52
+ def self.Tuple(*types)
53
+ Literal::Tuple::Generic.new(*types)
54
+ end
55
+
51
56
  def self.check(actual:, expected:)
52
57
  if expected === actual
53
58
  true
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: literal
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Drapper
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-29 00:00:00.000000000 Z
11
+ date: 2024-12-10 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: A literal Ruby gem.
13
+ description: Enums, properties, generics, structured objects and runtime type checking.
14
14
  email:
15
15
  - joel@drapper.me
16
16
  executables: []
@@ -22,7 +22,6 @@ files:
22
22
  - lib/literal.rb
23
23
  - lib/literal/array.rb
24
24
  - lib/literal/data.rb
25
- - lib/literal/data_property.rb
26
25
  - lib/literal/data_structure.rb
27
26
  - lib/literal/deferred_type.rb
28
27
  - lib/literal/enum.rb
@@ -46,6 +45,7 @@ files:
46
45
  - lib/literal/set.rb
47
46
  - lib/literal/struct.rb
48
47
  - lib/literal/transforms.rb
48
+ - lib/literal/tuple.rb
49
49
  - lib/literal/type.rb
50
50
  - lib/literal/types.rb
51
51
  - lib/literal/types/any_type.rb
@@ -78,7 +78,7 @@ licenses:
78
78
  metadata:
79
79
  homepage_uri: https://literal.fun
80
80
  source_code_uri: https://github.com/joeldrapper/literal
81
- changelog_uri: https://github.com/joeldrapper/literal/blob/main/CHANGELOG.md
81
+ changelog_uri: https://github.com/joeldrapper/literal/releases
82
82
  funding_uri: https://github.com/sponsors/joeldrapper
83
83
  rubygems_mfa_required: 'true'
84
84
  post_install_message:
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Literal::DataProperty < Literal::Property
4
- def generate_initializer_assign_value(buffer = +"")
5
- buffer <<
6
- "@" <<
7
- @name.name <<
8
- " = " <<
9
- escaped_name <<
10
- ".frozen? ? " <<
11
- escaped_name <<
12
- " : " <<
13
- escaped_name <<
14
- ".dup.freeze\n"
15
- end
16
- end