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,addsub 是 RPython,但是,generator 不是。

以下提供了入门级文章

试用翻译器

翻译器是基于 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 构建时很有用),请增加此值。

源代码