Class: Stone::Type::Union
Overview
Union type - represents a value that can be one of several types
Constant Summary
Constants inherited
from Stone::Type
PRIMITIVE_ALIGNMENTS, PRIMITIVE_SIZES
Instance Attribute Summary collapse
Attributes inherited from Stone::Type
#fields, #llvm_type, #max, #min, #name, #param_types, #property_types, #return_type
Instance Method Summary
collapse
Methods inherited from Stone::Type
#as_String, function, #inspect, #payload_llvm_type, #pointer_type?, primitive, record, #to_s, union
Constructor Details
#initialize(alternatives:) ⇒ Union
Returns a new instance of Union.
173
174
175
176
177
178
|
# File 'lib/stone/type.rb', line 173
def initialize(alternatives:)
@alternatives = flatten_and_dedupe(alternatives)
fail ::ArgumentError, "Union type requires at least one alternative" if @alternatives.empty?
super(name: generate_name, llvm_type: create_variable_sized_llvm_type)
end
|
Instance Attribute Details
#alternatives ⇒ Object
Returns the value of attribute alternatives.
171
172
173
|
# File 'lib/stone/type.rb', line 171
def alternatives
@alternatives
end
|
Instance Method Details
#==(other) ⇒ Object
Also known as:
eql?
291
292
293
294
295
|
# File 'lib/stone/type.rb', line 291
def ==(other)
return false unless other.is_a?(Union)
Set.new(@alternatives) == Set.new(other.alternatives)
end
|
#alignment ⇒ Object
184
185
186
187
|
# File 'lib/stone/type.rb', line 184
def alignment
[8, payload_alignment].max
end
|
#common_llvm_result_type ⇒ Object
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
|
# File 'lib/stone/type.rb', line 197
def common_llvm_result_type
non_null_alts = @alternatives.reject { |alt| alt.name == "Null" }
return LLVM::Int64.type if non_null_alts.empty?
all_pointers = non_null_alts.all?(&:pointer_type?)
all_integers = non_null_alts.all? { |alt| %w[Int Bool].include?(alt.name) }
return LLVM::Type.pointer if all_pointers
return LLVM::Int64.type if all_integers
nil end
|
#compatible_with?(other) ⇒ Boolean
279
280
281
|
# File 'lib/stone/type.rb', line 279
def compatible_with?(other)
other.union? ? covers_all_alternatives?(other) : includes_compatible_type?(other)
end
|
#function? ⇒ Boolean
244
245
246
|
# File 'lib/stone/type.rb', line 244
def function?
false
end
|
#hash ⇒ Object
298
299
300
|
# File 'lib/stone/type.rb', line 298
def hash
Set.new(@alternatives).hash
end
|
#homogeneous? ⇒ Boolean
214
215
216
217
|
# File 'lib/stone/type.rb', line 214
def homogeneous?
!common_llvm_result_type.nil?
end
|
#needs_runtime_type_tag? ⇒ Boolean
Returns true if the union contains types that cannot be distinguished by value alone.
For example, Bool | Int - both are integers, and Bool(1) looks like Int(1).
Such unions require returning the runtime type tag to Ruby for proper interpretation.
222
223
224
225
|
# File 'lib/stone/type.rb', line 222
def needs_runtime_type_tag?
non_null_names = @alternatives.reject { |alt| alt.name == "Null" }.map(&:name)
non_null_names.include?("Bool") && non_null_names.include?("Int")
end
|
#non_null_type ⇒ Object
272
273
274
275
276
277
|
# File 'lib/stone/type.rb', line 272
def non_null_type
remaining = @alternatives.reject { |t| null_type?(t) }
return remaining.first if remaining.length == 1
Stone::Type.union(alternatives: remaining)
end
|
#nullable? ⇒ Boolean
248
249
250
|
# File 'lib/stone/type.rb', line 248
def nullable?
@alternatives.any? { |t| null_type?(t) }
end
|
#payload_alignment ⇒ Object
193
194
195
|
# File 'lib/stone/type.rb', line 193
def payload_alignment
@alternatives.map(&:alignment).max || 1
end
|
#payload_size ⇒ Object
189
190
191
|
# File 'lib/stone/type.rb', line 189
def payload_size
@alternatives.map(&:size_bytes).max || 0
end
|
#primitive? ⇒ Boolean
236
237
238
|
# File 'lib/stone/type.rb', line 236
def primitive?
false
end
|
#property_return_type(property_name) ⇒ Object
Look through non-null alternatives for a property.
Returns the property type if ALL non-null alternatives have it with the same type.
This enables chained access like o.value.x where value is Point | Null.
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
|
# File 'lib/stone/type.rb', line 255
def property_return_type(property_name)
non_null_alts = @alternatives.reject { |alt| null_type?(alt) }
return nil if non_null_alts.empty?
prop_types = non_null_alts.map { |alt| alt.property_return_type(property_name) }
return nil if prop_types.any?(&:nil?)
return nil unless prop_types.uniq.length == 1
prop_types.first
end
|
#record? ⇒ Boolean
240
241
242
|
# File 'lib/stone/type.rb', line 240
def record?
false
end
|
#size_bytes ⇒ Object
180
181
182
|
# File 'lib/stone/type.rb', line 180
def size_bytes
8 + payload_size end
|
#union? ⇒ Boolean
232
233
234
|
# File 'lib/stone/type.rb', line 232
def union?
true
end
|