[plt-scheme] Macro contracts (feature request)
Macro definitions are often obfuscated by interleaving code to detect
and report errors in the use of the macro. The same can be true of
procedures, but fortunately the contract mechanism lets you write
procedures based on the assumptions stated in a contract. It would be
useful to write macros in a similar way.
For example, if I write the usual swap! macro:
(define-syntax swap!
(syntax-rules ()
((swap! x y)
(let ((tmp y))
(set! y x)
(set! x tmp)))))
I'd like to be able to attach the following contract to the transformer
procedure:
(-> (and/c (syntax/c
(list/c identifier? identifier? identifier?))
(lambda (stx)
(with-syntax (((swap! x y) stx))
(not (bound-identifier=? #'x #'y)))))
(syntax/c any/c))
Ideally, I could write (provide/contract [swap! ---]) with the above
contract. The contract system would, seeing that swap! is a macro,
attach the RHS to the transformer value. But as far as I can tell,
there is no way to do this currently.
I can fake it as follows:
(module m-syntax mzscheme
(require (lib "contract.ss"))
(require-for-template mzscheme)
(provide/contract
[swap!-procedure ;; shape contract for swap!.
(-> (and/c (syntax/c
(list/c identifier? identifier? identifier?))
(lambda (stx)
(with-syntax (((swap! x y) stx))
(not (bound-identifier=? #'x #'y)))))
(syntax/c any/c))])
(define swap!-procedure
(syntax-rules ()
((swap! x y)
(let ((tmp y))
(set! y x)
(set! x tmp))))))
(module m mzscheme
(provide swap!)
(require-for-syntax m-syntax)
(define-syntax swap! swap!-procedure))
But this sort of thing should be easier. Also, this gets the blame
wrong: (swap! x x) will blame m rather than the top-level where the
malformed expression occurs.
David