왜 C ++이 컴파일러를 작성하기에 좋은 선택인지 궁금했습니다. 물론 많은 컴파일러가 C 또는 C ++로 작성되었지만 이번에는 C ++에 더 관심이 있기 때문에 C도이 목적에 적합합니다. 좋은 이유가 있습니까? 나는 인터넷에서 그것을 찾고 있었지만 좋은 이유를 찾을 수 없습니다.
왜 C ++이 컴파일러를 작성하기에 좋은 선택인지 궁금했습니다. 물론 많은 컴파일러가 C 또는 C ++로 작성되었지만 이번에는 C ++에 더 관심이 있기 때문에 C도이 목적에 적합합니다. 좋은 이유가 있습니까? 나는 인터넷에서 그것을 찾고 있었지만 좋은 이유를 찾을 수 없습니다.
답변:
C ++에는 두 가지 측면이 있습니다. 저수준 개발 측면을 가지고있어 코드 생성과 같은 저수준 일을하는 데 자연스러운 언어처럼 보입니다. 또한 높은 수준의 측면 (C는 그렇지 않음)을 사용하여 복잡한 응용 프로그램 (컴파일러와 같은)을 논리적 객체 지향 방식으로 구성하면서 성능을 계속 유지할 수 있습니다. 낮은 수준과 높은 수준의 측면을 모두 가지고 있기 때문에 낮은 수준의 기능이나 성능이 필요한 대규모 응용 프로그램에 적합합니다.
내 경험이 여기에 당신의 전제에 동의하지 않습니다. 사실, 고급 범용 언어의 경우 소스 언어 (컴파일되는 언어)와 동일한 언어로 컴파일러를 작성하는 것이 일반적 입니다. 예를 들면 다음과 같습니다.
예외는 GCC, LLVM 또는 Polyglot과 같은 기존 컴파일러 프레임 워크 용으로 작성된 컴파일러 프론트 엔드이며 프레임 워크 언어로 작성된 컴파일러 또는 Yacc와 같은 기존 파서 생성기를 사용하는 컴파일러입니다. GCC, LLVM 및 Yacc는 C 및 C ++로 작성된 일반적이고 확립 된 도구이므로 컴파일러 작성자가이를 사용하도록 인센티브를 제공하므로 C 및 C ++가 컴파일러 구현 언어 배포에서 큰 비중을 차지하게됩니다.
javac
Java를 Java 바이트 코드로 컴파일하는 Sun의 Java 컴파일러 ( 명령 줄)입니다. Java로 작성되었습니다. 여러 번 직접 수정 했으며 Java 소스를 온라인으로 찾아 볼 수 있습니다 . 다른 하나는 핫스팟 JVM에 내장 된 JIT (Just-In-Time) 컴파일러입니다.이 컴파일러는 Java 바이트 코드 를 기본 머신 코드로 컴파일합니다 . 대부분의 JVM과 마찬가지로 C ++로 작성되었지만 Java 컴파일러 는 아닙니다. 실제로 Java 언어에 대해서는 아무것도 모릅니다.
무엇을 무엇으로 컴파일하려면? 컴파일러는 소스 코드를 한 언어 (원본 언어) 에서 다른 언어 (대상 언어)로 변환하는데, 이는 대상 언어의 저수준에 대해서는 아무 것도 나타내지 않습니다.
컴파일러를 작성하기 위해 선택한 언어는 상황에 따라 다릅니다. 예를 들어, PHP에서 파생 된 언어를 기본 PHP 코드로 컴파일하는 프로젝트를 작업하면서 PHP와 C #을 혼합하여 컴파일러를 작성했습니다. 다른 사람은 Python, Java 및 PHP 또는 C ++을 약간의 JavaScript 또는 기타로 선택합니다.
C 또는 C ++는 컴파일러 관련 도구 (Telastyn의 답변 참조)를 지원하고이 두 언어를 사용하면 실제로 네이티브로 이동할 수 있기 때문에 널리 사용됩니다. 그러나 다른 언어를 선택하는 데 아무런 문제가 없습니다.
좀 더 괴상 하기 위해 컴파일러 자체를 작성하기 위해 소스 언어를 선택할 수 있습니다. CoffeeScript 컴파일러와 다른 많은 컴파일러에서 일어난 일입니다. IDE에도 인기가 있습니다. 첫 번째 Visual Studio 중 하나는 동일한 Visual Studio를 사용하여 빌드되었습니다.
나는 여기서 기본적인 전제에 의문을 갖는 경향이있다. C와 C ++는 컴파일러 작성에 완벽하게 작동하지만 다른 언어들도이 작업에 완벽하게 작동하는 것 같습니다.
약간은 컴파일하는 언어에 따라 다릅니다. 작고 간단한 언어의 경우 C와 Pascal이 잘 작동합니다. 크고 복잡한 것을 컴파일하려는 경우 컴파일러도 크고 복잡해집니다.이 경우 더 큰 프로그램을 구성하고 작업하기위한 C ++의 추가 기능은 분명히 유용합니다. 컴파일에는 그다지 구체적이지 않고 일반적으로 더 큰 프로그램에 유용한 기능입니다.
다른 요점도 언급 할 가치가 있다고 생각합니다. 초보자는 컴파일러가 주로 텍스트 조작을하는 것으로 생각하므로 Perl과 같은 것이 컴파일러 작성에 큰 도움이 될 것이라고 생각합니다. 실제로 컴파일의 흥미로운 부분은 대부분 AST를 빌드 한 후에 시작되지 않습니다. Perl이 완벽하게 잘 할 수 있다고 확신하지만 텍스트 조작 기능은 실제로 큰 이점을 제공하지는 않습니다 (텍스트 조작은 대부분 어휘 분석기에 있으며 C와 같은 것들에 대한 어휘 생성기는 RE를 지원합니다).
컴파일러는 모든 현대 언어로 구현 될 수 있습니다. 그러나 컴파일러의 가장 중요한 요구 사항 중 하나는 빠릅니다.
C ++은 여기에 분명한 장점이 있습니다. C ++의 최적화는 저렴하지 않습니다. 그러나이 언어의 낮은 수준의 특성으로 인해 다른 언어 (휴대용이 아닌 어셈블리 제외)보다 C ++ 코드를 수동으로 최적화 할 수 있습니다.
나는 그들의 사용에 대한 주요 동기가 C에서 Lex / Yacc / Bison 출력이 (주로) 있다고 생각합니다. 그것이 오랫동안 표준 이었으므로 추진력이 있습니다.
그것들이 특히 좋은 이유는 아닙니다 ...
이 문제에 대한 경험이 있습니다. C 및 C ++로 컴파일러를 작성했습니다. C와 C ++의 주요 차이점은 C에 자동 방식으로 동적 메모리 관리 기능이 없다는 것입니다. C의 모든 메모리 관리는 명시 적으로 수행해야합니다. 컴파일러를 작성하면 문자열 처리 및 배열 관리가 많이 처리됩니다. C에서는 모든 문자열과 선언하는 모든 배열의 크기를 생각하고 해당 객체에 액세스 할 때 인덱스를 확인해야합니다 (코드를 안전하고 안정적으로 유지하려는 경우). C에서는 물론 동적 메모리 관리가 가능하지만 자동적 인 것은 없습니다. malloc () 및 free ()를 사용하여 명시 적으로 메모리를 할당하고 사용 가능하게하고 동적 오브젝트의 크기를 분리 된 변수로 유지하여 경계 외부로 액세스하지 않도록해야합니다.
C ++에서는 동일한 메커니즘을 사용할 수 있지만 명시 적으로 호출 할 필요가없는 생성자와 소멸자 내에 모든 메모리 관리를 캡슐화 할 수 있기 때문에 실제로 개발 시간이 효율적입니다. 따라서 컴파일러는 리소스를 할당하고 해제합니다. 클래스를 직접 만들면 동적 객체의 크기를 캡슐화 할 수 있으며 오버로드 연산자 []를 사용하여 경계 액세스를 위해 인덱스를 확인할 수 있습니다. 이러한 추상화는 코드를 더 깨끗하고 이해하기 쉽고 디버깅하며 개발 속도를 높여줍니다.
C로 컴파일러를 만들면 더 많은 시간이 걸립니다. C ++을 사용하면 짧은 시간 안에 프로젝트를 완료 할 수 있습니다. C와 C ++의 성능은 동일하지만 C ++에는 C와는 다른 많은 장점이 있습니다.
CompCert의 프로젝트는 연구의 C ++ C 또는 C로 작성되지 않은 컴파일러,하지만 더 OCaml로하고 COQ입니다.
C ++가 C로 번역 된 적이 있음을 관찰하십시오 ( Cfront에서 ). 이제 GCC 프론트 엔드를 Gimple으로 사용 하고 Gimple을 일부 데이터베이스에 덤프 한 다음 Gimple을 어셈블러 번역기에 쓸 수 있습니다. 그러나 법적 이유 ( GCC 런타임 라이브러리 예외 )는 이러한 컴파일러가 오픈 소스 여야합니다. 자세한 내용은 변호사에게 문의하십시오. 저는 변호사가 아닙니다. 이전 버전의 GCC는 일부 C ++ 변형에 대한 프런트 엔드를 사용하여 C (+ 여러 도메인 특정 언어)로 작성되었습니다. OpenWatcom 은 C로 작성된 C ++ 컴파일러 일 수 있습니다 (확인하겠습니다).
Compcert의 출처는 학술 및 연구 목적으로 무료로 제공됩니다. 산업적으로 (법적으로) 사용하려면 Absint로부터 라이센스를 받아야합니다.
내가 2020 년에 C (또는 C ++) 컴파일러를 처음부터 (Linux에서 실행 중이거나, 일부 크로스 컴파일러에서 ) 작성해야한다면 아마도 C ++로 작성하지 않을 것입니다. Ocaml , Go 또는 Rust 사용하여 작성하는 것이 좋습니다. 그리고 가능하다면 Frama-C를 기반으로 할 수 있습니다. C 또는 C ++로 코딩 해야하는 경우 먼저 가비지 수집기 라이브러리를 코딩합니다. 일부 지속성 계층은 전체 프로그램 최적화에 매우 유용합니다. 그런 다음 메타 프로그래밍 방식을 고려합니다 (대부분의 C 또는 C ++ 코드 생성) Ad-hoc 도구가 포함 된 컴파일러, Bismon 또는 RefPerSys 허용되는 경우).
Common Lisp 또는 Python (예 : ShivyC 또는 nqcc )으로 코딩 된 일부 (오픈 오픈 소스) C 컴파일러를 찾을 수 있습니다. ZetaC 도 살펴보십시오 .
최신 버전의 GCC 는 기술적으로 순수 C ++로 코딩되지 않았으며, GCC와 관련된 수십 개의 도메인 특정 언어입니다 (여러 언어 는 Turing-complete ). 내 이전 GCC MELT 프로젝트 도 참조하십시오 .
향후 버전의 GCC에서 일부 Python 또는 Guile 인터프리터가 GCC의 패스 관리자를 대체하는 것과 같이 내부에 포함되어 있으면 놀라지 않을 것입니다.
MILEPOST GCC 프로젝트 도 살펴보십시오 .