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)

타입맵(typemap)은 같은 변환이 여러 곳에서 필요한 대규모 API에서 매우 유용합니다. XXX 예제