RPython 시작하기 ================ .. contents:: .. warning:: 먼저 `이 FAQ 항목을 읽어보십시오 `_\ ! .. _`read this FAQ entry`: http://rpython.readthedocs.org/en/latest/faq.html#do-i-have-to-rewrite-my-programs-in-rpython RPython은 정적으로 컴파일할 수 있는 Python2의 부분집합입니다. PyPy 인터프리터는 대부분 RPython으로 작성되어 있으며(일부는 Python으로 작성됨), RPython 컴파일러는 Python으로 작성되어 있습니다. 이해하기 어려운 부분은 Python이 RPython을 위한 메타프로그래밍 언어라는 점입니다. 즉, "유효한 RPython인지"는 임포트가 완료된 **이후**\ 의 실제 객체에 대해서만 의미가 있는 질문입니다. 이 부분은 좀 더 설명이 필요할 수 있습니다. ``entry_point``\ 부터 RPython 작성을 시작하며, 좋은 시작점은 :source:`rpython/translator/goal/targetnopstandalone.py`\ 입니다. 이것이 대단한 일을 하지는 않지만, 시작점은 됩니다. 이제 분석 대상 코드(이 경우 ``entry_point``)가 어떤 함수들을 호출하면, 그 호출들은 추적됩니다. 그렇게 추적된 호출들은 그 자체로 RPython이어야 하지만(그리고 그것들이 호출하는 모든 것 등도 마찬가지), 모듈 파일 전체가 그럴 필요는 없습니다. 메타프로그래밍을 어떻게 사용할 수 있는지 보여주기 위해, 간단한 예제를 하나 살펴보겠습니다(클로저는 RPython이 아니라는 점에 유의하십시오).:: def generator(operation): if operation == 'add': def f(a, b): return a + b else: def f(a, b): return a - b return f add = generator('add') sub = generator('sub') def entry_point(argv): print add(sub(int(argv[1]), 3) 4) return 0 이 예시에서 ``entry_point``\ 는 RPython이고, ``add``\ 와 ``sub``\ 도 RPython이지만, ``generator``\ 는 그렇지 않습니다. 다음과 같은 입문 수준의 문서를 이용할 수 있습니다: * Laurence Tratt -- `Fast Enough VMs in Fast Enough Time`_. * `How to write interpreters in RPython`_ * `RPython By Example`_ .. _Fast Enough VMs in Fast Enough Time: http://tratt.net/laurie/tech_articles/articles/fast_enough_vms_in_fast_enough_time .. _How to write interpreters in RPython: https://www.pypy.org/posts/2011/04/tutorial-writing-interpreter-with-pypy-3785910476193156295.html .. _RPython By Example: https://mssun.github.io/rpython-by-example/ .. _try-out-the-translator: 번역기(translator) 사용해 보기 ------------------------------ 번역기(translator)는 PyPy 인터프리터를 기반으로 한 도구로서, 충분히 정적인 RPython 프로그램을 저수준 코드로 번역(translation)할 수 있습니다(특히 `full Python interpreter`_\ 를 번역하는 데 사용할 수 있습니다). 이를 실험해 보려면 다음의 일반적인 (CPython2) 버전을 다운로드하여 설치해야 합니다: * Pygame_ * `Dot Graphviz`_ .. _Pygame: http://www.pygame.org/ .. _Dot Graphviz: http://www.graphviz.org/ 대화형 번역기(translator) 셸을 시작하려면 다음을 수행하십시오:: cd rpython python2 bin/translatorshell.py 번역 가능한 코드의 테스트 스니펫은 :source:`rpython/translator/test/snippet.py` 파일에 제공되며, 이 파일은 ``snippet``\ 이라는 이름으로 임포트됩니다. 예를 들어:: >>> t = Translation(snippet.is_perfect_number, [int]) >>> t.view() 그 후에, 그래프 뷰어가 나타나며, 흐름 그래프를 대화식으로 살펴볼 수 있게 해줍니다. 이동하려면, 살펴보고 싶은 대상을 클릭하십시오. 사용법에 대한 도움말을 보려면, 'H'를 누르십시오. 다시 닫으려면, 'Q'를 누르십시오. 타입 애노테이터 사용해보기 ~~~~~~~~~~~~~~~~~~~~~~~~~~ 저희는 ``is_perfect_number``\ 와 같은 함수(및 훨씬 더 큰 예제)에 대한 타입을 완전히 추론할 수 있는 타입 애노테이터를 보유하고 있습니다:: >>> t.annotate() >>> t.view() 변수 이름(빨간색으로 표시됨) 위에 마우스를 올리면 추론된 타입을 확인할 수 있습니다. 흐름 그래프를 C 코드로 번역(translation)하기 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 그래프는 C 코드로 변환될 수 있습니다:: >>> t.rtype() >>> lib = t.compile_c() 첫 번째 명령은 연산을 C에서 사용 가능한 저수준 타입(예: int)만을 사용하는 다른 저수준 버전으로 대체합니다. 컴파일된 버전은 이제 ``.so`` 라이브러리에 있습니다. 예를 들어 ctypes를 사용하여 실행할 수 있습니다: >>> f = get_c_function(lib, snippet.is_perfect_number) >>> f(5) 0 >>> f(6) 1 조금 더 큰 예제 ~~~~~~~~~~~~~~~ 번역기(translator)와 어노테이터(annotator)를 보여주는 중소 규모의 데모가 있습니다.:: python2 bin/rpython --view --annotate translator/goal/bpnn.py 이것은 ``bpnn.py``\ 가 자신을 호출 그래프와 클래스 계층 구조로 표시하게 만듭니다. 함수를 클릭하면 해당 함수의 흐름 그래프가 표시됩니다. 클래스를 클릭하면 해당 클래스 인스턴스의 속성이 표시됩니다. 이 모든 정보(호출 그래프, 지역 변수의 타입, 인스턴스의 속성)는 애노테이터가 계산합니다. 이 예제를 C 코드(``bpnn-c``\ 라는 실행 파일로 컴파일됨)로 변환하려면, 다음과 같이 입력하면 됩니다.:: python2 bin/rpython translator/goal/bpnn.py 전체 프로그램 번역(translation)하기 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 완전한 RPython 프로그램을 번역(translation)하기 위한 ``rpython/bin/rpython`` 스크립트가 있습니다. 이에 대한 예시로는 약간 수정된 버전의 Pystone이 있습니다.:: python2 bin/rpython translator/goal/targetrpystonedalone 이렇게 하면 실행 파일 "targetrpystonedalone-c"가 생성\ 됩니다. 이 과정의 가장 큰 예는 `full Python interpreter`_\ 를 번역(translation)하는 것입니다. 또한 :ref:`직접 만든 인터프리터 `\ 를 위해 이 과정을 설정하는 방법에 대한 FAQ도 있습니다. RPython을 다루면서 유용하게 쓸 수 있는 몇 가지 환경 변수가 있습니다: ``PYPY_USESSION_DIR`` RPython은 번역(translation) 과정에서 생성되는 파일(예: 번역된 C 파일)을 저장하기 위해 임시 세션 디렉터리를 사용합니다. ``PYPY_USESSION_DIR``\ 은 이러한 세션 디렉터리의 기본 디렉터리 역할을 합니다. 이 변수의 기본값은 시스템의 임시 디렉터리입니다. ``PYPY_USESSION_KEEP`` RPython은 기본적으로 ``PYPY_USESSION_DIR`` 내부의 세션 디렉터리 중 최근 ``PYPY_USESSION_KEEP``\ 개(기본값 3)만 유지합니다. C 파일을 더 오래 보존하려면 이 값을 늘리십시오(lldebug 빌드를 많이 생성할 때 유용합니다). 출처 ---- * :source:`rpython/translator`\ 는 코드 분석과 생성 관련 내용을 담고 있습니다. translator.py부터 읽기 시작하면, 다양한 번역(translation) 단계에 관련된 코드 조각들을 쉽게 따라갈 수 있을 것입니다. * :source:`rpython/annotator`\ 는 그래프에 대해 추론할 수 있는 타입 어노테이션의 데이터 모델을 담고 있습니다. 이를 사용하는 그래프 "워커(walker)"는 :source:`rpython/annotator/annrpython.py`\ 에 있습니다. * :source:`rpython/rtyper`\ 는 RPython 타이퍼(typer)의 코드를 포함합니다. 타이퍼(typer)는 주석이 달린 흐름 그래프(flow graph)를 C 코드와 매우 비슷하게 만드는 방식으로 변환하여, 쉽게 번역될 수 있도록 합니다. 그래프 변환은 :source:`rpython/rtyper/rtyper.py`\ 의 코드에 의해 제어됩니다. 사용되는 객체 모델은 :source:`rpython/rtyper/lltypesystem/lltype.py`\ 에서 찾을 수 있습니다. 각 RPython 타입마다 해당 타입에 필요한 저수준 함수를 포함하는 rxxxx.py 파일이 있습니다. * :source:`rpython/rlib`\ 은 rpython에서 사용할 수 있는 것들인 :doc:`RPython 표준 라이브러리 `\ 를 포함합니다. .. _full Python interpreter: http://pypy.readthedocs.org/en/latest/getting-started-python.html