1.0.29.51: correctly compute default initargs for FAST-MAKE-INSTANCE
authorNikodemus Siivola <nikodemus@random-state.net>
Sun, 28 Jun 2009 10:55:52 +0000 (10:55 +0000)
committerNikodemus Siivola <nikodemus@random-state.net>
Sun, 28 Jun 2009 10:55:52 +0000 (10:55 +0000)
* Ooops, can't use DEFAULT-INITARGS, since calling it executes the
  initforms. Define and use CTOR-DEFAULT-INITARGS.

* A better test-case.

* Reported by Leslie P. Polzer.

src/pcl/ctor.lisp
tests/ctor.impure.lisp
version.lisp-expr

index 403732a..04daadf 100644 (file)
          (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))))))
index 69daa7a..953314d 100644 (file)
 ;;; 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 ()
index 8643e6a..634a70b 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.29.50"
+"1.0.29.51"