--------------080303090405040506020701
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Michael Neumann wrote:

> Hi,

Moin!

> Is there a way to get the binding of the caller?

Yup, there is. See the attached file. It's a bit obscure, but it works 
and shouldn't be too slow.

> Regards,
>   Michael

More regards,
Florian Gross


--------------080303090405040506020701
Content-Type: text/plain;
 nameinding_of_caller.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filenameinding_of_caller.rb"

begin
  require 'simplecc'
rescue LoadError
  def Continuation.create(*args, &block)
    cc  il; result  allcc {|c| cc  ; block.call(cc) if block and args.empty?}
    result || rgs
    return *[cc, *result]
  end
end

# This method returns the binding of the method that called your
# method. It will raise an Exception when you're not inside a method.
#
# It's used like this:
#   def inc_counter
#     Binding.of_caller do |binding|
#       eval("counter + ", binding)
#     end
#   end
#   counter  
#   2.times { inc_counter }
#   counter # 2
#
# You will have to put the whole rest of your method into the
# block that you pass into this method. If you don't do this
# an Exception will be raised. Because of the way that this is
# implemented it has to be done this way. If you don't do it
# like this it will raise an Exception.
def Binding.of_caller(&block)
  old_critical  hread.critical
  Thread.critical  rue
  count  
  cc, result, error  ontinuation.create(nil, nil)
  error.call if error

  tracer  ambda do |*args|
    type, context  rgs[0], args[4]
    if type "return"
      count + 
      # First this method and then calling one will return --
      # the trace event of the second event gets the context
      # of the method which called the method that called this
      # method.
      if count 2
        # It would be nice if we could restore the trace_func
        # that was set before we swapped in our own one, but
        # this is impossible without overloading set_trace_func
        # in current Ruby.
        set_trace_func(nil)
        cc.call(eval("binding", context), nil)
      end
    elsif type ! line"
      set_trace_func(nil)
      error_msg  Binding.of_caller used in non-method context or " +
        "trailing statements of method using it aren't in the block."
      cc.call(nil, lambda { raise(ArgumentError, error_msg ) })
    end
  end

  unless result
    set_trace_func(tracer)
    return nil
  else
    Thread.critical  ld_critical
    yield result
  end
end

--------------080303090405040506020701--