0.pre7.86.flaky7:
[sbcl.git] / src / compiler / typetran.lisp
index ed0cb35..3abec13 100644 (file)
@@ -12,9 +12,6 @@
 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
 ;;;; files for more information.
 
-;;; FIXME: Many of the functions in this file could probably be
-;;; byte-compiled, since they're one-pass, cons-heavy code.
-
 (in-package "SB!C")
 \f
 ;;;; type predicate translation
@@ -71,7 +68,7 @@
 (defun ir1-transform-type-predicate (object type)
   (declare (type continuation object) (type ctype type))
   (let ((otype (continuation-type object)))
-    (cond ((not (types-intersect otype type))
+    (cond ((not (types-equal-or-intersect otype type))
           nil)
          ((csubtypep otype type)
           t)
@@ -80,7 +77,8 @@
 
 ;;; Flush %TYPEP tests whose result is known at compile time.
 (deftransform %typep ((object type))
-  (unless (constant-continuation-p type) (give-up-ir1-transform))
+  (unless (constant-continuation-p type)
+    (give-up-ir1-transform))
   (ir1-transform-type-predicate
    object
    (specifier-type (continuation-value type))))
@@ -89,7 +87,7 @@
 ;;; whether the single argument is known to (not) be of the
 ;;; appropriate type, expanding to T or NIL as appropriate.
 (deftransform fold-type-predicate ((object) * * :node node :defun-only t)
-  (let ((ctype (gethash (leaf-name
+  (let ((ctype (gethash (leaf-source-name
                         (ref-leaf
                          (continuation-use
                           (basic-combination-fun node))))
   (declare (type hairy-type type))
   (let ((spec (hairy-type-specifier type)))
     (cond ((unknown-type-p type)
-          (when (policy nil (> speed inhibit-warnings))
+          (when (policy *lexenv* (> speed inhibit-warnings))
             (compiler-note "can't open-code test of unknown type ~S"
                            (type-specifier type)))
           `(%typep ,object ',spec))
              (res `(= (array-dimension ,obj ,i) ,dim)))))
        (res)))))
 
-;;; If we can find a type predicate that tests for the type w/o
+;;; If we can find a type predicate that tests for the type without
 ;;; dimensions, then use that predicate and test for dimensions.
 ;;; Otherwise, just do %TYPEP.
 (defun source-transform-array-typep (obj type)
 ;;; then we also check whether the layout for the object is invalid
 ;;; and signal an error if so. Otherwise, look up the indirect
 ;;; class-cell and call CLASS-CELL-TYPEP at runtime.
-;;;
-;;; KLUDGE: The :WHEN :BOTH option here is probably a suboptimal
-;;; solution to the problem of %INSTANCE-TYPEP forms in byte compiled
-;;; code; it'd probably be better just to have %INSTANCE-TYPEP forms
-;;; never be generated in byte compiled code, or maybe to have a DEFUN
-;;; %INSTANCE-TYPEP somewhere to handle them if they are. But it's not
-;;; terribly important because mostly, %INSTANCE-TYPEP forms *aren't*
-;;; generated in byte compiled code. (As of sbcl-0.6.5, they could
-;;; sometimes be generated when byte compiling inline functions, but
-;;; it's quite uncommon.) -- WHN 20000523
-(deftransform %instance-typep ((object spec) * * :when :both)
+(deftransform %instance-typep ((object spec) (* *) * :node node :when :both)
   (aver (constant-continuation-p spec))
   (let* ((spec (continuation-value spec))
         (class (specifier-type spec))
                   (if (and res (not (layout-invalid res)))
                       res
                       nil))))
-    (/noshow "entering DEFTRANSFORM %INSTANCE-TYPEP" otype spec class name layout)
     (cond
       ;; Flush tests whose result is known at compile time.
-      ((not (types-intersect otype class))
-       (/noshow "flushing constant NIL")
+      ((not (types-equal-or-intersect otype class))
        nil)
       ((csubtypep otype class)
-       (/noshow "flushing constant T")
        t)
       ;; If not properly named, error.
       ((not (and name (eq (sb!xc:find-class name) class)))
                        class:~%  ~S"
                       class))
       (t
+        ;; Delay the type transform to give type propagation a chance.
+        (delay-ir1-transform node :constraint)
+
        ;; Otherwise transform the type test.
        (multiple-value-bind (pred get-layout)
           (cond
              (values '%instancep '%instance-layout))
             (t
              (values '(lambda (x) (declare (ignore x)) t) 'layout-of)))
-        (/noshow pred get-layout)
         (cond
           ((and (eq (class-state class) :sealed) layout
                 (not (class-subclasses class)))
            ;; Sealed and has no subclasses.
-           (/noshow "sealed and has no subclasses")
            (let ((n-layout (gensym)))
              `(and (,pred object)
                    (let ((,n-layout (,get-layout object)))
-                     ,@(when (policy nil (>= safety speed))
+                     ,@(when (policy *lexenv* (>= safety speed))
                              `((when (layout-invalid ,n-layout)
                                  (%layout-invalid-error object ',layout))))
                      (eq ,n-layout ',layout)))))
           ((and (typep class 'basic-structure-class) layout)
-           (/noshow "structure type tests; hierarchical layout depths")
            ;; structure type tests; hierarchical layout depths
            (let ((depthoid (layout-depthoid layout))
                  (n-layout (gensym)))
              `(and (,pred object)
                    (let ((,n-layout (,get-layout object)))
-                     ,@(when (policy nil (>= safety speed))
+                     ,@(when (policy *lexenv* (>= safety speed))
                              `((when (layout-invalid ,n-layout)
                                  (%layout-invalid-error object ',layout))))
                      (if (eq ,n-layout ',layout)
                                 (eq (svref (layout-inherits ,n-layout)
                                            ,depthoid)
                                     ',layout))))))))
+           ((and layout (>= (layout-depthoid layout) 0))
+           ;; hierarchical layout depths for other things (e.g.
+           ;; CONDITIONs)
+           (let ((depthoid (layout-depthoid layout))
+                 (n-layout (gensym))
+                 (n-inherits (gensym)))
+             `(and (,pred object)
+                   (let ((,n-layout (,get-layout object)))
+                     ,@(when (policy *lexenv* (>= safety speed))
+                         `((when (layout-invalid ,n-layout)
+                             (%layout-invalid-error object ',layout))))
+                     (if (eq ,n-layout ',layout)
+                         t
+                         (let ((,n-inherits (layout-inherits ,n-layout)))
+                           (declare (optimize (safety 0)))
+                           (and (> (length ,n-inherits) ,depthoid)
+                                (eq (svref ,n-inherits ,depthoid)
+                                    ',layout))))))))
           (t
            (/noshow "default case -- ,PRED and CLASS-CELL-TYPEP")
            `(and (,pred object)
 ;;; If the type is TYPE= to a type that has a predicate, then expand
 ;;; to that predicate. Otherwise, we dispatch off of the type's type.
 ;;; These transformations can increase space, but it is hard to tell
-;;; when, so we ignore policy and always do them. When byte-compiling,
-;;; we only do transforms that have potential for control
-;;; simplification. Instance type tests are converted to
-;;; %INSTANCE-TYPEP to allow type propagation.
+;;; when, so we ignore policy and always do them. 
 (def-source-transform typep (object spec)
   ;; KLUDGE: It looks bad to only do this on explicitly quoted forms,
   ;; since that would overlook other kinds of constants. But it turns
                                 (cadr spec))
               `(%typep ,object ,spec))
              (t nil))
-           (and (not (byte-compiling))
-                (typecase type
-                  (numeric-type
-                   (source-transform-numeric-typep object type))
-                  (sb!xc:class
-                   `(%instance-typep ,object ,spec))
-                  (array-type
-                   (source-transform-array-typep object type))
-                  (cons-type
-                   (source-transform-cons-typep object type))
-                  (t nil)))
+           (typecase type
+             (numeric-type
+              (source-transform-numeric-typep object type))
+             (sb!xc:class
+              `(%instance-typep ,object ,spec))
+             (array-type
+              (source-transform-array-typep object type))
+             (cons-type
+              (source-transform-cons-typep object type))
+             (t nil))
            `(%typep ,object ,spec)))
       (values nil t)))
 \f
 ;;;; coercion
 
-;;; old working version
 (deftransform coerce ((x type) (* *) * :when :both)
   (unless (constant-continuation-p type)
     (give-up-ir1-transform))
   (let ((tspec (specifier-type (continuation-value type))))
     (if (csubtypep (continuation-type x) tspec)
        'x
+       ;; Note: The THE here makes sure that specifiers like
+       ;; (SINGLE-FLOAT 0.0 1.0) can raise a TYPE-ERROR.
        `(the ,(continuation-value type)
-             ,(cond ((csubtypep tspec (specifier-type 'double-float))
-                     '(%double-float x))       
-                    ;; FIXME: If LONG-FLOAT is to be supported, we
-                    ;; need to pick it off here before falling through
-                    ;; to %SINGLE-FLOAT.
-                    ((csubtypep tspec (specifier-type 'float))
-                     '(%single-float x))
-                    (t
-                     (give-up-ir1-transform)))))))
+          ,(cond
+            ((csubtypep tspec (specifier-type 'double-float))
+             '(%double-float x))       
+            ;; FIXME: #!+long-float (t ,(error "LONG-FLOAT case needed"))
+            ((csubtypep tspec (specifier-type 'float))
+             '(%single-float x))
+            ((csubtypep tspec (specifier-type 'simple-vector))
+             '(coerce-to-simple-vector x))
+            (t
+             (give-up-ir1-transform)))))))
 
-;;; KLUDGE: new broken version -- 20000504
-;;; FIXME: should be fixed or deleted
-#+nil
-(deftransform coerce ((x type) (* *) * :when :both)
-  (unless (constant-continuation-p type)
-    (give-up-ir1-transform))
-  (let ((tspec (specifier-type (continuation-value type))))
-    (if (csubtypep (continuation-type x) tspec)
-       'x
-       `(if #+nil (typep x type) #-nil nil
-            x
-            (the ,(continuation-value type)
-                 ,(cond ((csubtypep tspec (specifier-type 'double-float))
-                         '(%double-float x))   
-                        ;; FIXME: If LONG-FLOAT is to be supported,
-                        ;; we need to pick it off here before falling
-                        ;; through to %SINGLE-FLOAT.
-                        ((csubtypep tspec (specifier-type 'float))
-                         '(%single-float x))
-                        #+nil
-                        ((csubtypep tspec (specifier-type 'list))
-                         '(coerce-to-list x))
-                        #+nil
-                        ((csubtypep tspec (specifier-type 'string))
-                         '(coerce-to-simple-string x))
-                        #+nil
-                        ((csubtypep tspec (specifier-type 'bit-vector))
-                         '(coerce-to-bit-vector x))
-                        #+nil
-                        ((csubtypep tspec (specifier-type 'vector))
-                         '(coerce-to-vector x type))
-                        (t
-                         (give-up-ir1-transform))))))))