Last active
December 18, 2015 09:09
-
-
Save headius/5758887 to your computer and use it in GitHub Desktop.
Binding.of_caller for JRuby, implemented in Ruby.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Wow, that is great!