syntax-case自体はコンパイラとは関係ない(ないことはないが)、ライブラリとする。
define-syntaxで定義された構文は変換器を返し、変換器が変換する。
(Gaucheはそうしてると思う。ソース見る限り・・・今のところsyntax-rules限定っぽいけど)
define-syntaxで定義された構文にS式が与えられた場合、構文オブジェクトとしてすべての引数を与える。
こんな感じ?
(define-syntax sample
(lambda (x)
(syntax-case x ()
....)))
(sample 1 2 3) ;; <- この1 2 3っていうのがsyntax-caseによって処理されるために構文オブジェクトになる
ということは、マクロを展開する際に、S式をいったん構文オブジェクトにする必要がありそう。
これで、syntax-caseを定義するとすると
(define-syntax syntax-case
(lambda (x)
... ;; いろいろ定義がいりそう?
;; x は構文オブジェクト。matchはAndrew Wrightみたいなの(構文オブジェクトにも対応)
(match x
((_ e ((? literal? literals) ...) clauses ...)
...)))) ;; きっといろいろする
っで、こいつ自体が変換器なので、syntax-rulesはこう書いて
(define-syntax with-syntax
(lambda (x)
(syntax-case x ()
((_ () e1 e2 ...) (syntax (begin e1 e2 ...)))
((_ ((out in)) e1 e2 ...) (syntax (syntax-case in ()
(out (begin e1 e2 ...)))))
((_ ((out in) ...) e1 e2 ...) (syntax (syntax-case (list in ...) ()
((out ...) (begin e1 e2 ...))))))))
(define-syntax syntax-rules
(lambda (x)
(define clause
(lambda (y)
(syntax-case y ()
(((keyword . pattern) template)
(syntax ((dummy . pattern) (syntax template))))
(_
(syntax-violation 'syntax-rules "Invalid expression" x)))))
(syntax-case x ()
((_ (k ...) cl ...)
(for-all identifier? (syntax (k ...)))
(with-syntax (((cl ...) (map clause (syntax (cl ...)))))
(syntax
(lambda (x) (syntax-case x (k ...) cl ...))))))))
syntax-rulesで定義された構文は
構文 -> syntax-rules変換器 -> syntax-case変換器 -> ごにょごにょ
という感じになるはず。
こんなのは
(define-syntax print
(syntax-rules ()
((_ o)
(begin (display o) (newline)))
((_ o1 o2 ...)
(begin
(display o1)(newline)
(print o2 ...)))))
(print 1 2)
こうなる?(print 1 2) -> (transformer syntax-rules '(syntax-object (print 1 2)))
: with-syntaxは略
-> (transformer syntax-case '(syntax-object ...#;多分この辺にsyntax-rulesで作られたtempleteが入る (print 1 2)))
正しいのかよくわからん。その上、どう実装していいのかもよくわからん・・・
No comments:
Post a Comment