;; Defines macros, the declarations can have `keyword: ' to ;; specify keywords in the resulting macro, and `capture: ' to ;; specify names that are inserted unhygienically. See examples ;; below. (define-syntax defmac (syntax-rules () [(defmac (name . xs) decl ... body) (defmac-decls name xs (decl ...) () () body)])) ;; helper for defmac -- collects keyword & capture declarations (define-syntax defmac-decls (syntax-rules (keyword: capture:) [(defmac-decls name xs (keyword: key* more ...) (key ...) caps body) (defmac-decls name xs (more ...) (key ... key*) caps body)] [(defmac-decls name xs (capture: cap* more ...) keys (cap ...) body) (defmac-decls name xs (more ...) keys (cap ... cap*) body)] [(defmac-decls name xs () (key ...) (cap ...) body) (define-syntax (name stx) (syntax-case stx (key ...) [(name . xs) (with-syntax ([cap (datum->syntax-object stx 'cap stx)] ...) (syntax body))]))])) ;; Examples... ;; usual hygiene (defmac (orelse x y) (let ([tmp x]) (if tmp tmp y))) ;; works fine: (let ((tmp 123)) (orelse #f tmp)) ;; make it capture `tmp' (defmac (orelse x y) capture: tmp (let ([tmp x]) (if tmp tmp y))) ;; this expands to (let ((tmp 123)) (let ((tmp #f)) (if tmp tmp tmp))) (let ((tmp 123)) (orelse #f tmp)) ;; anaphoric if (defmac (aif cond then else) capture: it (let ([it cond]) (if it then else))) (aif (+ 1 2) it 3) ;; nested is ok (aif (aif (+ 1 2) it 3) (aif (+ 4 5) it 6) 7)