티스토리 뷰

Etc.

컴파일러와 인터프리터의 차이

ccc124213131 2021. 10. 10. 00:00
728x90

# 컴파일러

 

역사적으로, 1950년대 까지는 컴퓨터 프로그램은 어셈블리어로 만들어졌다. 그러다가 1951-1952년 Grace Hopper가 UNIVAC I을 위해 A-0 시스템을 개발했다. Grace Hopper는 나중에 COBOL 디자인에 중요한 기여를 하였다. 1957년에는 John Backus가 이끄는 팀에 조직에 의해 포트란 컴파일러가 IBM에서 개발되었다.

이후 1960년대에 LISP를 위한 최초의 bootstrapping compiler가 만들어졌고, 1970년대에 이르러서는 굉장히 많은 프로그래밍 언어와 컴파일러 설계가 이루어졌다.

오늘날에는 약 수천개의 언어가 존재한다. (대부분은 거의 쓰이지 않지만..)



# 기본 아키텍처

컴파일러는 프론트엔드와 백엔드로 나뉜다. 프론트엔드에는 Parsing, 백엔드에는 Optimization과 Code generation으로 구성된다.

 

## 프론트엔드

프론트엔드는 다시 Lexing과 (앞서 말한 Parsing보다 협의의) Parsing으로 구성된다. 이 두 과정을 거쳐 소스코드 문자열은 data structures로 변환된다. 보통 소스코드 문자열을 Token들로 변환하는 과정을 Lexing, 이후 Token을 Abstract Syntax Tree로 변환하는 과정을 Parsing이라 한다.

 

### Parsing 툴

Parsing의 대표적인 툴로는 Lex, Yacc, Menhir, Antlr 등이 존재한다. 이들은 Regular expression(finite state automata 이론)과 Context-free grammars(push-down automata 이론) 등의 많은 CS 이론등이 활용되어 개발된다.

 

### Type-checking

Type-checking은 보안, safety를 위해 sub-expression에 대한 타입을 추론하고, 옳은 타입이 주어졌는지를 확인하는 작업이다.

Ex. Untyped AST -> Typed AST

 

### Lowering

high-level feature들을 타겟 코드와 유사한, 더 작은 수의 feature들로 변환하는 과정이다. 예를 들어, C의 while, for, do-loops 들은 모두 goto 문으로 변환된다. 또한 object, closure 등은 record와 function pointer 등으로 변환되고, type test와 array 바운드 체크 등이 진행된다.

Typed AST -> Intermediate Code ASTs

 

## 백엔드

백엔드는 Optimization과 Code generation으로 구성된다. 이 두 과정을 거쳐 최종적으로 타겟 코드가 산출된다.

 

### Optimization

이 과정에서는 비용이 드는 연산들을 덜 비용이 드는 연산들로 다시 작성된다. 예를 들어 3+4는 7로, loop 내에 존재하는 변하지 않는 연산들은 loop 밖으로 옮겨지고, loop가 병행 처리될 수 있다.

 

Intermediate Code ASTs -> Optimization -> IC ASTs

 

### Code generation

중간 코드를 타겟 코드로 변환한다. 이 과정에서 레지스터 할당, 명령어 선택, 명령어 스케줄링, 특정 머신에 맞는 Optimization 등이 이루어진다.

 

언어를 기술하기 위해서는 1) 구문과 2) 의미론이 필요하다. 문법은 어떤 sequences of characters가 legal한 지의 여부를 말하고, 의미론은 어떤 프로그램이 의미하는 바가 무엇인지에 대한 것이다.

 

# 컴파일러와 인터프리터

컴파일러와 인터프리터의 차이는 무엇일까? 인터프리터는 위의 컴파일 과정에서 일반적으로 백엔드 부분이 Evaluation 혹은 Execution으로 대체된다. 즉 소스코드 문자열을 받아서 lexing하여 token을 내보내고, token을 parsing하여 AST를 내보내고, 이 AST를 Evaluation하는 것이 인터프리터이다.

 

좀 더 차이점을 나열해보면,

 

컴파일러는,

1. 프로그램을 분석, 처리하는 데에 상대적으로 많은 시간 소비(대신 일단 컴파일되면 그 이후에는 상대적으로 빠르게 실행됨)

2. 최종 산출물인 실행 코드가 machine-specific한 바이너리 코드 형태

3. 컴퓨터 하드웨어가 해당 실행 코드를 실행

4. 프로그램 실행이 빠름

 

인터프리터는,

1. 프로그램을 분석, 처리하는 데에 상대적으로 적은 시간 소비

2. 결과 실행 코드가 중간 코드(intermediate code) 형태

3. 결과 실행 코드가 다른 프로그램(== 인터프리터)에 의해 interpret됨

4. 프로그램 실행이 상대적으로 느림.

댓글