# File typeprof-0.21.2/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.21.2/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.21.2/lib/typeprof/type.rb, line 89 def each_child yield self end
# File typeprof-0.21.2/lib/typeprof/type.rb, line 93 def each_child_global yield self end
# File typeprof-0.21.2/lib/typeprof/type.rb, line 97 def each_free_type_variable end
# File typeprof-0.21.2/lib/typeprof/type.rb, line 11 def globalize(_env, _visited, _depth) self end
# File typeprof-0.21.2/lib/typeprof/type.rb, line 19 def limit_size(limit) self end
# File typeprof-0.21.2/lib/typeprof/type.rb, line 15 def localize(env, _alloc_site, _depth) return env, self end
# File typeprof-0.21.2/lib/typeprof/type.rb, line 100 def union(other) return self if self == other # fastpath ty1, ty2 = self, other case when ty1.is_a?(Union) ty1_types = ty1.types ty1_elems = ty1.elems when ty1.is_a?(Array) || ty1.is_a?(Hash) ty1_types = Utils::Set[] ty1_elems = {[ty1.class, ty1.base_type] => ty1.elems} else ty1_types = ty1_elems = nil end case when ty2.is_a?(Union) ty2_types = ty2.types ty2_elems = ty2.elems when ty2.is_a?(Array) || ty2.is_a?(Hash) ty2_types = Utils::Set[] ty2_elems = {[ty2.class, ty2.base_type] => ty2.elems} else ty2_types = ty2_elems = nil end if ty1_types && ty2_types 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.create(ty, all_elems) elsif ty1_types Type::Union.create(ty1_types.add(ty2), ty1_elems) elsif ty2_types Type::Union.create(ty2_types.add(ty1), ty2_elems) else Type::Union.create(Utils::Set[ty1, ty2], nil) end end