PyPy会翻译自己吗?

时间:2011-12-09 22:16:15

标签: python pypy rpython

我直截了当吗? PyPy解释器是否实际解释了自己然后自我翻译?

所以这是我目前的理解:

  • RPython的工具链涉及部分执行要翻译的程序,以获得一种预处理版本来进行注释和翻译。
  • 运行在CPython之上的PyPy解释器执行部分解释本身,此时它将控制权移至RPython的一半,执行转换?

如果这是真的,那么这是我见过的最令人费解的事情之一。

2 个答案:

答案 0 :(得分:65)

PyPy的翻译过程实际上在概念上不如听起来那么递归。

实际上它只是一个Python程序,它处理Python函数/类/其他对象( Python源代码)并输出C代码。但是它当然不会处理任何 Python对象;它只能处理特定的表单,如果你在RPython中编写要翻译的代码,那就是你得到的。

由于翻译工具链是一个Python程序,你可以在任何Python解释器上运行它,这显然包括PyPy的python解释器。所以没什么特别的。

由于它翻译了RPython对象,你可以用它来翻译PyPy的python解释器,它是用RPython编写的。

但是您无法在翻译框架本身上运行它,而不是 RPython。只有PyPy的python解释器本身就是RPython。

事情只会变得有趣,因为RPython代码也是Python代码(但不是反过来的),因为RPython并不是真的存在"在源文件中,但只在内存中的一个有效的Python进程内部必须包含其他非RPython代码(例如,没有"纯-Ryython"导入或函数定义,因为翻译器操作的函数是已定义并导入)。

请记住,翻译工具链可以在内存中的Python代码对象上运行。 Python的执行模型意味着这些在某些Python代码运行之前不存在。你可以想象,如果你高度简化它,开始翻译过程看起来有点像这样:

from my_interpreter import main
from pypy import translate

translate(main)

众所周知,只需导入main即可运行大量Python代码,包括所有其他模块my_interpreter导入。但是翻译过程开始分析功能对象 main;它永远不会看到,也不关心,无论执行什么代码来提出main

想到这一点的一种方法是在RPython中进行编程"意味着"编写一个生成RPython程序的Python程序,然后将其提供给翻译过程"。这相对容易理解并且与其他编译器的工作方式类似(例如,在C语言中编程的一种方法是,您实际上是在编写一个生成C程序的C预处理器程序,这是然后送到C编译器。)

在PyPy案例中只会让事情变得混乱,因为所有3个组件(生成RPython程序的Python程序,RPython程序和翻译过程)都被加载到相同的Python解释器中。这意味着当使用某些参数调用时,很可能有RPython函数,而不是在使用其他参数调用时,作为生成RPython程序的一部分从转换框架调用辅助函数,以及许多其他奇怪的事情。所以情况变得相当模糊,你不能将你的源代码线干净地分成" RPython进行翻译"," Python生成我的RPython程序"和#34;将RPython程序交给翻译框架"。


  

在CPython之上运行的PyPy解释器部分执行   解释自己

我认为你在这里提到的是PyPy在翻译过程中使用the flow object space进行抽象解释。即使这不像最初看起来那样疯狂和令人费解。我对PyPy的这一部分知之甚少,但据我所知:

PyPy通过将它们委托给一个"对象空间"来实现Python解释器的所有操作,该对象空间包含所有基本内置操作的实现。但是你可以插入不同的对象空间来获得不同的效果,只要它们实现相同的对象空间"接口解释器仍然能够执行" Python代码。

PyPy转换工具链处理的RPython代码对象是可由解释器执行的Python代码。因此,PyPy通过插入流对象空间,重新使用部分Python解释器作为转换工具链的一部分。当"执行"对于具有该对象空间的代码,解释器实际上并不执行代码的操作,而是生成流程图,其类似于许多其他编译器使用的各种中间表示;它只是一个简单的机器可操作的代码表示,有待进一步处理。这就是常规(R)Python代码对象如何转换为其余翻译过程的输入。

由于通过翻译过程翻译的通常事物是PyPy的Python解释器,它确实"解释自己"与流对象空间。但真正意味着你有一个Python程序正在处理Python函数,包括那些正在处理的函数。就其本身来说,除了将装饰器应用于自身,或者使用包装器类包装自身的实例(或包装类本身)之外,它本身并没有任何令人头疼的方法。


嗯,有点混乱。无论如何,我希望它有所帮助,我希望我没有说过任何不准确之处;如果我有,请纠正我。

答案 1 :(得分:12)

  

免责声明:我不是PyPy的专家 - 特别是,我不了解RPython翻译的细节,我只引用我之前读过的内容。有关RPython翻译 的工作方式的更具体的帖子,请查看此answer

答案是,是的,它可以(但只有在首次使用CPython编译之后)。

更长的描述:

起初它看起来非常精神错乱和矛盾,但一旦你理解它,它很容易。在Wikipedia上查看答案。

  

程序开发中的引导开始于20世纪50年代,当时每个程序都是用十进制代码或二进制代码,一点一点(1s和0s)在纸上构建的,因为没有高级计算机语言,没有编译器,没有汇编程序,没有链接器。一个微小的汇编程序是为一台新计算机(例如IBM 650)手工编写的,它将一些指令转换成二进制或十进制代码:A1。然后,这个简单的汇编程序用刚刚定义的汇编语言重写,但扩展可以使用一些额外的助记符来处理更复杂的操作代码。

该过程称为软件自举。基本上,你用较低的语言构建了一个工具,比如一个C ++编译器,它已经被制作出来了(一点上的所有东西都必须用二进制编码),比如ASM。现在您已经拥有了C ++,现在可以用C ++编写C ++编译器,然后使用ASM C ++编译器编译新的编译器。在编译完新编译器之后,您现在可以使用它来编译自己。

所以基本上,用手工编写第一个计算机工具,使用该解释器制作另一个更好的解决方案,然后使用那个解决方案做出更好的解决方案......最终你今天就得到了所有复杂的软件! :)

另一个有趣的案例是CoffeeScript语言,它是用...写的。CoffeeScript。 (虽然这个用例仍然需要使用外部解释器,即Node.js)

运行在CPython之上的PyPy解释器执行以部分解释自己,此时它将控制到其RPython的一半,执行转换?

您可以使用已编译的PyPy解释器编译PyPy,也可以使用CPython编译它。但是,既然PyPy现在有一个JIT,那么使用它本身而不是CPython来编译PyPy会更快。 (大多数情况下PyPy is now faster than CPython