해석과 컴파일 : 유용한 차이점?


29

해석 된 언어와 컴파일 된 언어 구현에 대한 많은 질문이 여기에 있습니다. 구별이 실제로 어떤 의미가 있는지 궁금합니다. (실제로 질문은 일반적으로 언어에 관한 것이지만 실제로는 그 언어의 가장 보편적 인 구현에 대해 생각하고 있습니다).

오늘날 거의 구현이 엄격하게 해석되지 않습니다. 즉, 한 번에 한 줄씩 코드를 구문 분석하고 실행하는 사람은 거의 없습니다. 또한 머신 코드로 컴파일하는 구현도 덜 일반적입니다. 점점 더 많은 컴파일러가 일종의 가상 머신을 대상으로합니다.

실제로 대부분의 구현은 동일한 기본 전략으로 수렴되고 있습니다. 컴파일러는 JIT를 통해 원시 코드로 해석되거나 컴파일 된 바이트 코드를 생성합니다. 그것은 실제로 컴파일과 해석의 전통적인 아이디어의 혼합입니다.

따라서 나는 묻습니다. 요즘 해석 된 구현과 컴파일 된 구현 사이에 유용한 차이점이 있습니까?


7
@DeadMG 당신이 생각하는 것처럼 새롭지 않은 : 적시 의 짧은 역사 ...
yannis

4
@DeadMG 지난 10 년 동안 도입 된 새로운 언어의 대부분이 주로 일종의 VM에서 실행된다는 점을 감안할 때, 그는 그가 요점을 가지고 있다고 말합니다. 물론 네이티브 코드로 컴파일 된 언어가 여전히 있으며 앞으로 수십 년 동안 JIT는 고급 상태를 유지할 것입니다. 그렇습니다. 과장된 진술이 가능하지만 주류 (현재와 예측 가능한 미래)는 바이트 코드 컴파일러 + 아마도 JIT 인 것으로 동의합니다.

4
@DeadMG, VM 모델이 "새"인 경우 길고 흰 수염이 있어야합니다. P-code1966 년에 처음 소개되었습니다. IBM AIX는 1986 년부터 주변에
SK-논리

6
유닉스 쉘, Tcl 등은 항상 순수하게 해석되므로 적어도 학문적 인 CS에서는 구별이 의미가 있습니다. 그러나 코더가 인터프리터와 컴파일러에 대해 불평 할 때 대부분의 경우 이해가되지 않습니다.
SK-logic

3
@ SK-logic, 귀하의 의견이 더 나은 답변이라고 생각합니다. 그러면 실제로 게시 된 답변들입니다.
Winston Ewert

답변:


23

해석과 컴파일은 서로에 대한 대안이 아니라는 점을 명심해야합니다. 결국, 여러분이 작성하는 모든 프로그램 (머신 코드로 컴파일 된 프로그램 포함)이 해석됩니다. 코드 해석은 단순히 일련의 지침을 취하고 답변을 반환하는 것을 의미합니다.

반면에 컴파일은 한 언어의 프로그램을 다른 언어로 변환하는 것을 의미합니다. 일반적으로 컴파일이 수행 될 때 코드는 "낮은 수준의"언어 (예 : 머신 코드, 일종의 VM 바이트 코드 등)로 컴파일된다고 가정합니다. 이 컴파일 된 코드는 여전히 나중에 해석됩니다.

해석 된 언어와 컴파일 된 언어 사이에 유용한 차이점이 있는지에 대한 귀하의 질문과 관련하여, 제 개인적인 견해는 모든 사람들이 해석하는 동안 작성한 코드에 무슨 일이 일어나고 있는지에 대한 기본적인 이해가 있어야한다는 것입니다. 따라서 코드가 JIT 컴파일 또는 바이트 코드 캐시 등이라면 프로그래머는 최소한 그 의미에 대한 기본적인 이해가 있어야합니다.


3
예, 프로그래머는 기본적인 이해를해야합니다. 그러나 컴파일 / 해석 된 용어가 그렇게되지 않는지 궁금합니다.
Winston Ewert

2
고맙습니다!! 해석은 "실행 된"의 동의어 일 뿐이며 모든 프로그램이 실행되는 방식입니다.
gardenhead

9

컴파일 된 언어가 의미를 해석하는 언어가 반드시 의미하지 않는 방식으로 의미를 제한하기 때문에 구별이 매우 의미가 있습니다. 일부 해석 기술은 컴파일하기가 매우 어렵습니다 (실제로는 불가능합니다).

