在Ruby的引擎盖下看到了什么?

时间:2011-12-20 07:01:55

标签: ruby programming-languages language-design interpreter

我最近一直在通过编程语言语言学第3版来学习更多关于语言如何在其下工作的方法,并且我已经从看到由真正基本的GCC编译的C代码生成的程序集中获得了很多好处。 。我开始对C系列的静态语言感到更舒服,我也想开始研究解释语言。

Ruby,作为我最喜欢的脚本语言,将是一个很好的候选人。我认为从学习目的开始使用MRI是可以的,并弄清楚所有的扫描/解析/语义分析/绑定/范围以及其他魔法是如何在幕后发生的。

这是在任何地方详细描述的,还是有任何方法让我深入研究,比如说,编译程序的反汇编?我没有用解释语言进行太多挖掘,所以就MRI而言,我不知道从哪里开始。

谢谢!

3 个答案:

答案 0 :(得分:4)

您可以使用RubyVM::InstructionSequence

查看任何Ruby源代码的YARV字节码

这是一个简单的例子:

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:initialize@<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:greet!@<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)

答案 1 :(得分:2)

Ruby本身是用C语言编写的,因此可能值得一看。 https://github.com/ruby/ruby

我还推荐Patrick Farley关于方法调度的文章。 http://www.klankboomklang.com/2007/09/14/method-dispatch/

答案 2 :(得分:1)

a Japanese book描述了MRI 1.7.3的内部工作方式,称为Ruby Hacking Guide。 A partial English translation可用。

即使翻译不完整且本书基于较旧版本的ruby,我仍然认为它是一种极好的资源。本书涵盖的许多内容可能仍然与当前的ruby版本相关,例如对象的结构,实例变量的存储方式,方法查找的完成方式等等。

这是一篇非常有趣的读物。但是,您必须注意版本之间的差异。始终保持ruby source code