Как прочитать содержимое Ruby Pro c в строку - PullRequest
0 голосов
/ 26 февраля 2020

У меня есть следующие настройки в 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 ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...