LISP 구현하기 – MACRO

진행 중인 Go로 LISP 구현하기 개인 프로젝트(링크)에, “MACRO Definitions for LISP”을 참고하여 MACRO를 구현했다.

이 문서에는 LISP 1.5를 기준으로 MACRO를 도입한 새로운 interpreter를 M-expression으로 상세히 기술되어 있다. 다만 LISP 1.5의 시스템 정의를 조금 알아야 문서를 읽을 수 있어서, “LISP 1.5 Programmer’s Manual”도 같이 봐야 했다.

MACRO definitions for LISP

LISP 1.5에는 Symbol마다 Property list라는 것이 있다. Property list에는 indicator와 value의 쌍이 이어진다. indicator중에서 EXPR이라는 것이 사용자 정의 함수이다. DEFINE 함수로 정의할 수 있다.

DEFINE ( (
(FOO) (LAMBDA (X) ...)
))

동일한 문법을 사용하되, MACRO 함수를 이용하면 MACRO라는 indicator로 해당 함수 정의를 저장해 놓는다. DEFINE 함수와 형태가 일치하므로 내부적으로는 deflist[l;ind]를 이용하여 구현된다. (l은 정의 리스트, ind는 indicator) 즉, define[l] => deflist[l;EXPR]. macro[l] => deflist[l;MACRO]이다.

MACRO ( (
(M1) (LAMBDA (FORM) ...)
))

사용자로부터 식을 읽어들일때마다 매크로를 적용하여 form을 확장(expand)하는 것으로 구현할 수 있다.

구현하기

LISP 1.5는 기본적으로 입력 내용을 함수와 인자리스트형태로 받아서 evalquote[f;a]로 넘긴다. 그래서 Scheme과는 다른 위와 같은 모양이 나오는 것이다. Micro Manual For LISP을 보면, (defun …)형태로 사용자 함수를 정의하는 방식이 소개되므로, 이 방식을 매크로 정의에 사용하면 (defmacro …)형태로 매크로를 정의하도록 할 수 있다.

(defmacro select (form)
  ( (lambda (symbol) (list (list 'lambda (list symbol)
    (cons 'cond
      (maplist (cddr form)
        (function (lambda (l) (cond
            ( (null (cdr l))
              (list 'T (car l)))
            (T
              (list (list 'equal symbol (caar l)) (cadar l))))))))) (cadr form)))
   (gensym)))

문서의 끝에 나온 select 구현을 충실히 옮기면 위와 같다. 아직 quasiquote, unquote 등이 도입되기 전이라 읽기가 상당히 어렵다. 그 필요성을 바로 알 수 있다.

LISP 1.5에는 Symbol마다 Property List가 있지만, symbol->value 사전 형태의 구현에서는 EXPR 사전과 MACRO 사전을 따로 관리해야 하는 문제가 있다. 우선은 indicator에 해당하는 내용을 Symbol에 덧붙여서 저장하고 불러오는 방법으로 같은 효과를 얻을 수 있다.

Related Posts

About jooyunghan

한주영
This entry was posted in 기타 and tagged . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>