원래 통역사와 독립적으로 "부트 스트랩"통역사를 만들 수 있습니까?


21

Wikipedia 에 따르면 컴파일러 작성과 관련하여 "부트 스트래핑"이라는 용어는 다음을 의미합니다 .

컴퓨터 과학에서 부트 스트랩은 컴파일하려는 소스 프로그래밍 언어로 컴파일러 (또는 어셈블러)를 작성하는 프로세스입니다. 이 기술을 적용하면 자체 호스팅 컴파일러가 생성됩니다.

그리고 그것이 어떻게 작동하는지 이해할 수 있습니다. 그러나 그 이야기는 통역사들에게는 약간 다르게 보입니다. 물론, 자체 호스팅 인터프리터를 작성할 수 있습니다. 그것은 내가 요구하는 것이 아닙니다. 내가 실제로 부탁 해요 것은 : 원래, 제 1 통역자의 자체 호스팅 통역 독립을 만드는 것이 가능하다 . 내가 의미하는 바를 설명하려면 다음 예를 고려하십시오.

언어 X 로 첫 번째 인터프리터 버전을 작성 하면 인터프리터는 작성중인 새 언어 인 Y 입니다. 먼저 언어 X 컴파일러를 사용하여 실행 파일을 만듭니다. 이제 언어 X로 작성된 인터프리터를 사용 하여 새 언어 Y 로 작성된 파일을 해석 할 수 있습니다 .

이제 내가 이해하는 한, 언어 X로 작성한 인터프리터를 "부트 스트랩"하려면 언어 Y로 인터프리터를 다시 작성해야합니다 . 그러나 여기에는 문제가 있습니다. 통역사 전체를 언어 Y 로 다시 작성하더라도 언어 X로 작성한 원래 통역사가 여전히 필요합니다 . 언어 Y로 인터프리터를 실행 하려면 소스 파일을 해석해야합니다. 그러나 소스 파일을 정확히 해석 할 것은 무엇입니까? 글쎄, 물론 아무것도 될 수 없으므로 여전히 첫 번째 통역사를 사용해야합니다.

언어 Y로 쓰는 새로운 통역사 수에 관계없이 항상 후속 통역사를 해석하려면 X 로 작성된 첫 번째 통역사를 사용해야합니다 . 이것은 단순히 통역사의 특성으로 인해 문제가되는 것 같습니다.

그러나 반대로, 이 위키 백과의 통역사 기사는 실제로 자체 호스팅 통역사에 대해 이야기 합니다. 다음은 관련있는 작은 발췌문입니다.

자체 통역사는 자신을 해석 할 수있는 프로그래밍 언어로 작성된 프로그래밍 언어 해석기입니다. 예를 들어 BASIC으로 작성된 BASIC 인터프리터가 있습니다. 자체 통역사는 자체 호스팅 컴파일러와 관련이 있습니다.

언어를 해석하기위한 컴파일러가없는 경우, 자기 인터프리터를 작성하려면 호스트 언어 (다른 프로그래밍 언어 또는 어셈블러 일 수 있음)로 언어를 구현해야합니다. 이와 같은 첫 번째 통역사가 있으면 시스템이 부트 스트랩되고 새로운 버전의 통역사가 언어 자체로 개발 될 수 있습니다

그래도 이것이 정확히 어떻게 수행되는지는 분명하지 않습니다. 어쨌든 항상 호스트 언어로 작성된 첫 번째 버전의 통역사를 사용해야 할 것 같습니다.

이제 위에서 언급 한 기사는 위키 백과에서 자체 호스팅 인터프리터에 대한 예제를 제공하는 다른 기사로 연결됩니다 . 그러나 자세히 살펴보면 자체 호스팅 인터프리터 (특히 PyPy 또는 Rubinius와 같은 더 일반적인 인터프리터 중 일부)의 주요 "해석"부분은 실제로 C ++ 또는 C와 같은 다른 언어로 작성된 것 같습니다.

그래서 내가 위에서 설명한 것이 가능합니까? 자체 호스팅 통역사가 원래 호스트와 독립적 일 수 있습니까? 그렇다면 정확히 어떻게 수행됩니까?

답변:


24

짧은 대답은 : 당신이 당신의 의심에 맞아, 당신은 항상 X로 작성된 다른 통역사 또는 Y 에서 컴파일러가 이미 통역사가있는 다른 언어로 컴파일러 가 필요합니다. 통역사는 실행되고, 컴파일러는 한 언어에서 다른 언어로만 번역 합니다. 시스템의 어느 시점에서는 통역사 가 있어야합니다 . 심지어 CPU 일뿐입니다.

