class Steep::Interface::Shape::Methods

def [](name)

def [](name)
  return nil unless key?(name)
  resolved_methods[name] ||= begin
    entry = methods[name]
    Entry.new(
      method_types: entry.method_types.map do |method_type|
        method_type.subst(subst)
      end,
      private_method: entry.private_method?
    )
  end
end

def []=(name, entry)

def []=(name, entry)
  resolved_methods[name] = nil
  methods[name] = entry
end

def each(&block)

def each(&block)
  if block
    methods.each_key do |name|
      entry = self[name] or next
      yield [name, entry]
    end
  else
    enum_for :each
  end
end

def each_name(&block)

def each_name(&block)
  if block
    each do |name, _|
      yield name
    end
  else
    enum_for :each_name
  end
end

def initialize(substs:, methods:)

def initialize(substs:, methods:)
  @substs = substs
  @methods = methods
  @resolved_methods = methods.transform_values { nil }
end

def key?(name)

def key?(name)
  if entry = methods.fetch(name, nil)
    entry.has_method_type?
  else
    false
  end
end

def merge!(other, &block)

def merge!(other, &block)
  other.each do |name, entry|
    if block && (old_entry = methods[name])
      methods[name] = yield(name, old_entry, entry)
    else
      methods[name] = entry
    end
  end
end

def public_methods

def public_methods
  Methods.new(
    substs: substs,
    methods: methods.reject {|_, entry| entry.private_method? }
  )
end

def push_substitution(subst)

def push_substitution(subst)
  Methods.new(substs: [*substs, subst], methods: methods)
end

def subst

def subst
  @subst ||= begin
    substs.each_with_object(Substitution.empty) do |s, ss|
      ss.merge!(s, overwrite: true)
    end
  end
end