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 示例