Skip to content

Instantly share code, notes, and snippets.

@headius
Last active December 18, 2015 09:09
Show Gist options
  • Select an option

  • Save headius/5758887 to your computer and use it in GitHub Desktop.

Select an option

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

badosu commented Jun 12, 2013

Copy link
Copy Markdown

Wow, that is great!

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