언어 Y로 쓰는 새로운 통역사 수에 관계없이 항상 후속 통역사를 해석하려면 X 로 작성된 첫 번째 통역사를 사용해야합니다 . 이것은 단순히 통역사의 특성으로 인해 문제가되는 것 같습니다.

옳은. 당신이 할 수있는 일은 Y 에서 X (또는 인터프리터가있는 다른 언어) 에서 컴파일러를 작성하는 것이고, 심지어 Y로도 할 수 있습니다 . 그런 다음 당신은 당신의 실행 Y의 작성 컴파일러 YY 로 작성 통역 X (또는에 Y 로 작성 통역 Y 상의 실행 Y 로 작성 통역 X , 또는에서 Y의 작성 통역 Y 상의 실행 Y 로 작성 통역 Y는 온 실행 Y작성 통역 X , 또는 ... 무한히는) 당신의 컴파일 Y의 작성 통역 YX를 사용하면 다음에 그것을 실행할 수 그래서, X의 통역. 그런 식으로, 당신은 당신의 제거 입수했습니다 Y의 작성 통역 X ,하지만 지금은 당신이 필요 X의 (그렇지 않으면 우리는 실행 수 없기 때문에 우리는하지만, 우리는 이미 하나를 가지고 것을 알고 통역 X의 작성 통역 Y을 ), 그리고 당신 Y -to- X 컴파일러를 먼저 작성해야했습니다 .

그러나 반대로 통역사에 관한 Wikipedia 기사는 실제로 자체 호스팅 통역사에 대해 이야기합니다. 다음은 관련있는 작은 발췌문입니다.

자체 통역사는 자신을 해석 할 수있는 프로그래밍 언어로 작성된 프로그래밍 언어 해석기입니다. 예를 들어 BASIC으로 작성된 BASIC 인터프리터가 있습니다. 자체 통역사는 자체 호스팅 컴파일러와 관련이 있습니다.

언어를 해석하기위한 컴파일러가없는 경우, 자기 인터프리터를 작성하려면 호스트 언어 (다른 프로그래밍 언어 또는 어셈블러 일 수 있음)로 언어를 구현해야합니다. 이와 같은 첫 번째 통역사가 있으면 시스템이 부트 스트랩되고 새로운 버전의 통역사가 언어 자체로 개발 될 수 있습니다

그래도 이것이 정확히 어떻게 수행되는지는 분명하지 않습니다. 어쨌든 항상 호스트 언어로 작성된 첫 번째 버전의 통역사를 사용해야 할 것 같습니다.

옳은. Wikipedia 기사는 명시 적으로 언어 의 두 번째 구현 이 필요하며 첫 번째 언어를 제거 할 수는 없다고 명시하고 있습니다.

이제 위에서 언급 한 기사는 위키 백과에서 자체 호스팅 인터프리터에 대한 예제를 제공하는 다른 기사로 연결됩니다. 그러나 자세히 살펴보면 자체 호스팅 인터프리터 (특히 PyPy 또는 Rubinius와 같은 더 일반적인 인터프리터 중 일부)의 주요 "해석"부분은 실제로 C ++ 또는 C와 같은 다른 언어로 작성된 것 같습니다.

다시, 수정하십시오. 이것들은 정말 나쁜 예입니다. 예를 들어 Rubinius를 생각해보십시오. 그렇습니다. Rubinius의 Ruby 부분은 자체 호스팅되지만 인터프리터가 아닌 컴파일러입니다. Ruby 소스 코드를 Rubinius 바이트 코드로 컴파일합니다. 인터프리터 부분 OTOH는 자체 호스팅되지 않습니다 : Rubinius 바이트 코드를 해석하지만 C ++로 작성되었습니다. 그래서는 "자체 호스팅 통역"Rubinius를 호출하면 잘못 다음 자체 호스팅 부분은 아니다 통역통역 부분이 아닌 자체 호스팅 .

PyPy는 비슷하지만 훨씬 더 잘못되었습니다. 처음에는 Python으로 작성되지 않았으며 다른 언어 인 RPython으로 작성되었습니다. 문법적으로 파이썬과 유사하지만 의미 적으로 "확장 된 부분 집합"이지만 실제로는 Java와 거의 동일한 추상화 수준에서 정적으로 유형이 지정된 언어이며, 구현은 RPython을 C 소스 코드, ECMAScript로 컴파일하는 여러 백엔드가있는 컴파일러입니다. 소스 코드, CIL 바이트 코드, JVM 바이트 코드 또는 Python 소스 코드

그래서 내가 위에서 설명한 것이 가능합니까? 자체 호스트 인터프리터가 원래 호스트와 독립적 일 수 있습니까? 그렇다면 정확히 어떻게 수행됩니까?

아닙니다. 원래 인터프리터를 유지하거나 컴파일러를 작성하고 자기 인터프리터를 컴파일해야합니다.

있는 일부 메타 원형과 같은 VM을, 클라인 (작성 자체 )과 맥신 (Java로 작성된이). 그러나 여기서 "meta-circular"의 정의는 아직 다릅니다. 이러한 VM은 실행하는 언어로 작성 되지 않습니다 . Klein은 Self bytecode를 실행하지만 Self로 작성되고 Maxine은 JVM 바이트 코드를 실행하지만 Java로 작성됩니다. 그러나, VM의 자기 / Java 소스 코드가 실제로 셀프 / JVM 바이트 코드로 컴파일 한 후 VM에 의해 실행, 그래서 시간 VM이 실행됩니다 도착, 그것은 이다 그것을 실행하는 언어. 휴

또한 SqueakVMJikes RVM 과 같은 VM과 다릅니다 . Jikes는 Java로 작성되고 SqueakVM은 Slang (Smalltalk의 정적으로 유형이 지정된 구문 및 의미 하위 집합이 대략 상위 레벨 어셈블러와 동일한 추상화 레벨에서 작성 됨)로 작성되며 둘 다 실행되기 전에 기본 코드로 정적으로 컴파일됩니다. 그들은 내면으로 달려 가지 않습니다. 그러나 스스로 (또는 다른 스몰 토크 VM / JVM 위에서) 실행할 수 있습니다 . 그러나 이것은 이런 의미에서 "메타-원형"이 아닙니다.

맥신과 클라인, OTOH 할 일내면으로 달려라. 그들은 자신의 구현을 사용하여 자신의 바이트 코드를 실행합니다. 이것은 정말로 마음을 굽히는 것입니다! 예를 들어 VM이 사용자 프로그램과 함께 자체적으로 실행되므로 사용자 프로그램에서 VM으로의 호출을 인라인 할 수 있으며 가비지 콜렉터에 대한 호출 또는 메모리 할당자가 사용자에 인라인 될 수 있습니다. 코드 및 사용자 코드의 반사 콜백을 VM에 인라인 할 수 있습니다. 또한 현대 VM이 수행하는 모든 영리한 최적화 트릭은 실행 프로그램을보고 실제 작업 부하 및 데이터에 따라 최적화합니다 .VM은 사용자 프로그램을 실행하는 동안 사용자 프로그램을 실행하는 동안 동일한 트릭을 적용 할 수 있습니다 특정 워크로드를 실행 중입니다. 다시 말해서 VM은 자체로 전문화되어 있습니다.특정 작업을 실행 하는 특정 프로그램 .

그러나 위의 "통역사"라는 단어를 사용하고 항상 "실행"을 사용 했습니까? 이 VM은 인터프리터를 중심으로 구축 된 것이 아니라 JIT 컴파일러를 기반으로 구축 된 것입니다. 나중에 Maxine에 인터프리터가 추가되었지만 항상 컴파일러가 필요합니다. 다른 VM 위에서 VM을 한 번 실행해야합니다 (예 : Maxine의 경우 Oracle HotSpot). Maxine의 경우 자체 부트 업 단계를 JIT 컴파일 한 다음 컴파일 된 기본 코드를 부트 스트랩 VM 이미지에 직렬화하고 매우 간단한 부트 로더를 앞에 배치합니다 (C로 작성된 VM의 유일한 구성 요소는 편의를위한 것이지만) Java로도 가능합니다). 이제 Maxine을 사용하여 자체를 실행할 수 있습니다.


Yeesh . 나는 자체 호스팅 통역사의 세계가 끈적 끈적한 줄 몰랐어요! 멋진 개요를 제공해 주셔서 감사합니다.
Christian Dean

1
하하, 왜 세상은 개념보다 마음이 덜 굽어 야합니까? ;-)
Jörg W Mittag

3
문제 중 하나는 사람들이 종종 관련된 언어로 빠르고 느슨하게 연주한다는 것입니다. 예를 들어, Rubinius는 일반적으로 "Ruby in Ruby"라고하지만 이야기의 절반에 지나지 않습니다. 예, 엄밀하게는 , Rubinius에서 루비 컴파일러는 루비로 작성하지만, 바이트 코드를 실행하는 VM은 아니다. 그리고 더 나쁜 것은 : PyPy는 실제로 "Python in Python"이라고 불리는데, 실제로 파이썬에 한 줄의 파이썬이 없다는 것을 제외하고. 모든 것은 RPython으로 작성되었으며, 파이썬 프로그래머에게는 친숙하도록 설계되었지만 Python은 아닙니다 . 마찬가지로 SqueakVM : 스몰 토크로 작성되지 않았습니다…
Jörg W Mittag

… Slang으로 작성되었으며, 실제로 코딩 한 사람들에 따르면 추상화 기능에서 C보다 훨씬 나쁩니다. Slang이 가진 유일한 장점은 Smalltalk의 적절한 하위 집합이므로 강력한 Smalltalk IDE를 개발하고 VM을 실행하고 가장 중요하게 디버깅 할 수 있다는 의미입니다.
Jörg W Mittag

2
다른 합병증을 추가하는 것 : 일부 해석 된 언어 (예 : FORTH 및 TeX)는 실행중인 시스템의로드 가능한 메모리 이미지를 실행 파일로 쓸 수 있습니다. 그런 의미에서 그러한 시스템 원래 통역사없이 실행될 수 있습니다 . 예를 들어 한 번은 16 비트 버전의 FORTH를 사용하여 다른 CPU에 대한 32 비트 버전을 "교차 해석"하고 다른 OS에서 실행하여 FORTH 인터프리터를 작성했습니다. FORTH 언어에는 자체 어셈블러가 포함되어 있으므로 "FORTH VM"(일반적으로 10 또는 20 개의 기계 코드 명령어 임)을 FORTH 자체로 작성할 수 있습니다.
alephzero

7

자체 호스팅 인터프리터는 여전히 인터프리터 자체를 실행해야하며 컴파일러와 같은 의미로 부트 스트랩 할 수 없다는 점에 유의하십시오.

그러나 자체 호스팅 언어 는 자체 호스팅 인터프리터와 다릅니다. 일반적으로 컴파일러를 빌드하는 것보다 인터프리터를 빌드하는 것이 더 쉽습니다. 따라서 새로운 언어를 구현하기 위해 먼저 관련없는 언어로 인터프리터를 구현할 수 있습니다. 그런 다음 해당 인터프리터를 사용하여 해당 언어의 컴파일러를 개발할 수 있습니다. 그런 다음 컴파일러가 해석되므로 언어가 자체 호스팅됩니다. 그런 다음 컴파일러는 자체적으로 컴파일 된 다음 완전히 부트 스트랩 된 것으로 간주 될 수 있습니다.

특별한 경우는 자체 호스팅 JIT 컴파일 런타임입니다. 호스트 언어의 인터프리터로 시작한 다음 새 언어를 사용하여 JIT 컴파일을 구현 한 후 JIT 컴파일러가 자체 컴파일 할 수 있습니다. 이것은 자체 호스팅 통역사처럼 느껴지지만 무한한 해석 문제를 회피합니다. 이 접근 방식이 사용되지만 아직 일반적이지 않습니다.

또 다른 관련 기술은 확장 가능한 해석기이며, 해석되는 언어로 확장을 만들 수 있습니다. 예를 들어, 언어로 새로운 opcode를 구현할 수 있습니다. 이것은 순환 의존성을 피하지 않는 한 베어 인터프리터를 기능이 풍부한 인터프리터로 바꿀 수 있습니다.

실제로 상당히 일반적으로 발생하는 경우는 구문 분석 시간 평가 매크로와 같이 언어가 자체 구문 분석에 영향을 줄 수있는 능력입니다. 매크로 언어는 처리되는 언어와 동일하기 때문에 전용 또는 제한된 매크로 언어보다 기능이 훨씬 풍부한 경향이 있습니다. 그러나 확장을 수행하는 언어는 확장 후의 언어와 약간 다른 언어입니다.

"실제"자체 호스팅 통역사를 사용하는 경우 이는 일반적으로 교육 또는 연구 목적으로 수행됩니다. 예를 들어 Scheme 내부에 Scheme에 대한 인터프리터를 구현하는 것은 프로그래밍 언어를 가르치는 멋진 방법입니다 (SICP 참조).

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