웹 사이트 http://coffeescript.org/ 에서 CoffeeScript를 연구 중이며 텍스트가 있습니다.
CoffeeScript 컴파일러 자체는 CoffeeScript로 작성되었습니다
컴파일러는 어떻게 스스로 컴파일 할 수 있습니까? 아니면이 문장은 무엇을 의미합니까?
웹 사이트 http://coffeescript.org/ 에서 CoffeeScript를 연구 중이며 텍스트가 있습니다.
CoffeeScript 컴파일러 자체는 CoffeeScript로 작성되었습니다
컴파일러는 어떻게 스스로 컴파일 할 수 있습니까? 아니면이 문장은 무엇을 의미합니까?
답변:
컴파일러의 첫 번째 버전은 특정 프로그래밍 언어에서 기계로 생성 할 수 없습니다. 당신의 혼란은 이해할 수 있습니다. 더 많은 언어 기능을 가진 최신 버전의 컴파일러 (새 언어의 첫 번째 버전에서 소스가 다시 작성된)는 첫 번째 컴파일러에 의해 빌드 될 수 있습니다. 그런 다음 해당 버전은 다음 컴파일러 등을 컴파일 할 수 있습니다. 예를 들면 다음과 같습니다.
참고 : CoffeeScript 버전의 번호가 정확히 어떻게 사용되는지 잘 모르겠습니다. 이는 단지 예일뿐입니다.
이 과정을 일반적으로 부트 스트랩 이라고 합니다. 부트 스트랩 컴파일러의 또 다른 예 rustc
는 Rust 언어 의 컴파일러입니다 .
신뢰 신뢰에 관한 논문 에서 유닉스의 창시자 중 하나 인 켄 톰슨 (Ken Thompson)은 C 컴파일러가 어떻게 자신을 컴파일하는지에 대한 흥미롭고 읽기 쉬운 개요를 작성합니다. CoffeeScript 또는 다른 언어에도 비슷한 개념을 적용 할 수 있습니다.
자체 코드를 컴파일하는 컴파일러의 아이디어 는 원본 소스 코드를 출력으로 생성 하는 quine : 소스 코드 와 모호 합니다. 다음은 CoffeeScript quine의 예 입니다. 톰슨은 다음과 같은 C 퀴인 예제를 제공했습니다.
char s[] = {
'\t',
'0',
'\n',
'}',
';',
'\n',
'\n',
'/',
'*',
'\n',
… 213 lines omitted …
0
};
/*
* The string s is a representation of the body
* of this program from '0'
* to the end.
*/
main()
{
int i;
printf("char\ts[] = {\n");
for(i = 0; s[i]; i++)
printf("\t%d,\n", s[i]);
printf("%s", s);
}
다음으로, 이스케이프 시퀀스와 같은 이스케이프 시퀀스가 '\n'
ASCII 코드 10을 나타내는 것으로 컴파일러에게 어떻게 배울 지 궁금 할 것입니다 . 답은 C 컴파일러 어딘가에 문자 리터럴을 해석하는 루틴이 있으며, 이와 같은 조건을 포함하여 백 슬래시 시퀀스를 인식합니다.
…
c = next();
if (c != '\\') return c; /* A normal character */
c = next();
if (c == '\\') return '\\'; /* Two backslashes in the code means one backslash */
if (c == 'r') return '\r'; /* '\r' is a carriage return */
…
위 코드에 하나의 조건을 추가 할 수 있습니다.
if (c == 'n') return 10; /* '\n' is a newline */
… '\n'
ASCII 10 을 나타내는 것을 알고있는 컴파일러를 만드는 것 . 흥미롭게도, 그 컴파일러 와 그에 의해 컴파일 된 모든 후속 컴파일러는 그 매핑을 "알고"있으므로 다음 세대의 소스 코드에서 마지막 행을 다음과 같이 변경할 수 있습니다.
if (c == 'n') return '\n';
… 그리고 옳은 일을 할 것입니다! 는 10
컴파일러에서 온다, 더 이상 명시 적으로 컴파일러의 소스 코드에 정의 될 필요가있다. 1
이것이 C 코드로 구현 된 C 언어 기능의 한 예입니다. 이제 모든 단일 언어 기능에 대해이 프로세스를 반복하면 "셀프 호스팅"컴파일러 (C로 작성된 C 컴파일러)가 있습니다.
1 이 논문에서 묘사 한 플롯 트위스트는 컴파일러가 이와 같은 사실을 "학습"할 수 있기 때문에 탐지하기 어려운 방식으로 트로이 목마 실행 파일을 생성하는 실수를 범할 수 있으며, 이러한 방해 행위는 지속될 수 있습니다. 오염 된 컴파일러가 생성 한 모든 컴파일러에서
당신은 이미 매우 좋은 대답을 얻었지만, 나는 당신에게 다른 관점을 제공하고 싶습니다. 먼저 두 가지 모두에 동의 할 수있는 두 가지 사실을 설정합시다.
# 1과 # 2가 모두 사실임을 동의 할 수 있습니다. 이제 두 진술을보십시오. CoffeeScript 컴파일러가 CoffeeScript 컴파일러를 컴파일 할 수있는 것은 완전히 정상적인 것입니까?
컴파일러는 상관하지 않는다 어떤 것이 컴파일합니다. CoffeeScript로 작성된 프로그램이라면 컴파일 할 수 있습니다. 그리고 CoffeeScript 컴파일러 자체는 그러한 프로그램입니다. CoffeeScript 컴파일러는 자신이 컴파일하고있는 CoffeeScript 컴파일러 자체에 신경 쓰지 않습니다. 보이는 것은 일부 CoffeeScript 코드입니다. 기간.
컴파일러는 어떻게 스스로 컴파일 할 수 있습니까? 아니면이 문장은 무엇을 의미합니까?
그렇습니다. 그것이 바로 그 진술이 의미하는 바이며, 이제 그 진술이 어떻게 진실인지 알 수 있기를 바랍니다.
컴파일러는 어떻게 스스로 컴파일 할 수 있습니까? 아니면이 문장은 무엇을 의미합니까?
그것은 정확히 의미합니다. 우선, 고려해야 할 사항이 있습니다. 살펴 봐야 할 네 가지 객체가 있습니다.
이제 CoffeScript 컴파일러의 생성 된 어셈블리 (실행 파일)를 사용하여 임의의 CoffeScript 프로그램을 컴파일하고 해당 프로그램에 대한 어셈블리를 생성 할 수 있습니다.
이제 CoffeScript 컴파일러 자체는 임의의 CoffeScript 프로그램이므로 CoffeScript 컴파일러로 컴파일 할 수 있습니다.
당신의 혼란은 당신이 당신의 자신의 새로운 언어를 만들 때, 당신은하지 않는 것이 사실에서 비롯된 것으로 보인다 가지고 컴파일러를 아직 당신이 당신의 컴파일러를 컴파일하는 데 사용할 수 있습니다. 이것은 분명히 닭 계란 문제 처럼 보입니다 .
bootstrapping 이라는 프로세스를 소개하십시오 .
이제 새로운 기능을 추가해야합니다. while
-loops 만 구현 했지만 for
-loops 를 원한다고 가정하십시오. for
-loop와 같은 방식으로 -loop를 다시 작성할 수 있으므로 이것은 문제가되지 않습니다 while
. 즉, 사용 while
중인 어셈블리는 컴파일 만 할 수 있으므로 컴파일러의 소스 코드에는 -loops 만 사용할 수 있습니다. 그러나 컴파일러 내에서 for
루프를 실행 하고 컴파일 할 수있는 함수를 작성할 수 있습니다 . 그런 다음 이미 가지고있는 어셈블리를 사용하고 새 컴파일러 버전을 컴파일하십시오. 그리고 이제 for
루프를 구문 분석하고 컴파일 할 수있는 컴파일러 어셈블리가 있습니다 ! 이제 컴파일러의 소스 파일 while
로 for
돌아가서 원하지 않는 -loops를 -loops에 다시 쓸 수 있습니다 .
원하는 모든 언어 기능을 컴파일러로 컴파일 할 수있을 때까지 헹구고 반복하십시오.
while
그리고 for
분명히 단지 예시했지만, 이것은 당신이 원하는 새로운 언어 기능이 작동합니다. 그런 다음 CoffeScript가 현재 상황에 있습니다. 컴파일러가 자체 컴파일됩니다.
거기에 많은 문헌이 있습니다. 신뢰에 대한 고찰 신뢰 는 그 주제에 관심이있는 모든 사람들이 최소한 한 번은 읽어야하는 고전입니다.
여기서 컴파일러 라는 용어 는 두 개의 파일이 관련되어 있다는 사실을 강조 합니다. 하나는 CoffeScript로 작성된 입력 파일로 사용하고 다른 실행 파일, 링크 가능한 객체 파일 또는 공유 라이브러리를 출력 파일로 생성하는 실행 파일입니다. 다른 하나는 CoffeeScript 컴파일 절차를 설명하는 CoffeeScript 소스 파일입니다.
첫 번째 파일을 두 번째 파일에 적용하여 첫 번째 파일을 첫 번째 파일과 동일한 컴파일 동작을 수행 할 수있는 세 번째 파일을 생성합니다 (두 번째 파일이 첫 번째 파일에 의해 구현되지 않은 기능을 정의하는 경우 더 많을 수 있음). 욕망.
CoffeeScript 컴파일러의 Ruby 버전이 이미 존재하기 때문에 CoffeeScript 컴파일러의 CoffeeScript 버전을 작성하는 데 사용되었습니다.
이를 자체 호스팅 컴파일러라고 합니다.
매우 흔하며 일반적으로 언어의 성장을 유지하기 위해 자신의 언어를 사용하려는 저자의 소망에서 비롯됩니다.
컴파일러는 특정 언어로 작성된 프로그램이기 때문에 컴파일러의 문제가 아니라 표현력의 문제입니다.
"언어가 작성 / 구현된다"고 할 때 실제로는 해당 언어에 대한 컴파일러 또는 인터프리터가 구현됨을 의미합니다. 언어를 구현하는 프로그램을 작성할 수있는 프로그래밍 언어가 있습니다 (동일한 언어의 컴파일러 / 통역사). 이 언어를 보편적 언어 라고 합니다 .
이것을 이해하려면 금속 선반에 대해 생각하십시오. 금속을 성형하는 데 사용되는 도구입니다. 해당 도구 만 사용하여 부품을 작성하여 동일한 동일한 다른 도구를 작성할 수 있습니다. 따라서이 도구는 범용 기계입니다. 물론 첫 번째 방법은 다른 방법 (다른 도구)을 사용하여 만들어졌으며 아마도 품질이 떨어졌을 수 있습니다. 그러나 첫 번째 것은 더 높은 정밀도로 새로운 것을 만드는 데 사용되었습니다.
3D 프린터는 거의 보편적 인 기계입니다. 3D 프린터를 사용하여 전체 3D 프린터를 인쇄 할 수 있습니다 (플라스틱을 녹이는 팁을 만들 수 없음).
컴파일러는 높은 수준의 사양을 사용하여 하드웨어에서 실행될 수있는 것과 같은 낮은 수준의 구현으로 변환합니다. 따라서 대상 언어의 시맨틱 외에 사양 형식과 실제 실행 간에는 관계가 없습니다.
크로스 컴파일러는 한 시스템에서 다른 시스템으로 이동하고, 언어 간 컴파일러는 한 언어 사양을 다른 언어 사양으로 컴파일합니다.
기본적으로 컴파일은 단순한 번역이며 수준은 일반적으로 언어 수준이 높을수록 언어 수준이 낮지 만 여러 변형이 있습니다.
부트 스트랩 컴파일러는 물론 가장 혼란 스럽습니다. 그들이 작성하는 언어를 컴파일하기 때문입니다. 부트 스트랩의 초기 단계는 실행 가능한 최소한의 기존 버전이 필요하다는 것을 잊지 마십시오. 많은 부트 스트랩 컴파일러는 프로그래밍 언어의 최소 기능을 먼저 작동하고 이전 기능을 사용하여 새 기능을 표현할 수있는 한 복잡한 언어 기능을 추가합니다. 그렇지 않은 경우 "컴파일러"의 해당 부분을 미리 다른 언어로 개발해야합니다.
self-hosting
컴파일러입니다. programmers.stackexchange.com/q/263651/6221