Skip to content

Instantly share code, notes, and snippets.

@benolee
Last active December 16, 2015 14:20
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 benolee/868c72f16642e498e238 to your computer and use it in GitHub Desktop.
Save benolee/868c72f16642e498e238 to your computer and use it in GitHub Desktop.
require 'fiddle'
class RubyVM
class InstructionSequence
func = Fiddle::Function.new(Fiddle::Handle::DEFAULT['rb_iseq_load'], [Fiddle::TYPE_VOIDP] * 3, Fiddle::TYPE_VOIDP)
define_singleton_method(:load) do |data, parent = nil, opt = nil|
func.call(Fiddle.dlwrap(data), parent, opt).to_value
end
end
end
class C
def default_iseq
self
end
DEFAULT_ISEQ = RubyVM::InstructionSequence.of(instance_method(:default_iseq)).to_a.freeze
def make_unbound_method(options = {})
opts = {module_name: :Foo, method_name: :changeme, instructions: DEFAULT_ISEQ}.merge(options)
module_name = opts[:module_name]
method_name = opts[:method_name]
instructions = opts[:instructions]
RubyVM::InstructionSequence.load(Marshal.load(Marshal.dump(["YARVInstructionSequence/SimpleDataFormat", 2, 0, 1, {:arg_size=>0, :local_size=>2, :stack_max=>2}, "<compiled>", "", "", 0, :top, [:mod], 0, [], [[:putnil], [:getconstant, :Module], [:send, {:mid=>:new, :flag=>256, :orig_argc=>0, :blockptr=>nil}], [:setlocal, 2, 0], [:getlocal, 2, 0], [:putnil], [:defineclass, module_name, ["YARVInstructionSequence/SimpleDataFormat", 2, 0, 1, {:arg_size=>0, :local_size=>1, :stack_max=>4}, "<module:#{module_name}>", "", "", 1, :class, [], 0, [], [[:putspecialobject, 1], [:putspecialobject, 2], [:putobject, method_name], [:putiseq, instructions], [:send, {:mid=>:"core#define_method", :flag=>256, :orig_argc=>3, :blockptr=>nil}], [:pop], [:putself], [:leave]]], 10], [:leave]]]))).eval
end
end
if $0 == __FILE__
def foo
:bar!
end
def test_it
@it_mod = C.new.make_unbound_method(module_name: :WOAH, method_name: :haha, instructions: RubyVM::InstructionSequence.of(method(:foo)).to_a)
@it = @it_mod.instance_method(:haha)
end
test_it
#=> #<UnboundMethod: #<Module:0x0000010123b9d0>::WOAH#haha>
@it.bind(self).call
#=> :bar!
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment