Skip to content

Instantly share code, notes, and snippets.

@hanachin
Last active December 16, 2015 15:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hanachin/68f0b0b1ee63453e26b8 to your computer and use it in GitHub Desktop.
Save hanachin/68f0b0b1ee63453e26b8 to your computer and use it in GitHub Desktop.
ブロック中の数値が全て2倍になるメソッド書いてみた
#! ./ruby -I.ext/x86_64-darwin14 --disable-gems
require '-test-/iseq_load/iseq_load'
def double(&block)
iseq_data_magic_index = 0
iseq_data_major_version_index = 1
iseq_data_minor_version_index = 2
iseq_data_format_type_index = 3
iseq_data_misc_index = 4
iseq_data_label_index = 5
iseq_data_path_index = 6
iseq_data_absolute_path_index = 7
iseq_data_first_lineno_index = 8
iseq_data_type_index = 9
iseq_data_locals_index = 10
iseq_data_params_index = 11
iseq_data_catch_table_index = 12
iseq_data_bytecode_index = 13
iseq = RubyVM::InstructionSequence.of(block)
iseq_data = iseq.to_a
new_bytecodes = []
old_bytecodes = iseq_data[iseq_data_bytecode_index]
old_bytecodes.each do |bytecode|
if bytecode.kind_of?(Array) && bytecode.first == :putobject && bytecode.last.kind_of?(Fixnum)
new_bytecodes << [bytecode.first, bytecode.last * 2]
else
new_bytecodes << bytecode
end
end
new_iseq_data = iseq_data.dup
new_iseq_data[iseq_data_bytecode_index] = new_bytecodes
# topじゃないとevalときエラーになるのでblockをtopに細工
if new_iseq_data[iseq_data_type_index] == :block
new_iseq_data[iseq_data_type_index] = :top
end
new_iseq = RubyVM::InstructionSequence.iseq_load(new_iseq_data)
new_iseq.eval
end
double { puts 3 * 5 }
# 60
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment