2013-02-22 18 views

Odpowiedz

8

Spójrz na sourcify gem:

proc { x + y }.to_source 
# >> "proc { (x + y) }" 
+1

sourcify ma pułapka na nic po Ruby 1.9. Miałem szczęście z gemem source_method dla Ruby 2.1.2 (którego wersja zawiera jako zależność, więc była już dostępna w naszej infrastrukturze testowej, gdzie go potrzebowałem). Mam szczegółową odpowiedź tutaj: http://stackoverflow.com/questions/1675053/printing-the-source-code-of-a-ruby-block/36654421#36654421 – Nick

5

masz na myśli oryginalnego kodu źródłowego lub jego kodu bajtowego reprezentacja?

Dla tych pierwszych można użyć standardowej metody Proc za source_location

p.source_location 
=> ["test.rb", 21] 

i przeczytać odpowiednie linie kodu.

W tym ostatnim przypadku może się przydać RubyVM :: InstructionSequence a jego metoda klasy demontażu:

irb> RubyVM::InstructionSequence.disasm p 
=> "== disasm: <RubyVM::InstructionSequence:block in [email protected](irb)> 
=====\n== catch table\n| catch type: redo st: 0000 ed: 0011 sp: 0000 
cont: 0000\n| catch type: next st: 0000 ed: 0011 sp: 0000 cont: 
0011\n|------------------------------------------------------------------------\n 
0000 trace   1            
( 1)\n0002 putself   \n0003 putstring  \"ok\"\n0005 
send    :puts, 1, nil, 8, <ic:0>\n0011 leave   \n" 
+1

'RubyVM' jest niestandardowym rozszerzeniem przez YARV . Nie jest częścią specyfikacji języka Ruby. MRI go nie ma, Rubinius go nie ma, MagLev go nie ma, JRuby go nie ma, IronRuby go nie ma. Wolałbym nie polegać na czymś, co działa tylko na jednej implementacji Rubiego. –

+0

@ JörgWMittag Więc MRI utknął na poziomie 1.8, a Ruby 1.9 nie jest * oficjalną * implementacją? –

+0

@ JörgWMittag Z drugiej strony generalnie zgadzam się nie polegać na konkretnych funkcjach implementacyjnych, ale czasami trudno je zachować. –

4

Nie, nie ma sposobu, aby to zrobić w Ruby.

Niektóre implementacje Ruby mogą lub nie mogą mieć sposoby realizacji konkretnych na uzyskanie kodu źródłowego.

Można także spróbować użyć pliku Proc#source_location, aby znaleźć plik, w którym zdefiniowano Proc, a następnie przeanalizować plik, aby znaleźć kod źródłowy. Ale to nie zadziała, jeśli Proc nie został zdefiniowany w pliku (np. Jeśli został zdefiniowany dynamicznie z eval) lub jeśli plik źródłowy już nie istnieje, np. ponieważ używasz skompilowanej wersji AOT programu.

Krótka odpowiedź brzmi: nie, nie ma mowy. Długa odpowiedź brzmi: istnieją pewne sposoby, które mogą, ale nie muszą, działać w zależności od zbyt wielu czynników, aby nawet zacząć działać niezawodnie.

to nawet nie biorąc pod uwagę Proc s, które nie mają nawet kod źródłowy Ruby, ponieważ zostały one zdefiniowane w natywnym kodzie.

1

Jeśli proc jest zdefiniowana w pliku, U można uzyskać lokalizację pliku proc następnie szeregować je, a następnie po deserializowania wykorzystywać lokalizację, aby wrócić do proc ponownie

proc_location_array = proc.source_location

po Cofnięcie:

nazwa_pliku_logu = proc_location_array [0]

LINE_NUMBER = proc_location_array [1]

proc_line_code = IO.readlines (nazwa_pliku_logu) [LINE_NUMBER - 1]

proc_hash_string = proc_line_code [proc_line_code.index ("{") .. proc_line_code.Długość]

Proc = Eval ("N # {proc_hash_string}")

Powiązane problemy