PyPy翻译自己吗?

我正确吗? PyPy解释器是否实际解释自己然后翻译自己?

所以这是我目前的理解:

  • RPython的工具链涉及部分执行程序进行翻译,以获得一种预处理版本的注释和翻译。
  • 运行在CPython之上的PyPy解释器执行部分解释在这一点上,它将把它控制到它的RPython的一半,它执行翻译?

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

PyPy的翻译过程实际上远不如概念上的recursion。

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

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

由于它翻译了RPython对象,因此可以使用它来翻译Pyython的Python解释器,它是用RPython编写的。

但是你不能在翻译框架本身上运行它,这不是 RPython。 只有PyPy的Python解释器本身是RPython。

事情只是变得有趣,因为RPython代码也是Python代码(但不是相反的),并且因为RPython在源文件中并没有“真正存在”,而只存在于工作Python进程中的内存中,这个进程必然包含其他非RPython代码(没有“纯RPython”导入或函数定义,例如,因为翻译器对已经定义和导入的函数进行操作)。

请记住,翻译工具链在内存中的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被某些参数调用时,而不是被其他参数调用时,从翻译框架调用helper函数作为生成RPython程序的一部分,还有很多其他奇怪的事情。 所以情况变得相当模糊,你不一定要把源代码干净地分成“需要翻译的RPython”,“生成我的RPython程序的Python”和“将RPython程序交给翻译框架”。


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

我认为你在这里指的是PyPy在翻译过程中使用stream对象空间来做抽象的解释。 即使这不像起初看起来那么疯狂和令人费解。 我对PyPy的这部分知之甚less,但据我所知:

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

PyPy翻译工具链处理的RPython代码对象是可以由解释器执行的Python代码。 因此,PyPy通过插入stream对象空间,将部分Python解释器作为翻译工具链的一部分。 当用这个对象空间“执行”代码时,解释器实际上并不执行代码的操作,而是产生stream程图,类似于许多其他编译器使用的中间表示的种类; 这只是一个简单的机器可操作的代码表示,需要进一步处理。 这就是常规(R)Python代码对象如何转化为其余翻译过程的input。

由于通常的翻译过程是PyPy的Python解释器,所以它确实用stream对象空间“自我解释”。 但所有这一切意味着你有一个正在处理Python函数的Python程序,包括正在处理的Python程序。 它本身并不比将自己的装饰器应用于装饰器,或者将自己的实例包装到自己的实例(或包装类本身)上。


呃,这有点棘手。 无论如何,我希望它有帮助,我希望我没有说任何不准确的东西。 请纠正我,如果我有。

免责声明:我不是PyPy的专家 – 特别是我不明白RPython翻译的细节,我只引用了我之前读过的东西。 有关RPython翻译如何工作的更具体的文章,请查看这个答案 。

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

更长的描述:

起初,它似乎高度弯曲和矛盾,但一旦你明白了,这很容易。 检查维基百科的答案。

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

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

所以基本上,通过手工编写第一台计算机工具,使用这个解释器做一个更好的,然后用它来做一个更好的,最后你今天就得到所有复杂的软件! 🙂

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

运行在CPython之上的PyPy解释器执行部分解释,在这一点上,它将把它控制到它的RPython的一半,它执行翻译?

您可以使用已经编译好的PyPy解释器来编译PyPy,也可以使用CPython来编译它。 但是,由于PyPy现在有一个JIT,使用它自己而不是CPython来编译PyPy会更快。 (在大多数情况下, PyPy现在比CPython快 )