Y에서 Z에 X 컴파일러를 작성하기위한 일반 규칙


9

X가 입력 언어이고 Z가 출력 언어이고 f가 언어 Y로 작성된 컴파일러라고 가정합니다.

f = X -> Z

f는 프로그램 일 뿐이므로 Y는 어떤 언어라도 될 수 있다고 생각합니까? 그래서 우리는 각각 Y1, Y2로 작성된 컴파일러 f1, f2를 가질 수 있습니다.

f1 = f Y1    
f2 = f Y2

g = Z -> M
h = g . f    # We get a compiler X -> M

예를 들어, X는 Python, Z는 Python VM 코드, Y는 C입니다.

cpython = Python -> PythonVMCode C
interpreter = PythonVMCode -> Nothing
interpreter2 = PythonVMCode -> MachineCode

Python 소스는 Python VM 코드 인 .pyc 파일로 컴파일 된 다음 인터프리터에 의해 해석됩니다. 구현하기가 어렵지만 Python-> MachineCode를 직접 수행 할 수있는 컴파일러가있을 수있는 것처럼 보입니다.

   hardpython = interpreter2 . cpython 

또 다른 컴파일러로 파이썬-> PythonVMCode 작업을 수행 할 수도 있습니다.

mypython = Python -> PythonVMCode Python
mypython2 = Python -> PythonVMCode Ruby

자, 여기 PyPy의 복잡한 예가 있습니다. 나는 PyPy의 초보자 일뿐입니다. 틀린 경우 수정하십시오.

파이 파이 문서 http://doc.pypy.org/en/latest/architecture.html#pypy-the-translation-framework

우리의 목표는 언어 구현 자들의 문제에 대한 가능한 해결책을 제공하는 것입니다.

l은 X, p는 Y라고 생각할 수 있습니다. 모든 RPython 프로그램을 C로 변환하는 프로그램이 있습니다.

 rpython_compiler = RPython -> C  Python

 pypy = Python -> Nothing RPython

 translate = compile the program pypy written in RPython using rpython_compiler

 py2rpy = Python -> RPython  Python
 py2c = Python -> C Python 
 py2c = rpython_compiler . py2rpy

RPython 프로그램은 VM 명령어와 비슷하며 rpython_compiler는 VM입니다.

q1. pypy는 파이썬 코드를 해석 할 수있는 RPython 프로그램 인 인터프리터입니다. 출력 언어가 없으므로 컴파일러로 간주 할 수 없습니다.

추가 :

  • 번역 후에도 pypy는 여전히 통역사이며 이번에는 C로 작성되었습니다.
  • 인터프리터 pypy를 자세히 살펴보면 일종의 컴파일러가 있어야한다고 생각합니다. 파이썬 소스를 AST로 컴파일 한 다음 실행하십시오.

이처럼 :

compiler_inside_pypy = Python -> AST_or_so

q2. 컴파일러 py2rpy가 존재하여 모든 Python 프로그램을 RPython으로 변환 할 수 있습니까? 작성된 언어는 관련이 없습니다. 그렇다면 다른 컴파일러 py2c를 얻습니다. pypy와 py2rpy의 차이점은 무엇입니까? py2rpy는 pypy보다 쓰기가 훨씬 어렵습니까?

q3. 이것에 관한 일반적인 규칙이나 이론이 있습니까?

더 많은 컴파일러 :

gcc_c = C -> asm? C  # not sure, gimple or rtl?
g++ =   C++ -> asm? C
clang = C -> LLVM_IR  C++
jython = Python -> JVMCode java
ironpython = Python -> CLI C#

q4. X로 작성된 프로그램 P 인 f = X-> Z가 주어집니다. P의 속도를 높이려면 어떻게해야합니까? 가능한 방법 :

  • 보다 효율적인 알고리즘으로 P를 다시 작성

  • 더 나은 Z를 생성하려면 f를 다시 작성

  • Z가 해석되면 더 나은 Z 해석기를 작성하십시오 (PyPy가 여기 있습니까?)

  • Z로 재귀 적으로 작성된 프로그램 속도 향상

  • 더 나은 기계를 얻다

추신. 이 질문은 컴파일러를 작성하는 방법에 대한 기술적 내용이 아니라 특정 종류의 컴파일러를 작성하는 타당성과 복잡성에 관한 것입니다.


직접적으로 관련이 없지만 다소 유사한 개념 : en.wikipedia.org/wiki/Supercompilation
SK-logic

1
특히이 질문에 너무 많은 하위 질문이 있기 때문에이 질문이 실제로 스택 오버플로에 맞는지 확실하지 않지만 여전히이 생각에 감탄합니다.

