X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fpcl%2Fctor.lisp;h=0ef967b22a167f890c4dd3572837d8e52b2a3057;hb=22aec7852f4861e5dab28cc0d619c24b62590dad;hp=df5e2dcc855e554c6636cbeaf073a35f5224a675;hpb=a736ac10b709b2d40305f0a6e3764afd246a8ef5;p=sbcl.git diff --git a/src/pcl/ctor.lisp b/src/pcl/ctor.lisp index df5e2dc..0ef967b 100644 --- a/src/pcl/ctor.lisp +++ b/src/pcl/ctor.lisp @@ -285,6 +285,7 @@ ;; together with the system-defined ones in what ;; COMPUTE-APPLICABLE-METHODS returns. (or (and (not (structure-class-p class)) + (not (condition-class-p class)) (null (cdr make-instance-methods)) (null (cdr allocate-instance-methods)) (null (check-initargs-1 class (plist-keys (ctor-initargs ctor)) @@ -373,7 +374,7 @@ (multiple-value-bind (si-around si-before si-primary si-after) (standard-sort-methods si-methods) (declare (ignore si-primary)) - (assert (and (null ii-around) (null si-around))) + (aver (and (null ii-around) (null si-around))) (let ((initargs (ctor-initargs ctor)) (slot-inits (slot-init-forms ctor (or ii-before si-before)))) (values @@ -429,26 +430,33 @@ (make-array (layout-length (class-wrapper class)) :initial-element nil)) (class-inits ()) + (default-inits ()) (default-initargs (class-default-initargs class)) (initarg-locations (compute-initarg-locations class (append initkeys (mapcar #'car default-initargs))))) (labels ((initarg-locations (initarg) (cdr (assoc initarg initarg-locations :test #'eq))) - + (initializedp (location) + (cond + ((consp location) + (assoc location class-inits :test #'eq)) + ((integerp location) + (not (null (aref slot-vector location)))) + (t (bug "Weird location in ~S" 'slot-init-forms)))) (class-init (location type val) - (assert (consp location)) - (unless (assoc location class-inits :test #'eq) + (aver (consp location)) + (unless (initializedp location) (push (list location type val) class-inits))) - (instance-init (location type val) - (assert (integerp location)) - (assert (not (instance-slot-initialized-p location))) - (setf (aref slot-vector location) (list type val))) - - (instance-slot-initialized-p (location) - (not (null (aref slot-vector location))))) - ;; + (aver (integerp location)) + (unless (initializedp location) + (setf (aref slot-vector location) (list type val)))) + (default-init-var-name (i) + (let ((ps #(.d0. .d1. .d2. .d3. .d4. .d5.))) + (if (array-in-bounds-p ps i) + (aref ps i) + (intern (format nil ".D~D." i) *the-pcl-package*))))) ;; Loop over supplied initargs and values and record which ;; instance and class slots they initialize. (loop for (key value) on initargs by #'cddr @@ -462,22 +470,24 @@ (if (consp location) (class-init location 'param value) (instance-init location 'param value))))) - ;; ;; Loop over default initargs of the class, recording ;; initializations of slots that have not been initialized - ;; above. - (loop for (key initfn initform) in default-initargs do - (unless (member key initkeys :test #'eq) - (if (constantp initform) - (dolist (location (initarg-locations key)) - (if (consp location) - (class-init location 'constant initform) - (instance-init location 'constant initform))) - (dolist (location (initarg-locations key)) - (if (consp location) - (class-init location 'initfn initfn) - (instance-init location 'initfn initfn)))))) - ;; + ;; above. Default initargs which are not in the supplied + ;; initargs are treated as if they were appended to supplied + ;; initargs, that is, their values must be evaluated even + ;; if not actually used for initializing a slot. + (loop for (key initfn initform) in default-initargs and i from 0 + unless (member key initkeys :test #'eq) do + (let* ((type (if (constantp initform) 'constant 'var)) + (init (if (eq type 'var) initfn initform))) + (when (eq type 'var) + (let ((init-var (default-init-var-name i))) + (setq init init-var) + (push (cons init-var initfn) default-inits))) + (dolist (location (initarg-locations key)) + (if (consp location) + (class-init location type init) + (instance-init location type init))))) ;; Loop over all slots of the class, filling in the rest from ;; slot initforms. (loop for slotd in (class-slots class) @@ -487,11 +497,10 @@ as initform = (slot-definition-initform slotd) do (unless (or (eq allocation :class) (null initfn) - (instance-slot-initialized-p location)) + (initializedp location)) (if (constantp initform) (instance-init location 'initform initform) (instance-init location 'initform/initfn initfn)))) - ;; ;; Generate the forms for initializing instance and class slots. (let ((instance-init-forms (loop for slot-entry across slot-vector and i from 0 @@ -500,7 +509,7 @@ ((nil) (unless before-method-p `(setf (clos-slots-ref .slots. ,i) +slot-unbound+))) - (param + ((param var) `(setf (clos-slots-ref .slots. ,i) ,value)) (initfn `(setf (clos-slots-ref .slots. ,i) (funcall ,value))) @@ -526,12 +535,18 @@ (loop for (location type value) in class-inits collect `(setf (cdr ',location) ,(ecase type - (constant `',(eval value)) - (param `,value) - (initfn `(funcall ,value))))))) - `(progn - ,@(delete nil instance-init-forms) - ,@class-init-forms))))) + (constant `',(eval value)) + ((param var) `,value) + (initfn `(funcall ,value))))))) + (multiple-value-bind (vars bindings) + (loop for (var . initfn) in (nreverse default-inits) + collect var into vars + collect `(,var (funcall ,initfn)) into bindings + finally (return (values vars bindings))) + `(let ,bindings + (declare (ignorable ,@vars)) + ,@(delete nil instance-init-forms) + ,@class-init-forms)))))) ;;; ;;; Return an alist of lists (KEY LOCATION ...) telling, for each