1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
;;;; -*- Mode: Lisp; Base: 10; Syntax: ANSI-Common-Lisp; Package: ANAPHORA -*-
;;;; Anaphora: The Anaphoric Macro Package from Hell
;;;;
;;;; This been placed in Public Domain by the author,
;;;; Nikodemus Siivola <nikodemus@random-state.net>
(in-package :anaphora)
;;; This was the original implementation of SYMBOLIC -- and still good
;;; for getting the basic idea. Brian Masterbrooks solution to
;;; infinite recusion during macroexpansion, that nested forms of this
;;; are subject to, is in symbolic.lisp.
;;;
;;; (defmacro symbolic (op test &body body &environment env)
;;; `(symbol-macrolet ((it ,test))
;;; (,op it ,@body)))
(defmacro alet (form &body body)
"Binds the FORM to IT (via LET) in the scope of the BODY."
`(anaphoric ignore-first ,form (progn ,@body)))
(defmacro slet (form &body body)
"Binds the FORM to IT (via SYMBOL-MACROLET) in the scope of the BODY. IT can
be set with SETF."
`(symbolic ignore-first ,form (progn ,@body)))
(defmacro aand (first &rest rest)
"Like AND, except binds the first argument to IT (via LET) for the
scope of the rest of the arguments."
`(anaphoric and ,first ,@rest))
(defmacro sor (first &rest rest)
"Like OR, except binds the first argument to IT (via SYMBOL-MACROLET) for
the scope of the rest of the arguments. IT can be set with SETF."
`(symbolic or ,first ,@rest))
(defmacro aif (test then &optional else)
"Like IF, except binds the result of the test to IT (via LET) for
the scope of the then and else expressions."
`(anaphoric if ,test ,then ,else))
(defmacro sif (test then &optional else)
"Like IF, except binds the test form to IT (via SYMBOL-MACROLET) for
the scope of the then and else expressions. IT can be set with SETF"
`(symbolic if ,test ,then ,else))
(defmacro asif (test then &optional else)
"Like IF, except binds the result of the test to IT (via LET) for
the the scope of the then-expression, and the test form to IT (via
SYMBOL-MACROLET) for the scope of the else-expression. Within scope of
the else-expression, IT can be set with SETF."
`(let ((it ,test))
(if it
,then
(symbolic ignore-first ,test ,else))))
(defmacro aprog1 (first &body rest)
"Binds IT to the first form so that it can be used in the rest of the
forms. The whole thing returns IT."
`(anaphoric prog1 ,first ,@rest))
(defmacro awhen (test &body body)
"Like WHEN, except binds the result of the test to IT (via LET) for the scope
of the body."
`(anaphoric when ,test ,@body))
(defmacro swhen (test &body body)
"Like WHEN, except binds the test form to IT (via SYMBOL-MACROLET) for the
scope of the body. IT can be set with SETF."
`(symbolic when ,test ,@body))
(defmacro sunless (test &body body)
"Like UNLESS, except binds the test form to IT (via SYMBOL-MACROLET) for the
scope of the body. IT can be set with SETF."
`(symbolic unless ,test ,@body))
(defmacro acase (keyform &body cases)
"Like CASE, except binds the result of the keyform to IT (via LET) for the
scope of the cases."
`(anaphoric case ,keyform ,@cases))
(defmacro scase (keyform &body cases)
"Like CASE, except binds the keyform to IT (via SYMBOL-MACROLET) for the
scope of the body. IT can be set with SETF."
`(symbolic case ,keyform ,@cases))
(defmacro aecase (keyform &body cases)
"Like ECASE, except binds the result of the keyform to IT (via LET) for the
scope of the cases."
`(anaphoric ecase ,keyform ,@cases))
(defmacro secase (keyform &body cases)
"Like ECASE, except binds the keyform to IT (via SYMBOL-MACROLET) for the
scope of the cases. IT can be set with SETF."
`(symbolic ecase ,keyform ,@cases))
(defmacro accase (keyform &body cases)
"Like CCASE, except binds the result of the keyform to IT (via LET) for the
scope of the cases. Unlike CCASE, the keyform/place doesn't receive new values
possibly stored with STORE-VALUE restart; the new value is received by IT."
`(anaphoric ccase ,keyform ,@cases))
(defmacro sccase (keyform &body cases)
"Like CCASE, except binds the keyform to IT (via SYMBOL-MACROLET) for the
scope of the cases. IT can be set with SETF."
`(symbolic ccase ,keyform ,@cases))
(defmacro atypecase (keyform &body cases)
"Like TYPECASE, except binds the result of the keyform to IT (via LET) for
the scope of the cases."
`(anaphoric typecase ,keyform ,@cases))
(defmacro stypecase (keyform &body cases)
"Like TYPECASE, except binds the keyform to IT (via SYMBOL-MACROLET) for the
scope of the cases. IT can be set with SETF."
`(symbolic typecase ,keyform ,@cases))
(defmacro aetypecase (keyform &body cases)
"Like ETYPECASE, except binds the result of the keyform to IT (via LET) for
the scope of the cases."
`(anaphoric etypecase ,keyform ,@cases))
(defmacro setypecase (keyform &body cases)
"Like ETYPECASE, except binds the keyform to IT (via SYMBOL-MACROLET) for
the scope of the cases. IT can be set with SETF."
`(symbolic etypecase ,keyform ,@cases))
(defmacro actypecase (keyform &body cases)
"Like CTYPECASE, except binds the result of the keyform to IT (via LET) for
the scope of the cases. Unlike CTYPECASE, new values possible stored by the
STORE-VALUE restart are not received by the keyform/place, but by IT."
`(anaphoric ctypecase ,keyform ,@cases))
(defmacro sctypecase (keyform &body cases)
"Like CTYPECASE, except binds the keyform to IT (via SYMBOL-MACROLET) for
the scope of the cases. IT can be set with SETF."
`(symbolic ctypecase ,keyform ,@cases))
(defmacro acond (&body clauses)
"Like COND, except result of each test-form is bound to IT (via LET) for the
scope of the corresponding clause."
(labels ((rec (clauses)
(if clauses
(destructuring-bind ((test &body body) . rest) clauses
(if body
`(anaphoric if ,test (progn ,@body) ,(rec rest))
`(anaphoric if ,test it ,(rec rest))))
nil)))
(rec clauses)))
(defmacro scond (&body clauses)
"Like COND, except each test-form is bound to IT (via SYMBOL-MACROLET) for the
scope of the corresponsing clause. IT can be set with SETF."
(labels ((rec (clauses)
(if clauses
(destructuring-bind ((test &body body) . rest) clauses
(if body
`(symbolic if ,test (progn ,@body) ,(rec rest))
`(symbolic if ,test it ,(rec rest))))
nil)))
(rec clauses)))
(defmacro alambda (lambda-list &body body)
"Like LAMBDA, except that SELF is bound to the resulting function (via LABELS)
within BODY."
`(labels ((self ,lambda-list ,@body))
#'self))
|