module BindingOfCallers module Reveal Klass = Kernel.instance_method(:class) InstanceVariables = Kernel.instance_method(:instance_variables) InstanceVariableGet = Kernel.instance_method(:instance_variable_get) InstanceVariableSet = Kernel.instance_method(:instance_variable_set) def _binding instance_variable_defined?(:@_binding) ? @_binding : self end def inspect "#<#{self.class}:#{object_id} #{file}:#{line} #{klass}#{call_symbol}#{frame_env}>" end def iv *args case args.count when 0 all_iv when 1 the_iv args[0] when 2 set_iv(*args) end end def lv *args case args.count when 0 all_lv when 1 the_lv args[0] when 2 set_lv(*args) end end def klass return @klass if instance_variable_defined? :@klass determine_klass @klass end def singleton_method? return @sm if instance_variable_defined? :@sm determine_klass @sm end def call_symbol @call_sym ||= singleton_method? ? '.' : '#' end def file _binding.eval('__FILE__') end def line _binding.eval('__LINE__') end def frame_env _binding.frame_description end def env_type _binding.frame_type end private def determine_klass itself = binding_self @from_object = (Object === itself) binding_class = (@from_object ? itself.class : Klass.bind(itself).call) class_name = binding_class.name if class_name == 'Module' || class_name == 'Class' @sm = true @klass = itself else @sm = false @klass = binding_class end end def all_iv determine_klass unless instance_variable_defined? :@from_object if @from_object _binding.eval <<-EOS instance_variables.each_with_object({}) do |iv_name, vars| vars[iv_name] = instance_variable_get(iv_name) end EOS else itself = binding_self _instance_variable_get = InstanceVariableGet.bind(itself) InstanceVariables.bind(itself).call.each_with_object({}) do |iv_name, vars| vars[iv_name] = _instance_variable_get.call iv_name end end end def the_iv name determine_klass unless instance_variable_defined? :@from_object if @from_object binding_self.instance_variable_get name else InstanceVariableGet.bind(binding_self).call name end end def set_iv name, value determine_klass unless instance_variable_defined? :@from_object if @from_object binding_self.instance_variable_set name, value else InstanceVariableSet.bind(binding_self).call name, value end end def binding_self _binding.eval "instance_eval('self')" end def all_lv _binding.send(:local_variables).each_with_object({}) do |lv_name, vars| vars[lv_name] = the_lv lv_name end end def the_lv name _binding.local_variable_get name end def set_lv name, value _binding.local_variable_set name, value end end end