4
배운 내용에도 불구하고 AST는 필요하지 않습니다. 이는 단순히 일부 컴파일러가 사용하는 전략입니다.

1
아마도 이것은 cstheory.stackexchange.com
9000

3
대부분의 "통역사"와 마찬가지로 PyPy의 Python 구현은 실제로 바이트 코드 컴파일러이자 해당 바이트 코드 형식의 해석기입니다.

답변:


4

q1. pypy는 파이썬 코드를 해석 할 수있는 RPython 프로그램 인 인터프리터입니다. 출력 언어가 없으므로 컴파일러로 간주 할 수 없습니다.

PyPy는 CPython과 유사하며 둘 다 컴파일러 + 인터프리터를 가지고 있습니다. CPython에는 Python을 Python VM으로 바이트 코드로 컴파일하는 컴파일러가 C로 작성되고, C로 작성된 인터프리터에서 바이트 코드를 실행하는 PyPy가 있습니다. PyPy에는 Python을 Python VM으로 바이트 코드를 컴파일하는 RPython으로 작성된 컴파일러가 있습니다.

q2. 컴파일러 py2rpy가 존재할 수 있습니까? 작성된 언어는 관련이 없습니다. 그렇다면 다른 컴파일러 py2c를 얻습니다. pypy와 py2rpy의 차이점은 무엇입니까? py2rpy는 pypy보다 쓰기가 훨씬 어렵습니까?

컴파일러 py2rpy가 존재할 수 있습니까? 이론적으로 그렇습니다. 튜링 완성도를 보장합니다.

구성하는 한 가지 방법 py2rpy은 생성 된 소스 코드에 RPython으로 작성된 Python 인터프리터의 소스 코드를 간단히 포함시키는 것입니다. Bash로 작성된 py2rpy 컴파일러의 예 :

// suppose that /pypy/source/ contains the source code for pypy (i.e. Python -> Nothing RPython)
cp /pypy/source/ /tmp/py2rpy/pypy/

// suppose $inputfile contains an arbitrary Python source code
cp $inputfile /tmp/py2rpy/prog.py

// generate the main.rpy
echo "import pypy; pypy.execfile('prog.py')" > /tmp/py2rpy/main.rpy

cp /tmp/py2rpy/ $outputdir

이제 파이썬 코드를 RPython 코드로 변환해야 할 때마다이 스크립트를 호출하여 $ outputdir에서 RPython main.rpy, RPython의 Python 인터프리터 소스 코드 및 이진 Blob prog.py를 생성합니다. 그런 다음을 호출하여 생성 된 RPython 스크립트를 실행할 수 있습니다 rpython main.rpy.

(참고 : rpython 프로젝트, rpython 인터프리터 호출 구문, pypy를 가져오고 pypy.execfile을 수행하는 기능 및 .rpy 확장자는 순전히 구성되어 있지만 잘 이해하고 있다고 생각합니다)

q3. 이것에 관한 일반적인 규칙이나 이론이 있습니까?

예, 모든 Turing Complete 언어는 이론적으로 모든 Turing Complete 언어로 번역 될 수 있습니다. 일부 언어는 다른 언어보다 번역하기가 훨씬 어려울 수 있지만 질문이 "가능한가?"라면 대답은 "예"입니다.

q4. ...

여기에 의문의 여지가 없습니다.


py2rpy 컴파일러는 정말 영리합니다. 그것은 또 다른 아이디어로 연결됩니다. 1. 파이썬에서 pypy를 RPython으로 작성해야합니까? 파이썬 파일을 해석 할 수있는 것만 있으면됩니다. 2. os.system ( 'python $ inputfile')도 RPython에서 지원되는 경우 작동 할 수 있습니다. 적어도 문자 그대로 컴파일러라고 할 수 있는지 확실하지 않습니다.

pypy가 여전히 Python VM을 사용하고 있습니까? 지금은 분명하다. pypy_the_compiler = Python-> PythonVMCode RPython, pypy_the_interpreter = PythonVMCode-> Nothing RPython, cpython_the_compiler = Python-> PythonVMCode C, cpython_the_interpreter = PythonVMCode-> Nothing C

@jaimechen : Does pypy have to be written in RPython in your compiler?아니요. RPython으로 작성 될 필요는 없지만 RPython은 "보조 해석기"/ "런타임"에 Python 코드를 실행하도록 지시 할 수 있어야합니다. 그렇습니다. 이것이 실제 의미에서 "컴파일러"가 아니라는 것은 사실이지만, 쓸 수 있다는 건설적인 증거입니다 Python -> RPython. Is pypy still using the Python VM?pypy는 CPython을 전혀 사용하지 않는다고 생각합니다 (잘못 될 수도 있습니다). 대신 PyPy에는 python으로 작성된 "Python VM"자체 구현이 있습니다.
거짓말 라이언

