Class: Literal::Types::UnionType

Inherits:
Object
  • Object
show all
Includes:
Enumerable, Literal::Type
Defined in:
lib/literal/types/union_type.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(queue) ⇒ UnionType

Returns a new instance of UnionType.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/literal/types/union_type.rb', line 7

def initialize(queue)
  raise Literal::ArgumentError.new("_Union type must have at least one type.") if queue.size < 1
  types = []
  primitives = Set[]

  while queue.length > 0
    type = queue.shift
    case type
    when Literal::Types::UnionType
      queue.concat(type.types, type.primitives.to_a)
    when Array, Hash, String, Symbol, Integer, Float, Complex, Rational, true, false, nil
      primitives << type
    else
      types << type
    end
  end

  types.uniq!
  @types = types.freeze
  @primitives = primitives.freeze

  freeze
end

Instance Attribute Details

#primitivesObject (readonly)

Returns the value of attribute primitives.



31
32
33
# File 'lib/literal/types/union_type.rb', line 31

def primitives
  @primitives
end

#typesObject (readonly)

Returns the value of attribute types.



31
32
33
# File 'lib/literal/types/union_type.rb', line 31

def types
  @types
end

Instance Method Details

#<=(other, context: nil) ⇒ Object



113
114
115
116
117
118
119
# File 'lib/literal/types/union_type.rb', line 113

def <=(other, context: nil)
  case other
  when Module
    @primitives.all? { |primitive| Literal.subtype?(primitive, other, context:) } &&
      @types.all? { |type| Literal.subtype?(type, other, context:) }
  end
end

#===(value) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/literal/types/union_type.rb', line 37

def ===(value)
  return true if @primitives.include?(value)

  types = @types

  i, len = 0, types.size
  while i < len
    return true if types[i] === value
    i += 1
  end

  false
end

#>=(other, context: nil) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/literal/types/union_type.rb', line 98

def >=(other, context: nil)
  types = @types
  primitives = @primitives

  case other
  when Literal::Types::UnionType
    other.types.all? { |t| primitives.any? { |p| Literal.subtype?(t, p, context:) } || types.any? { |t2| Literal.subtype?(t, t2, context:) } } &&
      other.primitives.all? { |p| primitives.any? { |p2| Literal.subtype?(p, p2, context:) } || types.any? { |t| Literal.subtype?(p, t, context:) } }
  when Literal::Types::TaggedUnionType
    other.members.values.all? { |t| primitives.any? { |p| Literal.subtype?(t, p, context:) } || types.any? { |t2| Literal.subtype?(t, t2, context:) } }
  else
    primitives.any? { |p| Literal.subtype?(other, p, context:) } || types.any? { |t| Literal.subtype?(other, t, context:) }
  end
end

#[](key) ⇒ Object



84
85
86
87
88
# File 'lib/literal/types/union_type.rb', line 84

def [](key)
  if @primitives.include?(key) || @types.include?(key)
    key
  end
end

#deconstructObject



80
81
82
# File 'lib/literal/types/union_type.rb', line 80

def deconstruct
  to_a
end

#eachObject



68
69
70
71
72
73
74
75
76
77
78
# File 'lib/literal/types/union_type.rb', line 68

def each(&)
  if block_given?
    @primitives.each(&)
    @types.each(&)
  else
    Enumerator.new do |yielder|
      @primitives.each { |primitive| yielder.yield(primitive) }
      @types.each { |type| yielder.yield(type) }
    end
  end
end

#fetch(key) ⇒ Object



90
91
92
# File 'lib/literal/types/union_type.rb', line 90

def fetch(key)
  self[key] or raise KeyError.new("Key not found: #{key.inspect}")
end

#inspectObject



33
34
35
# File 'lib/literal/types/union_type.rb', line 33

def inspect
  "_Union(#{to_a.map(&:inspect).join(', ')})"
end

#mapObject



94
95
96
# File 'lib/literal/types/union_type.rb', line 94

def map(&)
  Literal::Types::UnionType.new([*@primitives.map(&), *@types.map(&)])
end

#resolve(value) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/literal/types/union_type.rb', line 51

def resolve(value)
  if @primitives.include?(value)
    value
  else
    types = @types

    i, len = 0, types.size
    while i < len
      type = types[i]
      return type if type === value
      i += 1
    end

    raise Literal::ArgumentError.new("No match found for #{value.inspect} in #{inspect}.")
  end
end