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으로 작성된 메타클래스를 지원합니다. 예시로는 건너뛴(skipped) 테스트인 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 예제