(and (symbolp constant)
(not (null (symbol-package constant)))))))
-;;; somewhat akin to DEFAULT-INITARGS (SLOT-CLASS T T), but just
-;;; collecting the defaulted initargs for the call.
+;;; Somewhat akin to DEFAULT-INITARGS, but just collecting the defaulted
+;;; initargs for the call.
(defun ctor-default-initkeys (supplied-initargs class-default-initargs)
(loop for (key) in class-default-initargs
when (eq (getf supplied-initargs key '.not-there.) '.not-there.)
collect key))
+
+;;; Like DEFAULT-INITARGS, but return a list that can be spliced into source,
+;;; instead of a list with values already evaluated.
+(defun ctor-default-initargs (supplied-initargs class-default-initargs)
+ (loop for (key form fun) in class-default-initargs
+ when (eq (getf supplied-initargs key '.not-there.) '.not-there.)
+ append (list key (if (constantp form) form `(funcall ,fun)))
+ into default-initargs
+ finally
+ (return (append supplied-initargs default-initargs))))
\f
;;; *****************
;;; CTORS *********
(make-instance ,class ,@initargs))
(let ((defaults (class-default-initargs class)))
(when defaults
- (setf initargs (default-initargs initargs defaults)))
+ (setf initargs (ctor-default-initargs initargs defaults)))
`(lambda ,lambda-list
(declare #.*optimize-speed*)
(fast-make-instance ,class ,@initargs))))))
;;; Make sure we get default initargs right with on the FAST-MAKE-INSTANCE path CTORs
(defclass some-class ()
((aroundp :initform nil :reader aroundp))
- (:default-initargs :x :success?))
+ (:default-initargs :x :success1))
+
(defmethod initialize-instance :around ((some-class some-class) &key (x :fail?))
- (unless (eq x :success?)
+ (unless (eq x :success1)
(error "Default initarg lossage"))
(setf (slot-value some-class 'aroundp) t)
(when (next-method-p)
(call-next-method)))
-(with-test (:name (make-instance :ctor-default-initargs))
+
+(with-test (:name (make-instance :ctor-default-initargs-1))
(assert (aroundp (eval `(make-instance 'some-class))))
(let ((fun (compile nil `(lambda () (make-instance 'some-class)))))
(assert (aroundp (funcall fun)))
(let ((ctor (find-callee fun :type 'sb-pcl::ctor)))
(assert (find-callee ctor :name 'sb-pcl::fast-make-instance)))))
+;;; Make sure we get default initargs right with on the FAST-MAKE-INSTANCE path CTORs
+;;; in more interesting cases as well...
+(defparameter *some-counter* 0)
+(let* ((x 'success2))
+ (defclass some-class2 ()
+ ((aroundp :initform nil :reader aroundp))
+ (:default-initargs :x (progn (incf *some-counter*) x))))
+
+(defmethod initialize-instance :around ((some-class some-class2) &key (x :fail2?))
+ (unless (eq x 'success2)
+ (error "Default initarg lossage"))
+ (setf (slot-value some-class 'aroundp) t)
+ (when (next-method-p)
+ (call-next-method)))
+
+(with-test (:name (make-instance :ctor-default-initargs-2))
+ (assert (= 0 *some-counter*))
+ (assert (aroundp (eval `(make-instance 'some-class2))))
+ (assert (= 1 *some-counter*))
+ (let ((fun (compile nil `(lambda () (make-instance 'some-class2)))))
+ (assert (= 1 *some-counter*))
+ (assert (aroundp (funcall fun)))
+ (assert (= 2 *some-counter*))
+ ;; make sure we tested what we think we tested...
+ (let ((ctor (find-callee fun :type 'sb-pcl::ctor)))
+ (assert (find-callee ctor :name 'sb-pcl::fast-make-instance)))))
+
;;; No compiler notes, please
(locally (declare (optimize safety))
(defclass type-check-thing ()