伝統的なmacroの実装に向けて
私がRubyで書いているLisp方言、 [Nendo]の開発状況続き。
macroの実装方法調査中。 とにかくmacro機能が無いと何も実用的な構文は何も定義できないということを今になって痛感。(遅すぎ) 逆にmacro機能さえ有れば速度さえ気に為なければいくらでも必要な構文が量産定義できるのだった。 最近、 On Lisp
そんなこんなで、Rubyのライブラリを呼びだすという楽しい部分は後回しにしたい。
TinyScheme 1.39のソースコード(init.scm)に含まれるこのquasiquoteが動くとうれしい。というのも、こんな複雑な処理を自分で書くのは骨が折れるので割愛したい。 これくらい自分で書かないと行けないのかなとも思うけど。
しかし、これを動かそうとするだけでもapply とか eqv? とか色々足りない関数が有る。 しかも、condが使われているのでそのまま動かそうとするとcondをRubyで実装するしか無いのかだろうか。
いろいろ手は有るけど、このうちどの案にしようか。
quasiquoteの定義中でcondを使っている箇所をifに書きなおす(Lisperらしくないかも!)
condをビルトインにする(Rubyで実装する)
condをquasiquote無しでmacro定義する
動作速度にこだわらないToy言語ということで、3番が有力かなぁ。
;; The following quasiquote macro is due to Eric S. Tiedemann.
;; Copyright 1988 by Eric S. Tiedemann; all rights reserved.
;;
;; Subsequently modified to handle vectors: D. Souflis
(macro
quasiquote
(lambda (l)
(define (mcons f l r)
(if (and (pair? r)
(eq? (car r) 'quote)
(eq? (car (cdr r)) (cdr f))
(pair? l)
(eq? (car l) 'quote)
(eq? (car (cdr l)) (car f)))
(if (or (procedure? f) (number? f) (string? f))
f
(list 'quote f))
(if (eqv? l vector)
(apply l (eval r))
(list 'cons l r)
)))
(define (mappend f l r)
(if (or (null? (cdr f))
(and (pair? r)
(eq? (car r) 'quote)
(eq? (car (cdr r)) '())))
l
(list 'append l r)))
(define (foo level form)
(cond ((not (pair? form))
(if (or (procedure? form) (number? form) (string? form))
form
(list 'quote form))
)
((eq? 'quasiquote (car form))
(mcons form ''quasiquote (foo (+ level 1) (cdr form))))
(#t (if (zero? level)
(cond ((eq? (car form) 'unquote) (car (cdr form)))
((eq? (car form) 'unquote-splicing)
(error "Unquote-splicing wasn't in a list:"
form))
((and (pair? (car form))
(eq? (car (car form)) 'unquote-splicing))
(mappend form (car (cdr (car form)))
(foo level (cdr form))))
(#t (mcons form (foo level (car form))
(foo level (cdr form)))))
(cond ((eq? (car form) 'unquote)
(mcons form ''unquote (foo (- level 1)
(cdr form))))
((eq? (car form) 'unquote-splicing)
(mcons form ''unquote-splicing
(foo (- level 1) (cdr form))))
(#t (mcons form (foo level (car form))
(foo level (cdr form)))))))))
(foo 0 (car (cdr l)))))
macroが動いたら玩具Toy言語といえどももかなり遊べる様になるな。楽しみ^_^
P.S. ちなみにchibi-schemeは伝統的macroではなくdefine-syntaxでquasiquoteを実 現しているが、define-syntaxの実装は難しそうなのでnendoではパスするつも り。