有没有可能创建动态语言编译器而不失去其动态特性?

3
有哪些原因使得动态语言(如Python或Ruby)无法编译而只能解释?是否有可能创建一种编译器,使这些语言不会失去元编程、对象扩展、添加代码或在运行时修改类型系统等特性?总而言之,是否可能创建一个Ruby或Python编译器,同时不失去其作为动态编程语言的特性?

Python是编译型语言,编译成Python字节码。 - Martijn Pieters
3
语言并非编译或解释。一种语言的实现可以是解释或编译的,但实际上并没有明显的区别。事实上,使用Futamura投影,可以在自动方式下,给定一个解释器来获得一个编译器,因此很明显可以创建Python/Ruby编译器。真正的问题是:它会更快,或者它会带来任何优势吗? - Bakuriu
2
@jfcalvo:机器码只是由CPU解释的字节码。唯一的区别在于硬件和代码之间的层数。Java也是通过虚拟机进行解释的。这些问题并不是非黑即白的。 - Martijn Pieters
1
@martineau 要么是那样(虽然那实际上是一个JIT编译器,因此很难在设计为AOT工作的编译器中实现),要么它将解释器包含到二进制文件中。 - user395760
1
我不认为这个问题是基于观点的。"是否可能创建一个Ruby或Python编译器,而不失去它们作为编程语言的任何特性?",答案是肯定或否定,并附有解释。我投票支持重新开放。 - fotanus
显示剩余4条评论
2个回答

2
是的,动态语言可以创建编译器。实际上,已经有很多动态语言的编译器了,例如:
- CPython是Python语言的一种实现,它有一个Python编译器。 - PyPy是Python语言的一种实现,它有一个Python编译器。 - Jython是Python语言的一种实现,它有一个Python编译器。 - IronPython是Python语言的一种实现,它有一个Python编译器。 - Pynie是Python语言的一种实现,它有一个Python编译器。 - YARV是Ruby语言的一种实现,它有一个Ruby编译器。 - Rubinius是Ruby语言的一种实现,它有一个Ruby编译器。 - MacRuby是Ruby语言的一种实现,它有一个Ruby编译器。 - JRuby是Ruby语言的一种实现,它有一个Ruby编译器。 - IronRuby是Ruby语言的一种实现,它有一个Ruby编译器。 - MagLev是Ruby语言的一种实现,它有一个Ruby编译器。 - Quercus是PHP语言的一种实现,它有一个PHP编译器。 - P8是PHP语言的一种实现,它有一个PHP编译器。 - V8是ECMAScript语言的一种实现,它有一个ECMAScript编译器。
总的来说,任何语言都可以通过编译器来实现,也可以通过解释器来实现。甚至可以从解释器中自动派生出编译器,反之亦然。
大多数现代语言实现都同时使用解释和编译,有时甚至使用多个编译器。例如,Rubinius首先将Ruby代码编译成Rubinius字节码,然后由Rubinius虚拟机解释执行。已经解释多次的代码会被编译成Rubinius Compiler IR,然后编译成LLVM IR,最终编译成“本地代码”(无论是什么)。因此,Rubinius有一个解释器和三个编译器。
V8是另一个例子。它实际上没有解释器,但有两个不同的编译器:一个非常快速、非常内存高效的编译器,生成未优化的、略慢的代码。已经运行多次的代码将被丢弃,并使用第二个编译器重新编译,该编译器生成更积极优化的代码,但编译时间更长,在编译期间使用更多的内存。
然而,最终你不能在没有解释器的情况下运行代码。编译器不能运行代码。编译器将程序从一种语言翻译成另一种语言。就这样。你可以尽情翻译,但最终,必须有“某个东西”来运行代码,而这个东西就是解释器。它可以在软件或硅片中实现,但它仍然是一个解释器。

1
编译器不能运行代码 - 当然,它可以运行一些代码,但它不会运行您的最终程序,否则它就不会被称为“编译器”,而应该被称为“运行时”。例如,C++模板是一种将编译器欺骗成执行声明性语言而非命令式语言编写的代码的方法。编译器执行的此代码的输出是编译时实体(类、函数),它们组成编译器输出的程序的一部分。 - Steve Jessop
@SteveJessop:是的,这就是我想说的,谢谢你澄清。当然,编译器运行代码,至少它必须运行执行编译的代码。对于像C++模板、Scala的图灵完备类型系统、甚至是C#中的重载分辨率(虽然不是图灵完备,但可以编码任何3-SAT问题)和当然还有Lisp宏,编译器需要嵌入一个解释器来解释该语言或在“主”程序的编译之前编译它们。 - Jörg W Mittag
如果“没有解释器无法运行代码”,那解释器是如何运行的呢? - fotanus
@fotanus:根据这个定义,CPU 是一个解释器。它按照某些抽象规范通过推动电子来运行。 - Steve Jessop
@fotanus:解释器不一定是代码。它可以是一个人,例如 - 你从未在脑海中或用纸笔执行过程序吗?但更常见的情况是解释器是在硅中实现的。 - Jörg W Mittag

1
我假设你所说的"compile"是指"编译成本地机器代码",让别人来挑战这个非常狭隘的定义。答案是一个响亮的"是"。事实上,人们正在做这件事:
  • Nuitka
  • Cython(实际上不是Python,但非常接近,可以支持完整的Python)。
  • 各种“冻结”工具,尽管在技术上它们只是将字节码和字节码解释器打包到一个二进制文件中。
然而,这样的编译器不能执行许多(我会说几乎没有)优化,因此生成的代码基本上等同于简单的解释器所做的,你只能节省解释开销(同时失去一些解释器的好处,包括紧凑的代码和更快的周转时间)。换句话说:动态、正确、快速——选择两个(全面披露:被接受的答案是我的)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接