11

可能的重复:
如何用该语言编写语言的编译器?
在“自身”中实现编译器

我在看Rubinius,一个 Ruby 实现,它使用用 Ruby 编写的编译器编译成字节码。我无法理解这一点。你如何用语言本身为一种语言编写编译器?看起来它只是文本,没有任何东西可以将其编译成可执行文件,然后可以编译用 Ruby 编写的未来代码。我只是输入那句话感到困惑。谁能帮忙解释一下?

4

7 回答 7

18

为了简化:你首先为编译器编写一个编译器,用不同的语言。然后,你编译编译器,瞧!

所以,你需要某种已经有编译器的语言——但既然有很多这样的语言,你可以用 C 编写 Ruby 编译器编译器(!),然后编译 Ruby 编译器,然后编译 Ruby 程序,甚至更进一步的版本。

当然,最初的编译器是用机器代码编写的,编译编译器用于汇编,然后编译编译器用于例如 C 或 Fortran,后者编译编译器用于……几乎所有东西。迭代开发在行动。

这个过程被称为引导- 可能以男爵 Munchhausen 的故事命名,他通过自己的引导将自己从沼泽中拉出来 :)

于 2010-11-24T10:28:29.790 回答
3

关于编译器的引导,值得一读这个非常聪明的黑客。

http://catb.org/jargon/html/B/back-door.html

于 2010-11-24T10:58:38.637 回答
2

光看那句话我就糊涂了。

将编译器视为翻译器可能会有所帮助,通常称为编译器。它的目的是获取人类可以阅读的源代码并将其翻译成计算机可以阅读的二进制代码。在 Rubinius 的情况下,它读取的代码恰好是 Ruby 代码,它转换成的代码是机器码(实际上是 LLVM 机器码,它本身进一步编译成 Intel 机器码,但这只是背景细节) . Rubinius 本身几乎可以用任何编程语言编写。它恰好是用它编译的相同语言编写的。

当然,您首先需要一些东西来运行 Rubinius,这很可能是一个常规的 Ruby 解释器。但是请注意,一旦您能够在解释器上运行 Rubinius,您就可以将它自己的源代码传递给它,它会创建并运行它自己的编译版本。这被称为自举,从古老的短语,“通过自举使自己振作起来”。

最后一点:Ruby 程序不能调用任意机器代码。Rubinius 的那部分实际上是用 C++ 编写的。

于 2010-11-24T10:30:37.153 回答
0

那么可以按以下顺序进行:

  1. 用任何语言编写编译器,比如用 C 语言编写 Ruby 代码。
  2. 既然可以编译 Ruby 代码,那你就可以编写一个编译 ruby​​ 代码的编译器,并用你在步骤 1 中编写的 C 编译器编译这个编译器。哇这句话很奇怪!
  3. 从现在开始,您可以使用 2 中编写的编译器编译所有 ruby​​ 代码。:)

玩得开心!:)

于 2010-11-24T10:28:40.133 回答
0

编译器只是将源代码转换为可执行文件的东西。所以不管它是用什么写的——它可以是它正在编译的同一种语言,也可以是任何其他足够强大的语言。

当您为平台的语言编写编译器时,乐趣就来了,使用相同的语言编写,但还没有针对您的实现语言的编译器。您在这里的选择是在您有编译器的另一个平台上编译,或者用另一种语言编写编译器,并使用它来编译“真正的”编译器。

于 2010-11-24T10:30:03.740 回答
0

这是一个两步过程:

  1. 用 C 等其他语言编写一个 Ruby 编译器,假设 Ruby 编译器还不存在
  2. 因为你现在有了一个 Ruby 编译器,你可以编写一个 Ruby 程序,它是一个(新的)Ruby 编译器

由于有人已经编写了一个 Ruby 编译器(Matz),你“只”需要做第二部分。说起来容易做起来难。

于 2010-11-24T10:33:04.690 回答
0

到目前为止,所有答案都解释了如何使用不同的编译器引导编译器。但是,还有另一种选择:手动编译编译器。编译器没有理由必须由机器执行,它也可以由人类执行。

于 2010-11-24T14:24:30.847 回答