ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 컴파일러 언어vs 인터프리터 언어
    Computer Science 2021. 5. 9. 22:00

     

    컴파일 언어와 인터프리터 언어는 컴파일 타임이 있느냐 없느냐 즉, 소스 코드를 분석하는 시점과 입력 데이터를 받는 시점이 언제이냐에 따라 나뉜다. 이 문장만으로는 명확히 이해되지 않으니 C와 파이썬을 예로 들어보자.

     

     

    C언어 : 컴파일러 분석 언어

     

    소스코드에서 실행까지(C 언어)

     

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

     

     

    파이썬 : 인터프리터 언어 분석

     

    컴파일 되어 실행되는 과정( 파이썬 )

     

    파이썬도 소스 코드가 있으므로 이를 분석하는 컴파일러가 있다. 목적 코드로 기계어를 생성하는 C 언어와 달리 파이썬은 바이트 코드(byte code)를 생성한다. 바이트 코드가 생성된 후에는 PVM(Python Virtual Machine)에서 바이트 코드를 하나씩 해석하여 프로그램을 실행한다. 이러한 이유로 PVM을 파이썬 인터프리터라고 부르기도 한다. 중요한 점은 소스 코드를 분석하는 컴파일 타임이 따로 없고 실행과 동시에 분석을 시작한다는 점이다. 즉, 소스 코드와 입력 데이터가 같은 시점에 삽입된다.

     

     

    파이썬 : 소스 코드부터 실행까지

    컴파일러

    일반적인 컴파일러는 렉서(lexer)와 파서(parser)로 구성된다. 소스 코드가 렉서와 파서에 의해 어떻게 변하는지 알아보자.

     

    컴파일러의 구성

     

    위의 그림에서 렉서에 입력되는 것은 소스 코드이다. 소스 코드도 결국에는 문자에 불과하다. 이 문자들이 렉서를 거치면서 여러 개의 토큰(token)으로 변경된다.

     

    토큰이란, 예를 들어 "나는 사과를 먹었다"라는 문장이 있다면, 이 문장은 주어("나는"), 목적어("사과를"), 동사("먹었다")로 나눌 수 있다. 문장을 종류별로 쪼갠 후 종류와 문자를 함께 나타낸 것을 토큰이라고 한다. 위 문장을 토큰으로 나타내면 <주어, "나는">,<목적어, "사과를">,<동사, "먹었다"> 총 세 개의 토큰으로 나타낼 수 있다.

    프로그래밍 언어도 언어의 문법에 맞게 토큰으로 쪼갤 수 있다. 종류에는 변수나 함수 이름을 의미하는 식별자, for while if elif 같은 키워드, 1 2 3 'a' 'b' 같은 상수, + - * / 같은 연산자 등이 있다.

     

    파서는 토큰을 분석하여 분석 트리(parse tree)를 구성한다. 컴파일러마다 분석 트리를 생성하기도 하고 생성하지 않기도 한다. 분석 트리가 만들어지면 이를 이용해 목적 코드(C언어는 기계어, 파이썬은 바이트 코드)를 생성한다. 이를 코드 생성(code generation)이라고 한다.

     

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

    1. 소스코드 -> 분석 트리

    2. 분석트리 -> 추상 구문 트리

    3. 심벌 테이블 생성

    4. 추상 구문 트리 -> 바이트 코드

     

    예제를 통해 이 코드가 컴파일러를 거쳐 바이트 코드로 바뀐 후 PVM에서 작동하는 과정을 따라가 보자.

     

    def func(a, b):
        return a + b
    
    a = 10
    b = 20
    
    c = func(a,b)
    print(c)

     

    위의 코드는 매우 간단하다. 두 인자를 더한 값을 반환하는 함수 func()와 두 전역 변수 a, b가 있고 a와 b를 인자로 받아 func()를 호출한다음에 c에 그 값을 저장하고 이를 print() 함수로 출력한다. 실행하면 가장 먼저 컴파일러의 렉서가 코드의 문자들을 토큰으로 바꿀 것이다. 

     

     

    tokenize 모듈을 이용해 소스 코드를 여러 개의 토큰으로 쪼갠 다음 토큰을 출력하였다. 토큰을 출력해보면 타입과 실제 문자열, 시작 위치와 끝 등의 정보를 알 수 있다. 이렇게 얻어진 토큰으로 분석 트리를 만든 다음 추상 구문 트리로 변형한다.

     

     

    추상 구문 트리

    추상 구문 트리(Abstract Syntax Tree, AST)란 소스 코드의 구조를 나타내는 자료 구조다. AST를 바탕으로 심벌 테이블을 만들고 바이트 코드를 생성할 수 있다. 

     

     

    노드를 생성하고 ast.walk() 함수를 사용하면 트리의 모든 노드를 순회할 수 있는 발생자 객체를 얻을 수 있다.

    발생자(generator)는 함수를 실행 도중에 멈췄다가 원하는 시점에 다시 시작할 수 있도록 하는 함수다. (walk()함수를 통해 만들어진 발생자 객체는 next() 함수를 호출할 때마다 노드를 하나씩 넘겨준다.) 

     

    이렇게 봐서는 트리의 구성을 파악하기 어렵기 때문에 함수 func()의 정의 부분만 따로 떼어낸 트리 구성을 살펴보자.

     

    def func(a, b):
        return a+b

     

    위의 코드의 추상 구문 트르리를 그림으로 나타내면 아래의 그림과 같다.

     

    함수 func의 추상 구문 트리

     

    인자(arguments)는 a와 b고, 변수 이름 a와 b 값을 불러와(load) 이진 연산자(BinOp, binary operator)와 +(Add)로 연산한 다음 반환(return)한다.

    이번에는 func()의 반환 값을 c에 저장하는 코드의 추상 구문 트리를 살펴보자

     

    c = func(a,b)

     

     

    함수 호출 부분의 추상 구문 트리

     

    아래의 사진은 파일(test.py) 전체 코드의 AST를 나타낸 것이다.

     

     

    심벌 테이블

    심벌 테이블(sysbol table)은 변수나 함수의 이름과 그 속성에 대해 기술해 높은 테이블이다.

    test.py를 보면 전역 영역(global)에 변수 a, b, c와 함수 func, print가 있는 것을 알 수 있다. 

     

     

    symtable() 함수를 이용해 테이블을 받아오고 이름을 확인한다. 이름이 'top'이라고 나오는데 이는 이 테이블이 글로벌 테이블이라는 의미다. 클래스 테이블이면 클래스 이름이 나오고, 함수 테이블이면 함수 이름이 나온다. 다음으로 get_symbols() 함수로 현재 영역에 있는 심볼을 확인할 수 있다. 

     

     

    바이트 코드와 PVM

    마지막 단계로 바이트 코드를 생성할 차례다. 

     

     

    모듈 dis를 불러온 다음 get_instruction() 함수를 통해 바이트 코드를 제공하는 발생자를 만든다. 바이트 코드 이름과 인자 값을 출력해 보면 어셈블리어와는 다른 파이썬의 바이트 코드 인스트럭션을 확인할 수 있다.

     

    바이트 코드는 파이썬의 가상 머신 위에서 실행된다. 파이썬의 가상 머신인 PVM은 그저 굉장히 큰 무한 루프이다.

     

     

    출처:파이썬 컴퓨터 사이언스 부트캠프

    'Computer Science' 카테고리의 다른 글

    프로그래밍 기법과 패러다임 종류  (0) 2021.10.30
    컴퓨터의 동작 원리  (0) 2021.10.28
    Home server  (0) 2021.04.10
    문자와 문자열  (0) 2021.03.03
    실수  (0) 2021.03.03
Designed by Tistory.