-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathanaphora.lisp
168 lines (139 loc) · 6.34 KB
/
anaphora.lisp
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))