secret
Last active

  • Download Gist
rb-make-iseq-umethod.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
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

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.