2011-12-20 4 views
2

Я недавно проработал путь по программированию языка Pragmatics 3rd ed, чтобы узнать больше о том, как работают языки под ним, и я получил много пробега, не глядя на сборку, созданную на самом деле скомпилированным кодом CCC. Я начал более комфортно работать со статическими языками из семейства C, и я хотел бы также начать изучать интерпретируемые языки.Видя под капотом Руби?

Ruby, являющийся моим любимым языком сценариев, был бы отличным кандидатом на это. Я думаю, что было бы хорошо начать с МРТ для учебных целей и выяснить, как точно все сканирование/разбор/семантический анализ/привязка/область охвата и другая магия происходят за кулисами.

Разве это подробно описано в любом месте, или есть ли какой-либо способ для меня копаться в нем, например, с разборкой скомпилированной программы? Я не очень много копался с интерпретируемыми языками, поэтому я не знал бы, с чего начать, насколько это касается МРТ.

Спасибо!

ответ

4

Вы можете заглянуть в YARV байткод любого бита исходного кода Ruby, с RubyVM::InstructionSequence

Вот краткий пример:

class Greeter 
    def initialize(name) 
    @name = name 
    end 
    def greet! 
    puts @name 
    end 
end 

Greeter.new("Charlie").greet! 

Тогда вы можете скомпилировать его и разобрать его:

puts RubyVM::InstructionSequence.compile(src).disassemble 

И получить некоторые результаты следующим образом:

== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>========== 
0000 trace   1            ( 1) 
0002 putspecialobject 3 
0004 putnil   
0005 defineclass  :Greeter, <class:Greeter>, 3 
0009 pop    
0010 trace   1            ( 10) 
0012 getinlinecache 19, <ic:0> 
0015 getconstant  :Greeter 
0017 setinlinecache <ic:0> 
0019 putstring  "Charlie" 
0021 send    :new, 1, nil, 0, <ic:1> 
0027 send    :greet!, 0, nil, 0, <ic:2> 
0033 leave    
== disasm: <RubyVM::InstructionSequence:<class:Greeter>@<compiled>>===== 
0000 trace   2            ( 1) 
0002 trace   1            ( 2) 
0004 putspecialobject 1 
0006 putspecialobject 2 
0008 putobject  :initialize 
0010 putiseq   initialize 
0012 send    :"core#define_method", 3, nil, 0, <ic:0> 
0018 pop    
0019 trace   1            ( 5) 
0021 putspecialobject 1 
0023 putspecialobject 2 
0025 putobject  :greet! 
0027 putiseq   greet! 
0029 send    :"core#define_method", 3, nil, 0, <ic:1> 
0035 trace   4            ( 8) 
0037 leave               ( 5) 
== disasm: <RubyVM::InstructionSequence:[email protected]<compiled>>========== 
local table (size: 2, argc: 1 [opts: 0, rest: -1, post: 0, block: -1] s1) 
[ 2] name<Arg> 
0000 trace   8            ( 2) 
0002 trace   1            ( 3) 
0004 getlocal   name 
0006 dup    
0007 setinstancevariable :@name, <ic:0> 
0010 trace   16            ( 4) 
0012 leave               ( 3) 
== disasm: <RubyVM::InstructionSequence:[email protected]<compiled>>============== 
0000 trace   8            ( 5) 
0002 trace   1            ( 6) 
0004 putnil   
0005 getinstancevariable :@name, <ic:0> 
0008 send    :puts, 1, nil, 8, <ic:1> 
0014 trace   16            ( 7) 
0016 leave               ( 6) 
+0

Страница Википедии на YARV предполагает, что это то, что работает шоу, начиная с 1,9, и поэтому он действительно настолько близок, что вы можете увидеть канонический рубин (в отличие от, скажем, rubinius и jruby?) Является ли это более-менее точным ? –

+0

@glitch Да. Рубиний и JRuby имеют свой собственный байт-код, который должен быть так же легко заглянуть в –

1

Существует a Japanese book, который описывает внутреннюю работу МРТ 1.7.3, названную рубиновым хакерским руководством. A partial English translation.

Несмотря на то, что перевод не завершен, и книга была основана на более ранней версии рубина, я по-прежнему считаю ее превосходным ресурсом. Многие вещи, охватываемые книгой, вероятно, по-прежнему актуальны в текущих рубиновых версиях, таких как структура объектов, как хранятся переменные экземпляра, как выполняется поиск методов и т. Д.

Это очень интересное чтение. Однако вы должны следить за различиями между версиями. Всегда держите ruby source code под рукой.