RPython 入门¶
警告
请先 阅读此常见问题解答条目!
RPython 是 Python2 的一个子集,可以进行静态编译。PyPy 解释器主要用 RPython 编写(部分使用 Python),而 RPython 编译器则用 Python 编写。难以理解的部分是,Python 是 RPython 的元编程语言,也就是说,“是否是有效的 RPython” 只有在导入完成后的活动对象上才有意义。这可能需要更多解释。您从 entry_point
开始编写 RPython,一个好的起点是 rpython/translator/goal/targetnopstandalone.py。它并没有做太多事情,但这是一个开始。现在如果分析的代码(在本例中为 entry_point
)调用了一些函数,那么这些调用将被跟踪。这些被跟踪的调用本身必须是 RPython(以及它们调用的所有内容等等),但不是整个模块文件。为了展示如何使用元编程,我们可以举一个简单的例子(注意,闭包不是 RPython)
def generator(operation):
if operation == 'add':
def f(a, b):
return a + b
else:
def f(a, b):
return a - b
return f
add = generator('add')
sub = generator('sub')
def entry_point(argv):
print add(sub(int(argv[1]), 3) 4)
return 0
在这个例子中,entry_point
是 RPython,add
和 sub
是 RPython,但是,generator
不是。
以下提供了入门级文章
- Laurence Tratt – 足够快的虚拟机在足够快的时间内。
- 如何在 RPython 中编写解释器
- RPython 例子
试用翻译器¶
翻译器是基于 PyPy 解释器的一个工具,它可以将足够静态的 RPython 程序翻译成低级代码(特别是它可以用来翻译 完整的 Python 解释器)。为了能够进行实验,您需要下载并安装通常的(CPython2)版本的
要启动交互式翻译器 shell,请执行
cd rpython
python2 bin/translatorshell.py
可翻译代码的测试片段位于文件 rpython/translator/test/snippet.py 中,它以 snippet
的名称导入。例如
>>> t = Translation(snippet.is_perfect_number, [int])
>>> t.view()
之后,图形查看器会弹出,允许您交互式地检查流程图。要移动,请点击要检查的内容。要获取有关如何使用它的帮助,请按“H”。要再次关闭它,请按“Q”。
试用类型标注器¶
我们有一个类型标注器,它可以完全推断出像 is_perfect_number
这样的函数的类型(以及更大规模的例子)
>>> t.annotate()
>>> t.view()
将鼠标悬停在变量名(红色)上以查看其推断出的类型。
将流程图转换为 C 代码¶
该图可以转换为 C 代码
>>> t.rtype()
>>> lib = t.compile_c()
第一个命令用其他低级版本替换操作,这些版本仅使用 C 中可用的低级类型(例如 int)。编译后的版本现在位于 .so
库中。您可以使用 ctypes 运行它,例如
>>> f = get_c_function(lib, snippet.is_perfect_number)
>>> f(5)
0
>>> f(6)
1
一个稍微大一点的例子¶
有一个中小型演示展示了翻译器和标注器
python2 bin/rpython --view --annotate translator/goal/bpnn.py
这会导致 bpnn.py
将自身显示为调用图和类层次结构。点击函数会显示该特定函数的流程图。点击类会显示其实例的属性。所有这些信息(调用图、局部变量的类型、实例的属性)都是由标注器计算的。
要将此示例转换为 C 代码(编译为可执行文件 bpnn-c
),只需键入
python2 bin/rpython translator/goal/bpnn.py
翻译完整程序¶
要翻译完整的 RPython 程序,可以使用脚本 rpython/bin/rpython
。这方面的例子是 Pystone 的一个稍微修改过的版本
python2 bin/rpython translator/goal/targetrpystonedalone
这将生成可执行文件“targetrpystonedalone-c”。
此过程的最大示例是翻译 完整的 Python 解释器。还有一些关于如何为 您自己的解释器 设置此过程的常见问题解答。
在使用 RPython 时,您可以发现一些环境变量很有用
PYPY_USESSION_DIR
- RPython 使用临时会话目录来存储在翻译过程中生成的各种文件(例如,翻译后的 C 文件)。
PYPY_USESSION_DIR
充当这些会话目录的基本目录。此变量的默认值为系统的临时目录。 PYPY_USESSION_KEEP
- 默认情况下,RPython 只保留
PYPY_USESSION_DIR
内的最后PYPY_USESSION_KEEP
(默认为 3)个会话目录。如果您希望保留 C 文件更长时间(在生成大量 lldebug 构建时很有用),请增加此值。
源代码¶
- rpython/translator 包含代码分析和生成部分。从 translator.py 开始阅读,从中应该很容易理解参与各种翻译阶段的代码片段。
- rpython/annotator 包含可以推断出图的类型标注的数据模型。使用此模型的图“遍历器”位于 rpython/annotator/annrpython.py 中。
- rpython/rtyper 包含 RPython 类型检查器的代码。类型检查器以某种方式转换已标注的流程图,使其非常类似于 C 代码,以便于翻译。图转换由 rpython/rtyper/rtyper.py 中的代码控制。使用的对象模型可以在 rpython/rtyper/lltypesystem/lltype.py 中找到。对于每个 RPython 类型,都有一个 rxxxx.py 文件,其中包含此类型所需的低级函数。
- rpython/rlib 包含 RPython 标准库,您可以从 rpython 中使用这些库。