해석 된 코드는 런타임시 코드 생성과 같은 작업을 수행하고 해당 코드에 기존 범위의 어휘 바인딩에 대한 가시성을 제공 할 수 있습니다. 하나의 예입니다. 또 다른 방법은 인터프리터가 코드를 평가하는 방법을 제어 할 수있는 해석 된 코드로 확장 될 수 있다는 것입니다. 이것은 고대 Lisp "fexprs"의 기초입니다. 평가되지 않은 인수로 호출되고 함수로 무엇을할지 결정하는 함수 (코드를 걷고 변수를 평가하는 데 필요한 환경에 대한 전체 액세스 권한을 가짐) 컴파일 된 언어에서는 실제로이 기술을 사용할 수 없습니다. 대신 매크로를 사용합니다. 컴파일 할 때 평가되지 않은 인수로 호출되는 함수이며 해석하는 대신 코드를 변환합니다.

일부 언어 구현은 이러한 기술을 중심으로 구축되었습니다. 그들의 저자는 컴파일을 중요한 목표로 삼는 것을 거부하고 오히려 이런 종류의 유연성을 받아들입니다.

해석은 항상 컴파일러를 부트 스트랩하는 기술로 유용합니다. 구체적인 예는 CLISP (Common Lisp의 일반적인 구현)를 살펴보십시오. CLISP에는 자체적으로 작성된 컴파일러가 있습니다. CLISP를 빌드하면 초기 빌드 단계에서 해당 컴파일러가 해석됩니다. 자체 컴파일에 사용되며 일단 컴파일되면 컴파일 된 컴파일러를 사용하여 컴파일이 수행됩니다.

인터프리터 커널이 없으면 SBCL처럼 기존 Lisp로 부트 스트랩해야합니다.

해석을 통해 어셈블리 언어부터 시작하여 절대적으로 처음부터 언어를 개발할 수 있습니다. 기본 I / O 및 핵심 루틴을 개발 한 후 여전히 기계 언어의 평가를 작성하십시오. 평가가 끝나면 고급 언어로 작성하십시오. 머신 코드 커널이 평가를 수행합니다. 이 기능을 사용하면 더 많은 루틴을 사용하여 라이브러리를 확장하고 컴파일러도 작성할 수 있습니다. 컴파일러를 사용하여 해당 루틴과 컴파일러 자체를 컴파일하십시오.

해석 : 편집으로 이어지는 길에서 중요한 디딤돌입니다!


1
IMO, 이것이 최선의 대답입니다. 나는 내 장난감 언어로 작업하고 있으며 마지막 단락은 그것을 개발하는 방법을 설명합니다. 새로운 아이디어에 대한 작업이 훨씬 쉬워졌습니다. CLISP 부트 스트랩 프로세스에 대해서도 +1입니다.
sinan

이론적으로, 모든 "해석 된"언어는 인터프리터와 해석 된 프로그램의 소스 코드 또는 바이트 코드로 구성된 EXE 파일을 생성하여 "컴파일 된"언어로 만들 수 있습니다. 그러나 매우 효율적이지 않을 수 있습니다.
dan04

Wirth 등이 PSC 코드를 발명하여 PASCAL을 새로운 기계 아키텍처로 간단하게 포팅하는 방법을 읽어보십시오. 1970 년대 초반이었습니다.
John R. Strohm 2009 년

1
시작 문단이 컴파일 및 해석을 정적 및 동적 동작과 혼동하는 것으로 생각되지만 의심의 이점을 제공하고 컴파일이 "실제적으로 불가능한"의미를 가진 언어의 예를 요청합니다. 컴파일러 부트 스트랩과 관련하여 첫 번째 구현은 구현하려는 언어 이외의 언어로 작성해야하지만, 통역자가 아니어도 다른 언어로 작성된 컴파일러 일 수 있습니다.
8bittree

1

실제로 많은 언어 구현은 여전히 ​​엄격히 해석되며, 그 사실을 알지 못할 수도 있습니다. UNIX 쉘 언어, Windows cmd 및 PowerScript 쉘, Perl, awk, sed, MATLAB, Mathematica 등을 예로들 수 있습니다.


