Class: TypeProf::Type::Union
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
::TypeProf::Type
|
|
Instance Chain:
|
|
Inherits: |
TypeProf::Type
|
Defined in: | lib/typeprof/type.rb |
Constant Summary
::TypeProf::Type
- Inherited
Class Method Summary
- .create(tys, elems)
- .new(tys, elems) ⇒ Union constructor
::TypeProf::Type
- Inherited
Instance Attribute Summary
Instance Method Summary
- #consistent?(_other) ⇒ Boolean
-
#each_child(&blk)
local.
- #each_child_global(&blk)
- #each_free_type_variable(&blk)
- #globalize(env, visited, depth)
- #include_untyped?(scratch) ⇒ Boolean
- #inspect
- #limit_size(limit)
- #localize(env, alloc_site, depth)
- #screen_name(scratch)
- #substitute(subst, depth)
::TypeProf::Type
- Inherited
Constructor Details
.new(tys, elems) ⇒ Union
# File 'lib/typeprof/type.rb', line 250
def initialize(tys, elems) raise unless tys.is_a?(Utils::Set) @types = tys # Set # invariant check local = nil tys.each do |ty| raise ty.inspect unless ty.is_a?(Type) local = true if ty.is_a?(Local) end raise if local && elems @elems = elems raise elems.inspect if elems && !elems.is_a?(::Hash) end
Class Method Details
.create(tys, elems)
[ GitHub ]# File 'lib/typeprof/type.rb', line 219
def self.create(tys, elems) if tys.size == 1 && !elems tys.each {|ty| return ty } elsif tys.size == 0 if elems && elems.size == 1 (container_kind, base_type), nelems = elems.first # container_kind = Type::Array or Type::Hash container_kind.new(nelems, base_type) else new(tys, elems) end else class_instances = [] non_class_instances = [] degenerated = false tys.each do |ty| if ty != Type::Instance.new(Type::Builtin[:nil]) && ty.is_a?(Type::Instance) && ty.klass.kind == :class class_instances << ty degenerated = true if ty.include_subclasses else non_class_instances << ty end end if (Config.current. [:union_width_limit] >= 2 && class_instances.size >= Config.current. [:union_width_limit]) || (degenerated && class_instances.size >= 2) create(Utils::Set[Instance.new_degenerate(class_instances), *non_class_instances], elems) else new(tys, elems) end end end
Instance Attribute Details
#elems (readonly)
[ GitHub ]# File 'lib/typeprof/type.rb', line 284
attr_reader :types, :elems
#types (readonly)
[ GitHub ]# File 'lib/typeprof/type.rb', line 284
attr_reader :types, :elems
Instance Method Details
#consistent?(_other) ⇒ Boolean
# File 'lib/typeprof/type.rb', line 385
def consistent?(_other) raise "should not be called" end
#each_child(&blk)
local
# File 'lib/typeprof/type.rb', line 286
def each_child(&blk) # local @types.each(&blk) raise if @elems end
#each_child_global(&blk)
[ GitHub ]#each_free_type_variable(&blk)
[ GitHub ]# File 'lib/typeprof/type.rb', line 266
def each_free_type_variable(&blk) each_child_global do |ty| ty.each_free_type_variable(&blk) end end
#globalize(env, visited, depth)
[ GitHub ]# File 'lib/typeprof/type.rb', line 344
def globalize(env, visited, depth) return Type.any if depth <= 0 tys = Utils::Set[] if @elems # XXX: If @elems is non nil, the Union type should global, so calling globalize against such a type should not occur. # However, currently, ActualArguments may contain global types for flag_args_kw_splat case. # This should be fixed in future in ActualArguments side. See Scratch#setup_actual_arguments. #raise end elems = @elems ? @elems.dup : {} @types.each do |ty| ty = ty.globalize(env, visited, depth - 1) case ty when Type::Array, Type::Hash key = [ty.class, ty.base_type] elems[key] = union_elems(elems[key], ty.elems) else tys = tys.add(ty) end end elems = nil if elems.empty? Type::Union.create(tys, elems) end
#include_untyped?(scratch) ⇒ Boolean
# File 'lib/typeprof/type.rb', line 412
def include_untyped?(scratch) @types.each do |ty| return true if ty.include_untyped?(scratch) end @elems&.each do |(container_kind, base_type), elems| return true if base_type.include_untyped?(scratch) return true if elems.include_untyped?(scratch) end false end
#inspect
[ GitHub ]#limit_size(limit)
[ GitHub ]#localize(env, alloc_site, depth)
[ GitHub ]# File 'lib/typeprof/type.rb', line 370
def localize(env, alloc_site, depth) return env, Type.any if depth <= 0 tys = @types.map do |ty| env, ty2 = ty.localize(env, alloc_site, depth - 1) ty2 end @elems&.each do |(container_kind, base_type), elems| ty = container_kind.new(elems, base_type) env, ty = ty.localize(env, alloc_site, depth - 1) tys = tys.add(ty) end ty = Union.create(tys, nil) return env, ty end
#screen_name(scratch)
[ GitHub ]# File 'lib/typeprof/type.rb', line 308
def screen_name(scratch) types = @types.to_a @elems&.each do |(container_kind, base_type), elems| types << container_kind.new(elems, base_type) end if types.size == 0 "bot" else types = types.to_a optional = !!types.delete(Type::Instance.new(Type::Builtin[:nil])) bool = false if types.include?(Type::Instance.new(Type::Builtin[:false])) && types.include?(Type::Instance.new(Type::Builtin[:true])) types.delete(Type::Instance.new(Type::Builtin[:false])) types.delete(Type::Instance.new(Type::Builtin[:true])) bool = true end types.delete(Type.any) unless Config.current. [:show_untyped] proc_tys, types = types.partition {|ty| ty.is_a?(Proc) } types = types.map {|ty| ty.screen_name(scratch) } types << scratch.show_proc_signature(proc_tys) unless proc_tys.empty? types << "bool" if bool types = types.sort if optional case types.size when 0 then "nil" when 1 then types.first + "?" else "(#{ types.join (" | ") })?" end else types.join (" | ") end end end
#substitute(subst, depth)
[ GitHub ]# File 'lib/typeprof/type.rb', line 389
def substitute(subst, depth) return Type.any if depth <= 0 unions = [] tys = Utils::Set[] @types.each do |ty| ty = ty.substitute(subst, depth - 1) case ty when Union unions << ty else tys = tys.add(ty) end end elems = @elems&.to_h do |(container_kind, base_type), elems| [[container_kind, base_type], elems.substitute(subst, depth - 1)] end ty = Union.create(tys, elems) unions.each do |ty0| ty = ty.union(ty0) end ty end