CS TIL (20180813)

2019-04-18

.

study program : https://www.fastcampus.co.kr/dev_school_css

# 컴파일러 언어와 인터프리터 언어

프로그래밍을 배우다 보면 컴파일러 언어와 인터프리터 언어라는 말을 가끔 듣게 된다. 대표적인 컴파일러 언어에는 C나 자바가 있고 인터프리터 언어에는 파이썬이나 자바스크립트가 있다.

# 컴파일러 언어 (c언어를 예시로)

C 언어는 소스코드를 컴파일하여 object code 인 기계어로 된 인스트럭션을 만들어낸다. linker는 필요한 라이브러리를 가져오고, 여러 개의 목적 파일을 함께 묶어 executable file(실행파일)을 생성한다. 그리고 프로그램을 실행하고 데이터를 입력하면 결과 데이터가 출력된다. 중요한 점은 소스 코드를 분석하는 compile time과 실제 데이터를 입력받아 결과를 출력하는 run time이 분리되어 있다는 점이다.

1

# 인터프리터 언어(Python을 예시로)

파이썬도 소스 코드가 있으므로 이를 분석하는 컴파일러가 있다. object code로 기계어를 생성하는 C 언어와 달리 파이썬은 byte code를 생성한다. byte code가 생성된 후에는 PVM(Python Virtual Machine)서 byte code를 하나씩 해석하여 프로그램을 실행한다. 중요한 점은 소스 코드를 분석하는 컴파일 타임이 따로 없고 실행과 동시에 분석을 시작한다는 점이다. 다시말해, 소스 코드와 입력 데이터가 같은 시점에 삽입됩니다. 이점이 컴파일러 언어와 비교했을 때 가장 큰 차이다.

2

# Python을 예시로 source code에서 실행까지 과정

컴파일러

구성 : lexer와 parser

캐릭터 : ‘나는 사과를 먹는다’ ==> lexer ==> 토근 : <’나는’ 주어> <’사과를’, 목적어> <’먹는다’, 서술어>

토근 ==> parser ==> 분석 트리

3

분석 트리가 만들어지면 이를 이용해 목적 코드(C 언어는 기계어, 파이썬은 바이트 코드)를 생성하는데 이를 code generation이라고 한다.

파이썬은 파이썬 컴파일러를 통해 다음과 같은 과정을 거쳐 바이트 코드를 생성한다.

step1) 소스 코드 → 분석 트리

step2) 분석 트리 → 추상 구문 트리

step3) 심벌 테이블 생성

step4) 추상 구문 트리 → 바이트 코드

심벌테이블

변수와 함수를 모아서 그 속성에 대해 기술해 놓은 테이블.

심벌테이블이 있기 때문에 스텍 프레임을 쌓을 수 있다.

4

바이트 코드

이렇게 생성된 바이트 코드는 PVM(Python Virtual Machine) 위에서 실행된다. 결론적으로 PVM은 그저 굉장히 큰 무한 루프일 뿐이다.

“_PyEval_EvalFrameDefault()” 라는 함수 바이트 코드의 실제 실행을 담당하는 함수로, 이 함수 안에서 opcode라는 변수가 바이트 코드를 받아온다.

초기식이나 증감식이 없는 for(;;) 문은 무한 루프를 의미한다. 파이썬의 while True:와 같다. 이 무한 루프가 바로 PVM이다. 무한 루프 안에는 실제 바이트 코드를 분석해서 실행하는 switch 문이 있다. 파이썬에는 switch 문이 없는 대신 if ~ elif 문이 그 역할을 한다.

switch 문 안에 있는 case 문을 살펴보면 NOP, LOAD_FAST, STORE_FAST 같은 바이트 코드가 눈에 보이는데 Opcode가 NOP라면 break 문을 만날 때까지 case NOP: 부분이 실행된다. 다른 opcode라면 그에 해당하는 case 문이 실행된다.