Ale*_*lex 48 python pypy rpython
我直截了当吗?PyPy解释器是否真正解释自己然后翻译自己?
所以这是我目前的理解:
如果这是真的,那么这是我见过的最令人头疼的事情之一.
Ben*_*Ben 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代码(例如,没有"纯RPython"导入或函数定义,因为翻译器对已经定义和导入的函数进行操作).
请记住,翻译工具链在内存中的Python代码对象上运行.Python的执行模型意味着在某些Python代码运行之前它们不存在.你可以想象,如果你高度简化它,开始翻译过程看起来有点像这样:
from my_interpreter import main
from pypy import translate
translate(main)
Run Code Online (Sandbox Code Playgroud)
众所周知,只需导入main就可以运行大量的Python代码,包括所有其他模块的my_interpreter导入.但是翻译过程开始分析功能对象 main ; 它永远不会看到,也不关心,无论执行什么代码都能提出来main.
想到这一点的一种方法是"在RPython中编程"意味着"编写一个生成RPython程序的Python程序,然后将其提供给翻译过程".这是相对容易理解的,并且与其他编译器的工作方式类似(例如,在C语言中考虑编程的一种方法是,您实际上是在编写一个C预处理器程序,该程序生成一个C程序,然后将其输入到C编译器).
事情只会在PyPy案例中变得混乱,因为所有3个组件(生成RPython程序的Python程序,RPython程序和翻译过程)都被加载到同一个Python解释器中.这意味着当使用一些参数调用时,很可能有RPython函数,而不是在使用其他参数调用时,在生成RPython程序时从转换框架调用辅助函数,以及许多其他奇怪的事情.所以情况变得相当模糊,你不一定能将你的源代码线干净地划分为"要翻译的RPython","Python生成我的RPython程序"和"将RPython程序交给翻译框架".
在CPython之上运行的PyPy解释器执行以部分解释自身
我认为你在这里提到的是PyPy 在翻译过程中使用流对象空间来做抽象解释.即便如此,这并不像最初看起来那样疯狂和令人费解.我对PyPy的这一部分知之甚少,但据我所知:
PyPy通过将它们委托给"对象空间"来实现Python解释器的所有操作,该对象空间包含所有基本内置操作的实现.但是你可以插入不同的对象空间来获得不同的效果,只要它们实现相同的"对象空间"接口,解释器仍然可以"执行"Python代码.
PyPy转换工具链处理的RPython代码对象是可由解释器执行的Python代码.因此,PyPy通过插入流对象空间,重新使用部分Python解释器作为转换工具链的一部分.当用这个对象空间"执行"代码时,解释器实际上不执行代码的操作,而是生成流程图,类似于许多其他编译器使用的各种中间表示; 它只是一个简单的机器可操作的代码表示,有待进一步处理.这就是常规(R)Python代码对象如何转换为其余翻译过程的输入.
由于通过翻译过程翻译的通常事物是PyPy的Python解释器,它确实用流对象空间"解释自己".但真正意味着你有一个Python程序正在处理Python函数,包括那些正在处理的函数.本身并不比将装饰器应用于自身,或者使用包装类包装自身的实例(或包装类本身)更令人头疼.
嗯,有点rambly.无论如何,我希望它有所帮助,我希望我没有说任何不准确之处; 如果我有,请纠正我.
Joh*_*Doe 12
免责声明:我不是PyPy的专家 - 特别是,我不了解RPython翻译的细节,我只是引用我以前读过的东西.有关RPython翻译如何更具体的岗位可以正常工作,看看这个答案.
答案是,是的,它可以(但只有在它首次使用CPython编译之后).
更长的描述:
起初它似乎高度弯曲和矛盾,但一旦你理解它,它很容易.在维基百科上查看答案.
程序开发中的引导开始于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现在比CPython更快)