1 | ;;; setf.lisp |
---|
2 | ;;; |
---|
3 | ;;; Copyright (C) 2003 Peter Graves |
---|
4 | ;;; $Id: setf.lisp,v 1.32 2003-10-01 21:46:59 piso Exp $ |
---|
5 | ;;; |
---|
6 | ;;; This program is free software; you can redistribute it and/or |
---|
7 | ;;; modify it under the terms of the GNU General Public License |
---|
8 | ;;; as published by the Free Software Foundation; either version 2 |
---|
9 | ;;; of the License, or (at your option) any later version. |
---|
10 | ;;; |
---|
11 | ;;; This program is distributed in the hope that it will be useful, |
---|
12 | ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
14 | ;;; GNU General Public License for more details. |
---|
15 | ;;; |
---|
16 | ;;; You should have received a copy of the GNU General Public License |
---|
17 | ;;; along with this program; if not, write to the Free Software |
---|
18 | ;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
---|
19 | |
---|
20 | (in-package "SYSTEM") |
---|
21 | |
---|
22 | (defun get-setf-method-inverse (form inverse setf-function) |
---|
23 | (let ((new-var (gensym)) |
---|
24 | (vars nil) |
---|
25 | (vals nil)) |
---|
26 | (dolist (x (cdr form)) |
---|
27 | (push (gensym) vars) |
---|
28 | (push x vals)) |
---|
29 | (setq vals (nreverse vals)) |
---|
30 | (values vars vals (list new-var) |
---|
31 | (if setf-function |
---|
32 | `(,@inverse ,new-var ,@vars) |
---|
33 | `(,@inverse ,@vars ,new-var)) |
---|
34 | `(,(car form) ,@vars)))) |
---|
35 | |
---|
36 | ;;; If a macro, expand one level and try again. If not, go for the |
---|
37 | ;;; SETF function. |
---|
38 | (defun expand-or-get-setf-inverse (form environment) |
---|
39 | (multiple-value-bind |
---|
40 | (expansion expanded) |
---|
41 | (macroexpand-1 form environment) |
---|
42 | (if expanded |
---|
43 | (get-setf-expansion expansion environment) |
---|
44 | (get-setf-method-inverse form `(funcall #'(setf ,(car form))) |
---|
45 | t)))) |
---|
46 | |
---|
47 | (defun get-setf-expansion (form &optional environment) |
---|
48 | (let (temp) |
---|
49 | (cond ((symbolp form) |
---|
50 | (let ((new-var (gensym))) |
---|
51 | (values nil nil (list new-var) |
---|
52 | `(setq ,form ,new-var) form))) |
---|
53 | ((setq temp (get (car form) 'setf-inverse)) |
---|
54 | (get-setf-method-inverse form `(,temp) nil)) |
---|
55 | ((setq temp (get (car form) 'setf-expander)) |
---|
56 | (funcall temp form environment)) |
---|
57 | (t |
---|
58 | (expand-or-get-setf-inverse form environment))))) |
---|
59 | |
---|
60 | ;;; ROTATEF (from GCL) |
---|
61 | (defmacro rotatef (&rest rest) |
---|
62 | (do ((r rest (cdr r)) |
---|
63 | (pairs nil) |
---|
64 | (stores nil) |
---|
65 | (store-forms nil) |
---|
66 | (access-forms nil)) |
---|
67 | ((endp r) |
---|
68 | (setq stores (nreverse stores)) |
---|
69 | (setq store-forms (nreverse store-forms)) |
---|
70 | (setq access-forms (nreverse access-forms)) |
---|
71 | `(let* ,(nconc pairs |
---|
72 | (mapcar #'list stores (cdr access-forms)) |
---|
73 | (list (list (car (last stores)) (car access-forms)))) |
---|
74 | ,@store-forms |
---|
75 | nil)) |
---|
76 | (multiple-value-bind (vars vals stores1 store-form access-form) |
---|
77 | (get-setf-expansion (car r)) |
---|
78 | (setq pairs (nconc pairs (mapcar #'list vars vals))) |
---|
79 | (setq stores (cons (car stores1) stores)) |
---|
80 | (setq store-forms (cons store-form store-forms)) |
---|
81 | (setq access-forms (cons access-form access-forms))))) |
---|
82 | |
---|
83 | |
---|
84 | (defmacro setf (&rest args) |
---|
85 | (let ((count (length args))) |
---|
86 | (cond |
---|
87 | ((= count 2) |
---|
88 | (let ((place (first args)) |
---|
89 | (value-form (second args))) |
---|
90 | (if (atom place) |
---|
91 | `(setq ,place ,value-form) |
---|
92 | (multiple-value-bind (dummies vals newval setter getter) |
---|
93 | (get-setf-expansion place nil) |
---|
94 | (let ((inverse (get (car place) 'setf-inverse))) |
---|
95 | (if (and inverse (eq inverse (car setter))) |
---|
96 | (if (functionp inverse) |
---|
97 | `(funcall ,inverse ,@(cdr place) ,value-form) |
---|
98 | `(,inverse ,@(cdr place) ,value-form)) |
---|
99 | `(let* (,@(mapcar #'list dummies vals)) |
---|
100 | (multiple-value-bind ,newval ,value-form |
---|
101 | ,setter)))))))) |
---|
102 | ((oddp count) |
---|
103 | (error "odd number of args to SETF")) |
---|
104 | (t |
---|
105 | (do ((a args (cddr a)) (l nil)) |
---|
106 | ((null a) `(progn ,@(nreverse l))) |
---|
107 | (setq l (cons (list 'setf (car a) (cadr a)) l))))))) |
---|
108 | |
---|
109 | (defmacro incf (place &optional (delta 1)) |
---|
110 | `(setf ,place (+ ,place ,delta))) |
---|
111 | |
---|
112 | (defmacro decf (place &optional (delta 1)) |
---|
113 | `(setf ,place (- ,place ,delta))) |
---|
114 | |
---|
115 | (defun fdefinition (name) |
---|
116 | (cond ((symbolp name) |
---|
117 | (symbol-function name)) |
---|
118 | ((and (consp name) (eq (car name) 'setf)) |
---|
119 | (or (get (cadr name) 'setf-function) (error 'undefined-function))) |
---|
120 | (t (error 'type-error)))) |
---|
121 | |
---|
122 | (defun %set-fdefinition (name function) |
---|
123 | (cond ((symbolp name) |
---|
124 | (fset name function)) |
---|
125 | ((and (consp name) (eq (car name) 'setf)) |
---|
126 | (%put (cadr name) 'setf-function function)) |
---|
127 | (t (error 'type-error)))) |
---|
128 | |
---|
129 | ;; (defsetf subseq (sequence start &optional (end nil)) (v) |
---|
130 | ;; `(progn (replace ,sequence ,v :start1 ,start :end1 ,end) |
---|
131 | ;; ,v)) |
---|
132 | (defun %set-subseq (sequence start &rest rest) |
---|
133 | (let ((end nil) v) |
---|
134 | (ecase (length rest) |
---|
135 | (1 |
---|
136 | (setq v (car rest))) |
---|
137 | (2 |
---|
138 | (setq end (car rest) |
---|
139 | v (cadr rest)))) |
---|
140 | (progn |
---|
141 | (replace sequence v :start1 start :end1 end) |
---|
142 | v))) |
---|
143 | |
---|
144 | (defmacro defsetf (access-function update-function) |
---|
145 | `(%put ',access-function 'setf-inverse ',update-function)) |
---|
146 | |
---|
147 | (defun %set-caar (x v) (%rplaca (car x) v)) |
---|
148 | (defun %set-cadr (x v) (%rplaca (cdr x) v)) |
---|
149 | (defun %set-cdar (x v) (%rplacd (car x) v)) |
---|
150 | (defun %set-cddr (x v) (%rplacd (cdr x) v)) |
---|
151 | (defun %set-caaar (x v) (%rplaca (caar x) v)) |
---|
152 | (defun %set-cadar (x v) (%rplaca (cdar x) v)) |
---|
153 | (defun %set-cdaar (x v) (%rplacd (caar x) v)) |
---|
154 | (defun %set-cddar (x v) (%rplacd (cdar x) v)) |
---|
155 | (defun %set-caadr (x v) (%rplaca (cadr x) v)) |
---|
156 | (defun %set-caddr (x v) (%rplaca (cddr x) v)) |
---|
157 | (defun %set-cdadr (x v) (%rplacd (cadr x) v)) |
---|
158 | (defun %set-cdddr (x v) (%rplacd (cddr x) v)) |
---|
159 | (defun %set-caaaar (x v) (%rplaca (caaar x) v)) |
---|
160 | (defun %set-cadaar (x v) (%rplaca (cdaar x) v)) |
---|
161 | (defun %set-cdaaar (x v) (%rplacd (caaar x) v)) |
---|
162 | (defun %set-cddaar (x v) (%rplacd (cdaar x) v)) |
---|
163 | (defun %set-caadar (x v) (%rplaca (cadar x) v)) |
---|
164 | (defun %set-caddar (x v) (%rplaca (cddar x) v)) |
---|
165 | (defun %set-cdadar (x v) (%rplacd (cadar x) v)) |
---|
166 | (defun %set-cdddar (x v) (%rplacd (cddar x) v)) |
---|
167 | (defun %set-caaadr (x v) (%rplaca (caadr x) v)) |
---|
168 | (defun %set-cadadr (x v) (%rplaca (cdadr x) v)) |
---|
169 | (defun %set-cdaadr (x v) (%rplacd (caadr x) v)) |
---|
170 | (defun %set-cddadr (x v) (%rplacd (cdadr x) v)) |
---|
171 | (defun %set-caaddr (x v) (%rplaca (caddr x) v)) |
---|
172 | (defun %set-cadddr (x v) (%rplaca (cdddr x) v)) |
---|
173 | (defun %set-cdaddr (x v) (%rplacd (caddr x) v)) |
---|
174 | (defun %set-cddddr (x v) (%rplacd (cdddr x) v)) |
---|
175 | |
---|
176 | (defsetf car %rplaca) |
---|
177 | (defsetf cdr %rplacd) |
---|
178 | (defsetf caar %set-caar) |
---|
179 | (defsetf cadr %set-cadr) |
---|
180 | (defsetf cdar %set-cdar) |
---|
181 | (defsetf cddr %set-cddr) |
---|
182 | (defsetf caaar %set-caaar) |
---|
183 | (defsetf cadar %set-cadar) |
---|
184 | (defsetf cdaar %set-cdaar) |
---|
185 | (defsetf cddar %set-cddar) |
---|
186 | (defsetf caadr %set-caadr) |
---|
187 | (defsetf caddr %set-caddr) |
---|
188 | (defsetf cdadr %set-cdadr) |
---|
189 | (defsetf cdddr %set-cdddr) |
---|
190 | (defsetf caaaar %set-caaaar) |
---|
191 | (defsetf cadaar %set-cadaar) |
---|
192 | (defsetf cdaaar %set-cdaaar) |
---|
193 | (defsetf cddaar %set-cddaar) |
---|
194 | (defsetf caadar %set-caadar) |
---|
195 | (defsetf caddar %set-caddar) |
---|
196 | (defsetf cdadar %set-cdadar) |
---|
197 | (defsetf cdddar %set-cdddar) |
---|
198 | (defsetf caaadr %set-caaadr) |
---|
199 | (defsetf cadadr %set-cadadr) |
---|
200 | (defsetf cdaadr %set-cdaadr) |
---|
201 | (defsetf cddadr %set-cddadr) |
---|
202 | (defsetf caaddr %set-caaddr) |
---|
203 | (defsetf cadddr %set-cadddr) |
---|
204 | (defsetf cdaddr %set-cdaddr) |
---|
205 | (defsetf cddddr %set-cddddr) |
---|
206 | |
---|
207 | (defsetf first %rplaca) |
---|
208 | (defsetf second %set-cadr) |
---|
209 | (defsetf third %set-caddr) |
---|
210 | (defsetf fourth %set-cadddr) |
---|
211 | (defun %set-fifth (x v) (%rplaca (cddddr x) v)) |
---|
212 | (defsetf fifth %set-fifth) |
---|
213 | (defun %set-sixth (x v) (%rplaca (cdr (cddddr x)) v)) |
---|
214 | (defsetf sixth %set-sixth) |
---|
215 | (defun %set-seventh (x v) (%rplaca (cddr (cddddr x)) v)) |
---|
216 | (defsetf seventh %set-seventh) |
---|
217 | (defun %set-eighth (x v) (%rplaca (cdddr (cddddr x)) v)) |
---|
218 | (defsetf eighth %set-eighth) |
---|
219 | (defun %set-ninth (x v) (%rplaca (cddddr (cddddr x)) v)) |
---|
220 | (defsetf ninth %set-ninth) |
---|
221 | (defun %set-tenth (x v) (%rplaca (cdr (cddddr (cddddr x))) v)) |
---|
222 | (defsetf tenth %set-tenth) |
---|
223 | |
---|
224 | (defsetf rest %rplacd) |
---|
225 | (defsetf elt %setelt) |
---|
226 | (defsetf nth %setnth) |
---|
227 | (defsetf svref %svset) |
---|
228 | (defsetf fill-pointer %set-fill-pointer) |
---|
229 | (defsetf fdefinition %set-fdefinition) |
---|
230 | (defsetf subseq %set-subseq) |
---|
231 | (defsetf symbol-value set) |
---|
232 | (defsetf symbol-function fset) |
---|
233 | (defsetf symbol-plist %set-symbol-plist) |
---|
234 | (defsetf get %put) |
---|
235 | (defsetf gethash puthash) |
---|
236 | (defsetf char %set-char) |
---|
237 | (defsetf schar %set-schar) |
---|
238 | |
---|
239 | (defsetf charpos %set-charpos) |
---|