- explicit renaming
- syntax-case
- syntactic closure
R6RS has syntax-case and rumour says R7RS would have explicit renaming. According to this article, if implementations have one of them, then the rest can be implemented atop it. I'm wondering is it really true? Very lame conclusion is true. Because Sagittarius uses kind of syntactic closure and implements both explicit renaming and syntax-case. Now, can it be done in a portable way?
So I've wrote this. It seems this can work most of R6RS implementations except Racket. Though I haven't tested on Larceny, Guile and Vicare yet, they are using either Psyntax or van Tonder expander such as Mosh and IronScheme (Psyntax) or NMosh (van Tonder). So should work.
The basic idea of the implementation is very simple. rename procedure is a simple wrapper of
datum->syntax
. compare is free-identifier=?
. Then wrap the returning form with datum->syntax*
.The initial revision of the Gist used mere
datum->syntax
. This wasn't good enough because the procedure should only accept datum not syntax object. The error was raised by Psyntax implementations and Racket. Then I've been suggested to walk thought the returning form.
@tk_riple (1)renameはマクロ定義環境を参照すると理解してます。で、最初の例でもマクロ定義環境のfooはローカルのfooですよね? (2)erマクロ展開手続きから帰ってきたフォームをwalkして生シンボルをマクロ使用環境のsyntaxに置換するんじゃだめですか?
— Kilo Kawai (@anohana) October 24, 2015
I first thought this won't work because traversing and constructing a new form would return a list not a syntax object. However I was just didn't consider thoroughly. If I use
syntax-case
and quasisyntax
(with-syntax
could also be), then I can construct syntax object containing syntax object renamed by er-macro-transformer
. So I've rewrite the code. Then most of the R6RS implementation seem working. Even Racket seems working if the macro is very simple like the one on the comment.Now, my question is 'Is this R6RS portable?'. R6RS standard libraries 12.2 says:
The distinction between the terms “syntax object” and “wrapped syntax object” is important. For example, when invoked by the expander, a transformer (section 12.3) must accept a wrapped syntax object but may return any syntax object, including an unwrapped syntax object.So transformer *MAY* return unwrapped syntax object. Though what I'm doing is returning wrapped syntax object so should be fine. What I couldn't read is whether or not a syntax object can contain syntax object(s) inserted by other transformer. If this is required feature, then this might be a bug of Racket. Otherwise this is not portable.
I hope it's a bug of Racket, then you (not me) can write an explicit renaming SRFI with sample implementation.
For convenience, embedded source.