;;; Copyright (C) 1989 R. Kent Dybvig ;;; Permission is hereby granted, free of charge, to any person obtaining a ;;; copy of this software and associated documentation files (the "Software"), ;;; to deal in the Software without restriction, including without limitation ;;; the rights to use, copy, modify, merge, publish, distribute, sublicense, ;;; and/or sell copies of the Software, and to permit persons to whom the ;;; Software is furnished to do so, subject to the following conditions: ;;; ;;; The above copyright notice and this permission notice shall be included in ;;; all copies or substantial portions of the Software. ;;; ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ;;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ;;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ;;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ;;; DEALINGS IN THE SOFTWARE. ;;; PCScheme/MacScheme "macro" defined in terms of "syntax-case": (define-syntax macro (lambda (x) (syntax-case x () ((_ name fcn) #'(define-syntax name (lambda (x) (syntax-case x () ((k . stuff) (datum->syntax-object #'k (fcn (syntax-object->datum x))))))))))) ;;; PCScheme/MacScheme "macro" defined in terms of "extend-syntax": ;;; requires (current-expand eps-expand) ;(extend-syntax (macro) ; [(macro name fcn) ; (eval-when (compile load eval) ; (let ([f fcn]) ; (extend-syntax (name) ; [anything ; ((with ([w 'with]) w) ; ([v (f 'anything)]) v)])))]) ;;; The strange expression "(with ([w 'with]) w)" is used to insert the ;;; keyword "with" into the expansion. The "eval-when" in the expansion is ;;; necessary to allow macros defined in a file to be used later in the ;;; file, even if the file is compiled with "compile-file". If it were ;;; left out, the implicit "eval-when" wrapped around the "extend-syntax" ;;; would cause it to be evaluated, but without the enclosing "let" ;;; expression. The enclosing "let" expression is necessary to cause the ;;; function to be evaluated once, which may be important if the function ;;; something other than a simple lambda expression. ;;; PCScheme/MacScheme "macro" defined in terms of "define-syntax-expander": ;;; requires (current-expand eps-expand) ;(extend-syntax (macro) ; [(macro name fcn) ; (define-syntax-expander name ; (let ([f fcn]) ; (lambda (x e) (e (f x) e))))]) ;;; The "eval-when" is not necessary because "define-syntax-expander" ;;; expands into an "eval-when" expression, and the "let" expression is ;;; tucked inside the "define-syntax-expander" expression. ;;; If you want to see the expander generated by either of the above ;;; "extend-syntax" definitions looks like, use "extend-syntax/code" in ;;; place of "extend-syntax": ;;; > (extend-syntax/code (macro) ;;; [(macro name fcn) ;;; (define-syntax-expander name ;;; (let ([f fcn]) ;;; (lambda (x e) (e (f x) e))))]) ;;; ;;; (lambda (x e) ;;; (unless (procedure? e) ;;; (error 'macro "~s is not a procedure" e)) ;;; (e (cond ;;; [(syntax-match? '(macro * *) x) ;;; `(define-syntax-expander ,(cadr x) ;;; (let ([f ,@(cddr x)]) (lambda (x e) (e (f x) e))))] ;;; [else (error 'macro "invalid syntax ~s" x)]) ;;; e))