chibi-scheme
chibi-scheme copied to clipboard
Support SRFI 206
As far as I can tell, the groundwork for what would be needed to support SRFI 206 is already there in the (auto)
magic module. But, despite much poking about in meta-7.scm
, I can’t work out how to implement define-auxiliary-syntax
itself.
(define-auxiliary-syntax foo bar)
in definition context should be equivalent to an import like (import (rename (only (auto) bar) (bar foo)))
I think. That works in syntax-rules
, at least:
> (import (only (auto) bar))
> (import (rename (only (auto) bar) (bar foo)))
> (define-syntax is-bar
(syntax-rules (bar)
((_ bar) #t)
((_ _) #f)))
> (is-bar bar)
#t
> (is-bar foo)
#t
> (is-bar frotz)
#f
but according to free-identifier=?
from (chibi syntax-case)
, #'foo
and #'bar
are still distinct after doing this. That looks like a separate bug.
The magic happens in the module system itself, not through a primitive like define-auxiliary-syntax
. (auto)
is treated just like a normal library, but in resolve-import
we check for it specially and ensure any new bindings are defined (using eval
).
So you'd have to rely on import
being allowed in a definition context and use something like:
(define-syntax define-auxiliary-syntax
(er-macro-transformer
(lambda (expr rename compare)
;; intentionally not renaming only/auto keywords since currently
;; module names and keywords are not hygienic
`(,(rename 'import)
(rename (only (auto) ,(cadr expr))
(,(cadr expr) ,(car (cddr expr))))))))
Unfortunately, that can’t work in all cases because of internal definitions. Using this definition corrected to the actual syntax of SRFI 206:
(define-library (srfi 206)
(import (scheme base)
(only (meta) repl-import)
(only (chibi) er-macro-transformer))
(export define-auxiliary-syntax)
(begin
(define-syntax define-auxiliary-syntax
(er-macro-transformer
(lambda (expr rename compare)
(let* ((keyword (cadr expr))
(symbol (if (pair? (cddr expr))
(car (cddr expr))
keyword)))
;; intentionally not renaming only/auto keywords since currently
;; module names and keywords are not hygienic
`(,(rename 'repl-import)
(rename (only (auto) ,symbol)
(,symbol ,keyword)))))))))
Then this test fails:
(define-auxiliary-syntax foo)
(define-auxiliary-syntax bar foo)
(define-auxiliary-syntax baz)
(define-syntax is-foo?
(syntax-rules (foo)
((_ foo) #t)
((_ _) #f)))
(is-foo? foo) ;;=> #t (correct)
(is-foo? bar) ;;=> #t (correct)
(is-foo? baz) ;;=> #f (correct)
(let ()
(define-auxiliary-syntax foo baz)
(values (is-foo? foo)
(is-foo? bar))) ;; should be: #f #t
;; actual result: warning about importing an
;; already-used name, then #t #t
(is-foo? foo) ;;=> #t (correct, but probably for the wrong reasons)
Perhaps I’m using the wrong version of import
in the macro expansion, though.
Sorry, in general non-top-level import
isn't really supported. I actually objected to that in the WG1 discussions.
I also don't really see the point of non-top-level aliases (seems to be just asking for confusion) so wasn't much motivated by that aspect of SRFI 206.
FWIW, there is the excellent paper "Extending the Scope of Syntactic Abstraction" by Kent Dybvig and Oscar Waddell ([1]). It shows the power of local modules and local imports and how they can be integrated into Scheme's hygiene system. The discussed module system is compatible with the R[67]RS module system and is implemented in Chez Scheme and Unsyntax.
That said, I agree with Alex that first-class modules and local imports would have been outside the scope of R7RS-small. But with R7RS-large it's a different thing, IMO.
--
[1] - http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.52.1730&rep=rep1&type=pdf