# File typeprof-0.12.0/lib/typeprof/type.rb, line 23
def self.match?(ty1, ty2)
# both ty1 and ty2 should be global
# ty1 is always concrete; it should not have type variables
# ty2 might be abstract; it may have type variables
case ty2
when Type::Var
{ ty2 => ty1 }
when Type::Any
{}
when Type::Union
subst = nil
ty2.each_child_global do |ty2|
# this is very conservative to create subst:
# Type.match?( int | str, int | X) creates { X => int | str } but should be { X => str }???
subst2 = Type.match?(ty1, ty2)
next unless subst2
subst = Type.merge_substitution(subst, subst2)
end
subst
else
case ty1
when Type::Var then raise "should not occur"
when Type::Any
subst = {}
ty2.each_free_type_variable do |tyvar|
subst[tyvar] = Type.any
end
subst
when Type::Union
subst = nil
ty1.each_child_global do |ty1|
subst2 = Type.match?(ty1, ty2)
next unless subst2
subst = Type.merge_substitution(subst, subst2)
end
subst
else
if ty2.is_a?(Type::ContainerType)
# ty2 may have type variables
return nil if ty1.class != ty2.class
ty1.match?(ty2)
elsif ty1.is_a?(Type::ContainerType)
nil
else
ty1.consistent?(ty2) ? {} : nil
end
end
end
end
# File typeprof-0.12.0/lib/typeprof/type.rb, line 73
def self.merge_substitution(subst1, subst2)
if subst1
subst1 = subst1.dup
subst2.each do |tyvar, ty|
if subst1[tyvar]
subst1[tyvar] = subst1[tyvar].union(ty)
else
subst1[tyvar] = ty
end
end
subst1
else
subst2
end
end
# File typeprof-0.12.0/lib/typeprof/type.rb, line 89
def each_child
yield self
end
# File typeprof-0.12.0/lib/typeprof/type.rb, line 93
def each_child_global
yield self
end
# File typeprof-0.12.0/lib/typeprof/type.rb, line 97
def each_free_type_variable
end
# File typeprof-0.12.0/lib/typeprof/type.rb, line 11
def globalize(_env, _visited, _depth)
self
end
# File typeprof-0.12.0/lib/typeprof/type.rb, line 19
def limit_size(limit)
self
end
# File typeprof-0.12.0/lib/typeprof/type.rb, line 15
def localize(env, _alloc_site, _depth)
return env, self
end
# File typeprof-0.12.0/lib/typeprof/type.rb, line 100
def union(other)
return self if self == other # fastpath
ty1, ty2 = self, other
ty1 = container_to_union(ty1)
ty2 = container_to_union(ty2)
if ty1.is_a?(Union) && ty2.is_a?(Union)
ty = ty1.types.sum(ty2.types)
all_elems = ty1.elems.dup || {}
ty2.elems&.each do |key, elems|
all_elems[key] = union_elems(all_elems[key], elems)
end
all_elems = nil if all_elems.empty?
Type::Union.new(ty, all_elems).normalize
else
ty1, ty2 = ty2, ty1 if ty2.is_a?(Union)
if ty1.is_a?(Union)
Type::Union.new(ty1.types.add(ty2), ty1.elems).normalize
else
Type::Union.new(Utils::Set[ty1, ty2], nil).normalize
end
end
end