@jaimechen : 좀 더 실용적인 컴파일러는 코드 파일에 대한 입력 파일을 분석하여이를 개별적으로 컴파일하고 컴파일하는 방법을 알고 있으며 "재 컴파일 -to- 파이썬"파이썬과 "인터프리터- 돕다 "파이썬. 또한 JIT 컴파일에 일반적으로 사용되는 기술을 사용하여 RPython과 Python의 시맨틱의 차이로 인해 특정 입력이 다른 출력을 생성하는지 여부를 감지하고 이러한 경우 해석으로 대체 될 수 있습니다. 모든 것은보다 실용적인 Python -> RPython컴파일러 에서 볼 수있는 정교함입니다 .
거짓말 라이언

여기에 제약 조건을 추가해야 할 수도 있습니다. 기존의 세 번째 컴퓨터를 사용하지 않고 상태 머신 X를 상태 머신 Z로 변환합니다. 이것은 X가 완전히 새로운 경우이고 지금까지 컴파일러 나 인터프리터가 존재하지 않는 경우입니다.
jaimechen

2

q2에만 답하기 위해 William McKeeman의 컴파일러 책이 있습니다. 여기에는 언어 Y로 작성된 언어 X의 컴파일러 이론이 출력 언어 Z를 생성하는 T- 다이어그램 시스템을 통해 탐구됩니다. 1970 년대에 출판, 제목을 손에하지, 죄송합니다.



1

q1. 일반적으로 인터프리터는 컴파일러가 아닙니다. 컴파일러와 인터프리터의 주요 차이점은 인터프리터가 매번 소스 언어의 소스 코드로 새로 시작한다는 것입니다. pypy가 대신 pyAST 또는 pyP 코드이고 AST 또는 P 코드 인터프리터가있는 경우 pyAST를 컴파일러로 호출 할 수 있습니다. 이것은 이전 UCSD PASCAL 컴파일러가 작동하는 방식입니다 (몇몇 다른 것들도 마찬가지입니다) : P 코드로 컴파일되어 프로그램이 실행될 때 해석되었습니다. (.NET조차도 생성 된 객체 코드의 압축이 속도보다 훨씬 중요 할 때 이와 같은 것을 제공합니다.)

q2. 물론입니다. UCSD PASCAL 및 기타 여러 항목을 참조하십시오.

q3. 컴퓨터 과학의 고전 텍스트를 파헤쳐보십시오. Per Brinch-Hansen의 Concurrent PASCAL을 읽으십시오 (메모리가 나에게 도움이된다면). 컴파일러와 코드 생성에 대해 많은 글이 작성되었습니다. 기계 독립적 의사 코드를 생성하는 것은 일반적으로 기계 코드를 생성하는 것보다 훨씬 쉽습니다. 의사 코드는 일반적으로 실제 기계에 항상 포함되는 단점이 없습니다.

q4. 생성 된 객체를 더 빨리 실행하려면 더 나은 최적화를 위해 컴파일러를 더 똑똑하게 만듭니다. 객체가 해석되면 더 복잡한 연산을 원시 의사 명령어로 내리는 것을 고려하고 (CISC와 RISC는 유사 함) 해석기에서 frack을 최적화하기 위해 최선을 다합니다.

