class DEBUGGER__::FrameInfo

def self.pretty_path path

def self.pretty_path path
  return '#<none>' unless path
  use_short_path = CONFIG[:use_short_path]
  case
  when use_short_path && path.start_with?(dir = RbConfig::CONFIG["rubylibdir"] + '/')
    path.sub(dir, '$(rubylibdir)/')
  when use_short_path && Gem.path.any? do |gp|
      path.start_with?(dir = gp + '/gems/')
    end
    path.sub(dir, '$(Gem)/')
  when HOME && path.start_with?(HOME)
    path.sub(HOME, '~/')
  else
    path
  end
end

def block_identifier

def block_identifier
  return unless frame_type == :block
  _, level, block_loc = location.label.match(BLOCK_LABL_REGEXP).to_a
  [level || "", block_loc]
end

def c_identifier

def c_identifier
  return unless frame_type == :c
  "[C] #{klass_sig}#{location.base_label}"
end

def callee

def callee
  self._callee ||= begin
                     self.binding&.eval('__callee__')
                   rescue NameError # BasicObject
                     nil
                   end
end

def eval_binding

def eval_binding
  if b = self.dupped_binding
    b
  else
    b = self.binding || TOPLEVEL_BINDING
    self.dupped_binding = b.dup
  end
end

def file_lines

def file_lines
  SESSION.source(self.iseq)
end

def frame_type

def frame_type
  if self.local_variables && iseq
    if iseq.type == :block
      :block
    elsif callee
      :method
    else
      :other
    end
  else
    :c
  end
end

def get_singleton_class obj

def get_singleton_class obj
ngleton_class # TODO: don't use it
ypeError

def iseq_parameters_info

def iseq_parameters_info
  case frame_type
  when :block, :method
    parameters_info
  else
    nil
  end
end

def klass_sig

def klass_sig
f.class == get_singleton_class(self.self)
elf.self}."
elf.class}#"

def local_variable_get var

def local_variable_get var
variables[var]

def local_variables

def local_variables
  if lvars = self._local_variables
    lvars
  elsif b = self.binding
    b.local_variables.map{|var|
      [var, b.local_variable_get(var)]
    }.to_h
  end
end

def location_str

def location_str
  "#{pretty_path}:#{location.lineno}"
end

def matchable_location

def matchable_location
  # realpath can sometimes be nil so we can't use it here
  "#{path}:#{location.lineno}"
end

def method_identifier

def method_identifier
  return unless frame_type == :method
  "#{klass_sig}#{callee}"
end

def name

def name
  # p frame_type: frame_type, self: self
  case frame_type
  when :block
    level, block_loc = block_identifier
    "block in #{block_loc}#{level}"
  when :method
    method_identifier
  when :c
    c_identifier
  when :other
    other_identifier
  end
end

def other_identifier

def other_identifier
  return unless frame_type == :other
  location.label
end

def parameters_info

def parameters_info
  vars = iseq.parameters_symbols
  vars.map{|var|
    begin
      { name: var, value: DEBUGGER__.safe_inspect(local_variable_get(var), short: true) }
    rescue NameError, TypeError
      nil
    end
  }.compact
end

def path

def path
  location.path
end

def pretty_path

def pretty_path
  FrameInfo.pretty_path path
end

def realpath

def realpath
  location.absolute_path
end

def return_str

def return_str
  if self.binding && iseq && has_return_value
    DEBUGGER__.safe_inspect(return_value, short: true)
  end
end