3
나는 Perl이 내부적으로 바이트 코드로 컴파일되고 적어도 Mathematica가 컴파일 될 수 있다고 생각합니다. 그리고 awk와 sed의 구현을 지시하는 것은 아무것도 없습니다 (GNU coreutils 중 일부는 실행 전에 정규식을 유한 automata로 컴파일한다고 믿습니다.

1
실제로 Perl, MATLAB, Mathematica는 모두 바이트 코드로 컴파일됩니다. PowerScript에 익숙하지 않습니다. Powershell을 의미합니까? 그렇다면 CLR을 사용하는 것과 바이트 코드를 사용하는 것입니다.
Winston Ewert

@WinstonEwert, 죄송합니다. PowerShell을 의미했습니다. 내 이해는 중간 형태로의 번역이 무언가가 해석되지 않는다는 것을 의미하지는 않는다는 것이다. 원래 Dartmouth BASIC 통역사가 Heck을 해석하기 전에 소스를 토큰으로 변환했습니다. 내가 언급 한 각 도구에는 1) 소스 라인을 읽고 2) 해당 라인을 실행 가능한 형식으로 변환합니다 (아마도 원시 코드가 아닌 일부 중간 코드) .3) 해당 라인의 코드를 실행합니다 .4) 1)로 되돌아갑니다. 그것은 통역사에 대한 나의 이해에 해당합니다.
Charles E. Grant

2
바이트 코드는 컴파일되었음을 의미합니다. 바이트 코드 컴파일러는 단순히 소스를 가져 와서 바이트 코드로 변환하는 프로그램입니다. 따라서 모든 바이트 코드 사용에는 바이트 코드 컴파일러가 포함되어야합니다. 그러나 바이트 코드도 해석해야합니다 (또는 JITted). 바이트 코드를 사용하는 것은 인터프리터 / 컴파일러 하이브리드입니다.
Winston Ewert

4
실제로, 사람들은 구현에 대한 이해없이 "파이썬이 해석된다", "자바가 컴파일되었다"와 같은 문장을 던져 버리는 것입니다. 그 용어로 구현을 설명하는 것이 유용한 지 묻고 있습니다. 진실은 일반적으로 더 복잡하며 해석 / 컴파일로 정리하려고하는 것은 유용하지 않습니다.
Winston Ewert

1

생각합니다 : 물론 그렇습니다 .

실제로 대부분의 구현은 동일한 기본 전략으로 수렴되고 있습니다.

실제로 C ++은 일반적으로 인터프리터에게 전달되는 고급 개념을 컴파일러 도메인으로 이식하는 것을 목표로하지만 소수 측면에 머물러 있습니다 ...


2
Clang + LLVM이 가장 널리 사용되는 컴파일러 툴체인이 될 때까지 기다리십시오.
SK-logic

@ SK-logic은 이름에도 불구하고 Clang + LLVM이 기본 코드를 생성한다고 생각합니다.
Winston Ewert

1
원하는 경우에만 @Winston Ewert. LLVM IR 레벨을 중지하고 원하는대로 수행 할 수 있습니다. 해석, JIT 컴파일, 원하는 방식으로 계측하십시오. 당신은 자바 스크립트로 번역하고 통역을 통해 전달할 수 있습니다 github.com/kripken/emscripten/wiki
SK-논리

@ SK-logic, 깔끔한 것들! LLVM이 그렇게 할 수 있다는 것을 몰랐습니다.
Winston Ewert

1
llvm의 장점은 프런트 엔드와 백 엔드 간의 의도적 인 분리입니다. 명령 세트를 대상으로하기 전에 중간을 조작하기위한 도구. 전체 프로젝트를 바이트 코드로 병합 한 다음 전체를 최적화 할 수 있습니다. 다른 컴파일러와 함께 단일 파일 소스 또는 소스 트리를 통과하는 경로를 포함하는 최소한 하나의 파일 소스가 있어야 컴파일러가 하나의 결합 된 소스에서 작동합니다. 또한 llvm 아래의 도구 세트는 모든 대상에 공통적이므로 각 대상에 대해 빌드 할 필요가 없으며 하나의 컴파일러가 모든 대상에 적합합니다 (적어도 대상의 asm에 해당).
old_timer 2012

-1

유용한 구별 : 해석 된 프로그램은 런타임에 기능을 추가하거나 변경하여 스스로를 수정할 수 있습니다.


8
무의미한 말. 자체 수정 (기계) 코드는이 책에서 가장 오래된 트릭입니다. 다시 말하지만, 일부는 원시 코드조차도 궁극적으로 실리콘 (CPU)으로 캐스팅 된 인터프리터에 의해 해석된다고 주장합니다. 그러나 우리가 가정하면 모든 코드가 해석되며 구별 할 필요가 없습니다.

2
@delnan이 맞습니다. 현대 언어가 새로운 클래스를 동적으로 생성하고 라이브러리 (또는 예를 들어 .NET의 "어셈블리")를로드 / 언로드함으로써 현대 언어가 스스로를 수정할 수 있다고
덧붙입니다.

5
공통 Lisp는 컴파일되지만 런타임에서 함수 정의를 쉽게 바꿀 수 있습니다.
SK-logic

그것은 해석의 정말 흥미롭고 필요한 것입니다 (예를 들어 Prolog에서).
CapelliC
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.