Class: RDL::Type::UnionType

Inherits:
Type
  • Object
show all
Defined in:
lib/rdl/types/union.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Type

leq, #nil_type?, #optional?, #to_contract, #vararg?

Constructor Details

#initialize(types) ⇒ UnionType

Returns a new instance of UnionType.



28
29
30
31
32
33
34
# File 'lib/rdl/types/union.rb', line 28

def initialize(types)
  @types = types
  @canonical = false
  @canonicalized = false
  @hash = 41 + @types.hash # don't rehash if @types changes
  super()
end

Instance Attribute Details

#typesObject (readonly)

Returns the value of attribute types.



3
4
5
# File 'lib/rdl/types/union.rb', line 3

def types
  @types
end

Class Method Details

.__new__Object



6
# File 'lib/rdl/types/union.rb', line 6

alias :__new__ :new

.new(*types) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/rdl/types/union.rb', line 9

def self.new(*types)
  return RDL::Globals.types[:bot] if types.size == 0
  ts = []
  # flatten nested unions, check that all args are types
  types.each { |t|
    if t.instance_of? UnionType
      ts.concat t.types
    else
      raise RuntimeError, "Attempt to create union type with non-type" unless t.is_a? Type
      raise RuntimeError, "Attempt to create union with optional type" if t.is_a? OptionalType
      raise RuntimeError, "Attempt to create union with vararg type" if t.is_a? VarargType
      raise RuntimeError, "Attempt to create union with annotated type" if t.is_a? AnnotatedArgType
      ts << t
    end
  }
  return ts[0] if ts.size == 1
  return UnionType.__new__(ts)
end

Instance Method Details

#<=(other) ⇒ Object



88
89
90
# File 'lib/rdl/types/union.rb', line 88

def <=(other)
  return Type.leq(self, other)
end

#==(other) ⇒ Object Also known as: eql?

:nodoc:



64
65
66
67
68
69
70
71
72
73
# File 'lib/rdl/types/union.rb', line 64

def ==(other)  # :nodoc:
  return false if other.nil?
  canonicalize!
  return @canonical == other if @canonical
  other = other.canonical
  return false unless other.instance_of? UnionType
  other.canonicalize!
  return false unless @types.length == other.types.length
  return @types.all? { |t| other.types.any? { |ot| t == ot } }
end

#canonicalObject



36
37
38
39
40
# File 'lib/rdl/types/union.rb', line 36

def canonical
  canonicalize!
  return @canonical if @canonical
  return self
end

#canonicalize!Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/rdl/types/union.rb', line 42

def canonicalize!
  return if @canonicalized
  # for any type such that a supertype is already in ts, set its position to nil
  for i in 0..(@types.length-1)
    for j in (i+1)..(@types.length-1)
      next if (@types[j].nil?) || (@types[i].nil?)
      (@types[i] = nil; break) if @types[i] <= @types[j]
      (@types[j] = nil) if @types[j] <= @types[i]
    end
  end
  @types.delete(nil) # eliminate any "deleted" elements
  @types.sort! { |a, b| a.object_id <=> b.object_id } # canonicalize order
  @types.uniq!
  @canonical = @types[0] if @types.size == 1
  @canonicalized = true
end

#hashObject

:nodoc:



117
118
119
# File 'lib/rdl/types/union.rb', line 117

def hash  # :nodoc:
  return @hash
end

#instantiate(inst) ⇒ Object



111
112
113
114
115
# File 'lib/rdl/types/union.rb', line 111

def instantiate(inst)
  canonicalize!
  return @canonical.instantiate(inst) if @canonical
  return UnionType.new(*(@types.map { |t| t.instantiate(inst) }))
end

#leq_inst(other, inst = nil, ileft = true) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/rdl/types/union.rb', line 92

def leq_inst(other, inst=nil, ileft=true)
  canonicalize!
  return @canonical.leq_inst(other, inst, ileft) if @canonical
  other = other.type if other.is_a? DependentArgType
  other = other.canonical
  if inst && !ileft && other.is_a?(VarType)
    return leq_inst(inst[other.name], inst, ileft) if inst[other.name]
    inst.merge!(other.name => self)
    return true
  end
  return @types.all? { |t| t.leq_inst(other, inst, ileft) }
end

#match(other) ⇒ Object



77
78
79
80
81
82
83
84
85
86
# File 'lib/rdl/types/union.rb', line 77

def match(other)
  canonicalize!
  return @canonical.match(other) if @canonical
  other = other.canonical
  other = other.type if other.instance_of? AnnotatedArgType
  return true if other.instance_of? WildQuery
  return false unless other.instance_of? UnionType
  return false if @types.length != other.types.length
  @types.all? { |t| other.types.any? { |ot| t.match(ot) } }
end

#member?(obj, *args) ⇒ Boolean

Returns:

  • (Boolean)


105
106
107
108
109
# File 'lib/rdl/types/union.rb', line 105

def member?(obj, *args)
  canonicalize!
  return @canonical.member?(obj, *args) if @canonical
  @types.any? { |t| t.member?(obj, *args) }
end

#to_sObject

:nodoc:



59
60
61
62
# File 'lib/rdl/types/union.rb', line 59

def to_s  # :nodoc:
  return @canonical.to_s if @canonical
  return "#{@types.map { |t| t.to_s }.join(' or ')}"
end