rpython 语言的潜在改进¶
改进解释器 API¶
使实现 pypy 模块所需的各种函数的模块和名称合理化。一个典型的 rpython 文件可能包含许多 import 语句
from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter.gateway import ObjSpace, W_Root from pypy.interpreter.argument import Arguments from pypy.interpreter.typedef import TypeDef, GetSetProperty from pypy.interpreter.typedef import interp_attrproperty, interp_attrproperty_w from pypy.interpreter.gateway import interp2app from pypy.interpreter.error import OperationError from rpython.rtyper.lltypesystem import rffi, lltype
一种更直接的声明式方法来编写 Typedef
class W_Socket(W_Root): _typedef_name_ = 'socket' _typedef_base_ = W_EventualBaseClass @interp2app_method("connect", ['self', ObjSpace, W_Root]) def connect_w(self, space, w_addr): ...
支持用 rpython 编写的元类。例如,请参见跳过的测试 pypy.objspace.std.test.TestTypeObject.test_metaclass_typedef
RPython 语言¶
- 使用无符号整数进行算术运算,以及在不同符号的整数之间进行算术运算,只要不产生歧义。至少,应该允许与常量的比较和赋值。
- 在堆栈上分配变量,并将它们的地址(“按引用”)传递给 llexternal 函数。有关典型用法,请参见 rpython.rlib.rsocket.RSocket.getsockopt_int。
llexternal 的可扩展类型系统¶
llexternal 允许描述 C 函数,并传递与 C 头文件相同的关于参数的信息。但这通常不够。例如,类型为 int* 的参数将转换为 rffi.CArrayPtr(rffi.INT),但此信息不足以使用该函数。该参数可以是 int 数组,也可以是对单个值的引用,用于输入或输出…
一个“类型系统”可以保存此附加信息,并自动生成一些转换代码以简化从 rpython 使用该函数。例如
# double frexp(double x, int *exp);
frexp = llexternal("frexp", [rffi.DOUBLE, OutPtr(rffi.int)], rffi.DOUBLE)
OutPtr 指示该参数是只输出的,不需要初始化,并且其值将返回给调用者。在 rpython 中,调用变为
fraction, exponent = frexp(value)
此外,我们可以想象 llexternal 参数列表中的一个项目对应于 C 中的两个参数。在这里,OutCharBufferN 指示调用者将传递一个 rpython 字符串;框架将缓冲区和长度传递给函数
# ssize_t write(int fd, const void *buf, size_t count);
write = llexternal("write", [rffi.INT, CharBufferAndSize], rffi.SSIZE_T)
调用此函数的 rpython 代码非常简单
written = write(fd, data)
与现在的代码相比
count = len(data)
buf = rffi.get_nonmovingbuffer(data)
try:
written = rffi.cast(lltype.Signed, os_write(
rffi.cast(rffi.INT, fd),
buf, rffi.cast(rffi.SIZE_T, count)))
finally:
rffi.free_nonmovingbuffer(data, buf)
类型映射对于需要在许多地方进行相同转换的大型 API 非常有用。XXX 示例