class TypeProf::Type

Constants

Builtin
DummySubstitution

Public Class Methods

any() click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 427
def self.any
  Thread.current[:any] ||= Any.new
end
bool() click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 435
def self.bool
  Thread.current[:bool] ||= Union.new(Utils::Set[
    Instance.new(Type::Builtin[:true]),
    Instance.new(Type::Builtin[:false])
  ], nil)
end
bot() click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 431
def self.bot
  Thread.current[:bot] ||= Union.new(Utils::Set[], nil)
end
builtin_global_variable_type(var) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 809
def self.builtin_global_variable_type(var)
  case var
  when :$_, :$/, :$\, :$,, :$;
    Type.optional(Type::Instance.new(Type::Builtin[:str]))
  when :$0, :$PROGRAM_NAME
    Type::Instance.new(Type::Builtin[:str])
  when :$~
    # optional type is tentatively disabled; it is too conservative
    #Type.optional(Type::Instance.new(Type::Builtin[:matchdata]))
    Type::Instance.new(Type::Builtin[:matchdata])
  when :$., :$$
    Type::Instance.new(Type::Builtin[:int])
  when :$?
    Type.optional(Type::Instance.new(Type::Builtin[:int]))
  when :$!
    Type.optional(Type::Instance.new(Type::Builtin[:exc]))
  when :$@
    str = Type::Instance.new(Type::Builtin[:str])
    base_ty = Type::Instance.new(Type::Builtin[:ary])
    Type.optional(Type::Array.new(Type::Array::Elements.new([], str), base_ty))
  when :$*, :$:, :$LOAD_PATH, :$", :$LOADED_FEATURES
    str = Type::Instance.new(Type::Builtin[:str])
    base_ty = Type::Instance.new(Type::Builtin[:ary])
    Type::Array.new(Type::Array::Elements.new([], str), base_ty)
  when :$<
    :ARGF
  when :$>
    :STDOUT
  when :$DEBUG
    Type.bool
  when :$FILENAME
    Type::Instance.new(Type::Builtin[:str])
  when :$stdin
    :STDIN
  when :$stdout
    :STDOUT
  when :$stderr
    :STDERR
  when :$VERBOSE
    Type.bool.union(Type.nil)
  else
    nil
  end
end
gen_hash(base_ty = Type::Instance.new(Type::Builtin[:hash])) { |hg| ... } click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 750
def self.gen_hash(base_ty = Type::Instance.new(Type::Builtin[:hash]))
  hg = HashGenerator.new
  yield hg
  Type::Hash.new(Type::Hash::Elements.new(hg.map_tys), base_ty)
end
guess_literal_type(obj) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 756
def self.guess_literal_type(obj)
  case obj
  when ::Symbol
    Type::Symbol.new(obj, Type::Instance.new(Type::Builtin[:sym]))
  when ::Integer
    Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:int]))
  when ::Rational
    Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:rational]))
  when ::Complex
    Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:complex]))
  when ::Float
    Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:float]))
  when ::Class
    return Type.any if obj < Exception
    case obj
    when ::Object
      Type::Builtin[:obj]
    when ::Array
      Type::Builtin[:ary]
    else
      raise "unknown class: #{ obj.inspect }"
    end
  when ::TrueClass
    Type::Instance.new(Type::Builtin[:true])
  when ::FalseClass
    Type::Instance.new(Type::Builtin[:false])
  when ::Array
    base_ty = Type::Instance.new(Type::Builtin[:ary])
    lead_tys = obj.map {|arg| guess_literal_type(arg) }
    Type::Array.new(Type::Array::Elements.new(lead_tys), base_ty)
  when ::Hash
    Type.gen_hash do |h|
      obj.each do |k, v|
        k_ty = guess_literal_type(k).globalize(nil, {}, Config.current.options[:type_depth_limit])
        v_ty = guess_literal_type(v)
        h[k_ty] = v_ty
      end
    end
  when ::String
    Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:str]))
  when ::Regexp
    Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:regexp]))
  when ::NilClass
    Type.nil
  when ::Range
    Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:range]))
  when ::Encoding
    Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:encoding]))
  else
    raise "unknown object: #{ obj.inspect }"
  end
end
match?(ty1, ty2) click to toggle source
# File typeprof-0.21.8/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
        if ty1.class == ty2.class
          ty1.match?(ty2)
        else
          Type.match?(ty1, ty2.base_type)
        end
      elsif ty1.is_a?(Type::ContainerType)
        Type.match?(ty1.base_type, ty2)
      else
        ty1.consistent?(ty2) ? {} : nil
      end
    end
  end
end
merge_substitution(subst1, subst2) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 76
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
new() click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 5
def initialize
  raise "cannot instantiate abstract type"
end
nil() click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 442
def self.nil
  Thread.current[:nil] ||= Instance.new(Type::Builtin[:nil])
end
optional(ty) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 446
def self.optional(ty)
  ty.union(Type.nil)
end

Public Instance Methods

each_child() { |self| ... } click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 92
def each_child
  yield self
end
each_child_global() { |self| ... } click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 96
def each_child_global
  yield self
end
each_free_type_variable() click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 100
def each_free_type_variable
end
generate_substitution() click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 164
def generate_substitution
  {}
end
globalize(_env, _visited, _depth) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 11
def globalize(_env, _visited, _depth)
  self
end
include_untyped?(_scratch) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 177
def include_untyped?(_scratch)
  false
end
limit_size(limit) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 19
def limit_size(limit)
  self
end
localize(env, _alloc_site, _depth) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 15
def localize(env, _alloc_site, _depth)
  return env, self
end
remove_type_vars() click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 173
def remove_type_vars
  substitute(DummySubstitution, Config.current.options[:type_depth_limit])
end
substitute(_subst, _depth) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 160
def substitute(_subst, _depth)
  raise "cannot substitute abstract type: #{ self.class }"
end
union(other) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 103
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

Private Instance Methods

union_elems(e1, e2) click to toggle source
# File typeprof-0.21.8/lib/typeprof/type.rb, line 148
        def union_elems(e1, e2)
  if e1
    if e2
      e1.union(e2)
    else
      e1
    end
  else
    e2
  end
end