diff --git a/src/lsp/setf.lsp b/src/lsp/setf.lsp index 898fcb63d..1f31ceebe 100644 --- a/src/lsp/setf.lsp +++ b/src/lsp/setf.lsp @@ -38,17 +38,21 @@ by (documentation 'SYMBOL 'setf)." ,@(si::expand-set-documentation access-fn 'setf (cadr rest)) ',access-fn)) (t - (unless (= (list-length (cadr rest)) 1) - (error "(store-variable) expected.")) - (setq rest `(lambda ,(car rest) #'(lambda ,(cadr rest) ,@(cddr rest)))) - `(eval-when (compile load eval) - (sys:putprop ',access-fn #',rest 'SETF-LAMBDA) - (remprop ',access-fn 'SETF-UPDATE-FN) - (remprop ',access-fn 'SETF-METHOD) - (remprop ',access-fn 'SETF-SYMBOL) - ,@(si::expand-set-documentation access-fn 'setf - (find-documentation (cddr rest))) - ',access-fn)))) + (let* ((store (second rest)) + (args (first rest)) + (body (cddr rest)) + (doc (find-documentation body))) + (unless (and (= (list-length store) 1) (symbolp (first store))) + (error "Single store-variable expected.")) + (setq rest `(lambda ,args #'(lambda ,store ,@body))) + `(eval-when (compile load eval) + (sys:putprop ',access-fn #'(lambda (,@store ,@args) ,@body) + 'SETF-LAMBDA) + (remprop ',access-fn 'SETF-UPDATE-FN) + (remprop ',access-fn 'SETF-METHOD) + (remprop ',access-fn 'SETF-SYMBOL) + ,@(si::expand-set-documentation access-fn 'setf doc) + ',access-fn))))) ;;; DEFINE-SETF-METHOD macro. @@ -107,60 +111,47 @@ Checks if the third gang is a single-element list." ;;;; GET-SETF-METHOD-MULTIPLE-VALUE. -(defun get-setf-method-multiple-value (form &optional env &aux tem) +(defun get-setf-method-multiple-value (form &optional env &aux f) "Args: (form) Returns the 'five gangs' (see DEFINE-SETF-EXPANDER) for PLACE as five values. Does not check if the third gang is a single-element list." - (cond ((symbolp form) - (let ((store (gensym))) - (values nil nil (list store) `(setq ,form ,store) form))) - ((or (not (consp form)) (not (symbolp (car form)))) - (error "Cannot get the setf-method of ~S." form)) - ((and env (setq tem (assoc (car form) (cdr env)))) - (setq tem (macroexpand form env)) - (when (eq form tem) - (error "Cannot get setf-method for ~a" form)) - (return-from get-setf-method-multiple-value - (get-setf-method-multiple-value tem env))) - ((get (car form) 'SETF-METHOD) - (apply (get (car form) 'SETF-METHOD) env (cdr form))) - ((or (get (car form) 'SETF-UPDATE-FN) - (setq tem (get (car form) 'STRUCTURE-ACCESS))) - (let ((vars (mapcar #'(lambda (x) - (declare (ignore x)) - (gensym)) - (cdr form))) - (store (gensym))) - (values vars (cdr form) (list store) - (if tem - (setf-structure-access (car vars) (car tem) - (cdr tem) store) - `(,(get (car form) 'SETF-UPDATE-FN) - ,@vars ,store)) - (cons (car form) vars)))) - ((get (car form) 'SETF-LAMBDA) - (let* ((vars (mapcar #'(lambda (x) - (declare (ignore x)) - (gensym)) - (cdr form))) - (store (gensym)) - (f (get (car form) 'SETF-LAMBDA))) - (values vars (cdr form) (list store) - (funcall (apply f vars) store) - (cons (car form) vars)))) - ((macro-function (car form)) - (get-setf-method-multiple-value (macroexpand form))) - (t - (let ((vars (mapcar #'(lambda (x) - (declare (ignore x)) - (gensym)) - (cdr form))) - (store (gensym))) - (values vars (cdr form) (list store) - ;; use the symbol here, otherwise the CLOS walker punts. - `(,(si::setf-namep (list 'SETF (car form))) ,store ,@vars) - (cons (car form) vars)))))) - + (flet ((rename-arguments (vars &aux names values all-args) + (dolist (item vars) + (unless (or (fixnump item) (keywordp item)) + (push item values) + (setq item (gensym)) + (push item names)) + (push item all-args)) + (values (gensym) (nreverse names) (nreverse values) (nreverse all-args)))) + (cond ((symbolp form) + (let ((store (gensym))) + (values nil nil (list store) `(setq ,form ,store) form))) + ((or (not (consp form)) (not (symbolp (car form)))) + (error "Cannot get the setf-method of ~S." form)) + ((and env (setq f (assoc (car form) (cdr env)))) + (setq f (macroexpand form env)) + (when (eq form f) + (error "Cannot get setf-method for ~a" form)) + (return-from get-setf-method-multiple-value + (get-setf-method-multiple-value f env))) + ((macro-function (car form)) + (get-setf-method-multiple-value (macroexpand form))) + ((setq f (get (car form) 'SETF-METHOD)) + (apply f env (cdr form))) + (t + (let ((name (car form)) writer) + (multiple-value-bind (store vars inits all) + (rename-arguments (cdr form)) + (setq writer + (cond ((setq f (get name 'SETF-UPDATE-FN)) + `(,f ,@all ,store)) + ((setq f (get name 'STRUCTURE-ACCESS)) + (setf-structure-access (car all) (car f) (cdr f) store)) + ((setq f (get (car form) 'SETF-LAMBDA)) + (apply f store all)) + (t + `(,(si::setf-namep (list 'SETF name)) ,store ,@all)))) + (values vars inits (list store) writer (cons name all)))))))) ;;;; SETF definitions.