컴파일러를 더 빨리 실행하려면 소스 코드를 다시 생각하는 것을 포함하여 컴파일러가 수행하는 모든 작업을 살펴 ​​봐야합니다. 컴파일러 자체를로드 한 후 컴파일에서 가장 시간이 많이 걸리는 부분은 항상 소스 코드를 컴파일러로 읽는 것입니다. (예를 들어 C ++을 고려하십시오. 다른 모든 것들은 상대적으로 동일합니다. 간단한 "Hello, World"프로그램을 컴파일하기 위해 9,000 개 (또는 50,000 개) 줄의 #include 파일을 축소해야하는 컴파일러는 결코 빠르지 않습니다. 4 ~ 5 줄만 읽어야합니다.)

어디서 읽었는지 기억이 나지 않지만 ETH-Zurich의 원래 Oberon 컴파일러에는 매우 정교한 기호 테이블 메커니즘이 있습니다. 컴파일러 성능에 대한 Wirth의 벤치 마크는 컴파일러 자체 컴파일에 걸리는 시간이었습니다. 어느 날 아침 그는 들어가서 화려한 멀티 링크 울트라 트리 심볼 테이블을 찾아 간단한 선형 배열과 직선 선형 검색으로 대체했습니다. 그의 그룹의 대학원생들은 충격을 받았습니다. 변경 후, 컴파일러는 컴파일하는 모듈이 항상 작기 때문에 우아한 몬스터가 선형 배열 및 선형 검색보다 더 많은 오버 헤드를 부과 할 수있었습니다.


1
감사. 컴파일러는 '컴파일'하고 인터프리터는 '실행'하지만 두 유형의 프로그램에 대해 더 많은 통찰력을 가질 수 있습니까?
jaimechen

1

언급 한 귀하의 질문으로 인해 실제로 원하거나 필요로하는 것은 컴파일러가 무엇인지, 인터프리터가 무엇인지, 그리고 둘 사이의 차이점에 대한 설명이라고 믿게됩니다.

컴파일러 는 언어 X로 작성된 프로그램을 언어 Y로 작성된 기능적으로 동등한 프로그램에 맵핑합니다. 예를 들어, Pascal에서 C 로의 컴파일러는 컴파일 될 수 있습니다.

function Square(i: Integer)
begin
    Square := i * i
end

int Square(int i)
{
    return i * i;
}

대부분의 컴파일러는 '아래로'컴파일되므로 고급 프로그래밍 언어를 하위 언어로 컴파일하며 궁극적으로는 기계 코드 인 하위 레벨 언어입니다.

대부분의 컴파일러는 머신 코드로 직접 컴파일되지만 일부 (특히 Java 및 .NET 언어)는 '바이트 코드'( Java 바이트 코드CIL )로 컴파일됩니다 . 바이트 코드는 가상 컴퓨터의 기계 코드로 생각하십시오. 이 바이트 코드는 실행될 때 해석되거나 JITted (나중에 자세히 설명)입니다.

인터프리터 는 일부 언어 Z로 작성된 프로그램을 실행합니다. 인터프리터는 프로그램을 비트 단위로 읽고 진행하면서 프로그램을 실행합니다. 예를 들어 :

int i = 0;
while (i < 1)
{
    i++
}
return i;

인터프리터가 해당 프로그램 라인을보고 라인을 검사하고 라인을 검사하고 수행하는 것을 실행하고 다음 라인을보고 있다고 상상해보십시오.

통역사의 가장 좋은 예는 컴퓨터의 CPU입니다. 머신 코드를 해석하여 실행합니다. CPU의 작동 방식은 물리적으로 구축 된 방식으로 지정됩니다. 인터프리터 프로그램의 작동 방식은 코드의 모양에 따라 지정됩니다. 따라서 CPU는 인터프리터 프로그램을 해석하고 실행하며,이 프로그램은 입력을 해석하고 실행합니다. 이런 식으로 통역사를 연결할 수 있습니다.

JITter 는 Just-In-Time 컴파일러입니다. JITter는 컴파일러입니다. 유일한 차이점은 실행 시간입니다. 대부분의 프로그램은 작성, 컴파일, 사용자에게 제공된 후 실행되지만 Java 바이트 코드 및 CIL은 먼저 사용자에게 제공되며 실행 직전에 시스템에 컴파일됩니다. 사용자 코드.

C #-> (컴파일)-> CIL-> 고객에게 배송-> (실행 직전에 컴파일)-> 머신 코드-> (실행)

마지막으로 알아야 할 것은 Turing completeness ( link )입니다. 프로그래밍 언어는 ' 튜링 머신 '이 할 수 있는 모든 것을 계산할 수 있다면 , 즉 튜링 머신 만큼 '강력한' 언어 일 경우 완성됩니다 . 교회 튜링의 논문 튜링 기계는 적어도 우리가 이제까지 구축 할 수있는 시스템과 강력한 같은 것을 상태. 모든 튜링 완성 언어는 튜링 머신만큼 강력하고 모든 튜링 완성 언어는 똑같이 강력합니다.

다시 말해, 프로그래밍 언어가 Turing complete (거의 거의 전부 임) 인 한, 모두 같은 것을 계산할 수 있기 때문에 어떤 언어를 선택하든 상관 없습니다. 이것은 또한 컴파일러 나 인터프리터를 작성하기 위해 어떤 프로그래밍 언어를 선택하든 관련이 없다는 것을 의미합니다. 마지막으로, X와 Y가 모두 Turing을 완료하면 항상 언어 X에서 Y로 컴파일러를 작성할 수 있습니다.

Turing complete는 언어가 효율적인지, CPU 및 기타 하드웨어의 모든 구현 세부 사항 또는 언어에 사용하는 컴파일러의 품질에 대해 말하지 않습니다. 또한 운영 체제는 프로그램에 파일을 열 수있는 권한이 없지만 어떤 계산 능력도 방해 하지 않는다고 결정할 수 있습니다. 심지어 컴퓨팅을 정의하지 않은 것은 다른 텍스트를 필요로하기 때문입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.