Skip to content

Instantly share code, notes, and snippets.

@headius
Last active December 18, 2015 09:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save headius/5758887 to your computer and use it in GitHub Desktop.
Save headius/5758887 to your computer and use it in GitHub Desktop.
Binding.of_caller for JRuby, implemented in Ruby.
ext-jruby-local ~/projects/jruby $ jruby binding_of_caller.rb
RuntimeError: caller binding only supported in interpreter
binding_of_caller at binding_of_caller.rb:24
of_caller at binding_of_caller.rb:4
foo at binding_of_caller.rb:39
(root) at binding_of_caller.rb:43
ext-jruby-local ~/projects/jruby $ jruby -X-C binding_of_caller.rb
2
class << Binding
def of_caller(index = 1)
index += 1 # always omit this frame
JRuby.runtime.current_context.binding_of_caller(index)
end
end
class org::jruby::runtime::ThreadContext
java_import org.jruby.runtime.Binding
java_import org.jruby.RubyBinding
java_import org.jruby.RubyInstanceConfig::CompileMode
field_accessor :frameStack, :frameIndex,
:scopeStack, :scopeIndex,
:backtrace, :backtraceIndex
def binding_of_caller(index)
index += 1 # always omit this frame
raise IndexError, "insufficient frames for index #{index}" if index > frameIndex
compile_mode = JRuby.runtime.instance_config.compile_mode
unless compile_mode == CompileMode::OFF
raise RuntimeError, "caller binding only supported in interpreter"
end
frame = frameStack[frameIndex - index]
scope = scopeStack[scopeIndex - index]
element = backtrace[backtraceIndex - index]
binding = Binding.new(frame, scope.static_scope.module, scope, element.clone)
JRuby.dereference(RubyBinding.new(JRuby.runtime, Binding, binding))
end
end
x = 1
def foo
b = Binding.of_caller
eval "x = 2", b
end
foo
puts x
@badosu
Copy link

badosu commented Jun 12, 2013

Wow, that is great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment