У меня есть следующие настройки в Ruby 2.6.3:
def some_method(&block)
@block = block
end
some_method do
puts "Hello There!"
puts "General Kenobi"
end
Мне нужно взять pro c, который выходит из some_method
, и извлечь буквенный код, который был передан в данный блок, в этом примере я бы идеально получил:
"puts \"Hello There!\"\n puts \"General Kenobi\""
в виде строки, чтобы я мог оценить переданный код на более позднем этапе. Тем не менее, кажется, что все, что я мог найти для этого, уходило в окно после Ruby 1,9 (parse_tree и ruby2 ruby являются основными методами). В предыдущих итерациях этого проекта, где мне приходилось делать такие же странные вещи с Procs, я мог использовать source_location
переданного pro c, чтобы выяснить контент достаточно хорошо, чтобы достичь этого. К сожалению, я больше не могу полагаться на то, что pro c имеет законное местоположение источника, чтобы это работало.
Мой вопрос таков: Есть ли в современном Ruby способ, которым я мог бы просто чтобы получить внутреннюю часть этого про c, источник которого не существует надежно ?
Ища какой-то способ выяснить это, я наткнулся на класс RubyVM::InstructionSequence
и смог использовать это, чтобы вывести следующее о про c, о котором идет речь:
# Continuing from the first example
obj = RubyVM::InstructionSequence.of(@block)
puts obj.disasm
=> == disasm: #<ISeq:block in __pry__@(pry):7 (7,12)-(10,3)> (catch: FALSE)
== catch table
| catch type: redo st: 0001 ed: 0014 sp: 0000 cont: 0001
| catch type: next st: 0001 ed: 0014 sp: 0000 cont: 0014
|------------------------------------------------------------------------
0000 nop ( 7)[Bc]
0001 putself ( 8)[Li]
0002 putstring "Hello There!"
0004 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0007 pop
0008 putself ( 9)[Li]
0009 putstring "General Kenobi"
0011 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0014 nop
0015 leave ( 10)[Br]
Глядя на это, я ясно вижу инструкции по загрузке и запуску данного кода, но, особенно с сложный процесс, это не то, что я не могу и не хочу надежно десериализовать. Таким образом, последующий вопрос будет: Есть ли способ чистой десериализации этих инструкций RubyVM :: InstructionSequence ?