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 예제