0.7.9.41:
[sbcl.git] / src / code / late-type.lisp
index c61a3eb..3cd0808 100644 (file)
@@ -69,7 +69,7 @@
   ;; If TYPE2 might be concealing something related to our class
   ;; hierarchy
   (if (type-might-contain-other-types-p type2)
-      ;; too confusing, gotta punt 
+      ;; too confusing, gotta punt
       (values nil nil)
       ;; ordinary case expected by old CMU CL code, where the taxonomy
       ;; of TYPE2's representation accurately reflects the taxonomy of
            (type-specifier
             (fun-type-returns type)))))
 
-;;; Since all function types are equivalent to FUNCTION, they are all
-;;; subtypes of each other.
+;;; The meaning of this is a little confused. On the one hand, all
+;;; function objects are represented the same way regardless of the
+;;; arglists and return values, and apps don't get to ask things like
+;;; (TYPEP #'FOO (FUNCTION (FIXNUM) *)) in any meaningful way. On the
+;;; other hand, Python wants to reason about function types. So...
 (!define-type-method (function :simple-subtypep) (type1 type2)
-  (declare (ignore type1 type2))
-  (values t t))
+ (flet ((fun-type-simple-p (type)
+          (not (or (fun-type-rest type)
+                   (fun-type-keyp type))))
+        (every-csubtypep (types1 types2)
+          (loop
+             for a1 in types1
+             for a2 in types2
+             do (multiple-value-bind (res sure-p)
+                    (csubtypep a1 a2)
+                  (unless res (return (values res sure-p))))
+             finally (return (values t t)))))
+   (macrolet ((3and (x y)
+                `(multiple-value-bind (val1 win1) ,x
+                   (if (and (not val1) win1)
+                       (values nil t)
+                       (multiple-value-bind (val2 win2) ,y
+                         (if (and val1 val2)
+                             (values t t)
+                             (values nil (or win1 win2))))))))
+     (3and (values-subtypep (fun-type-returns type1)
+                            (fun-type-returns type2))
+           (cond ((fun-type-wild-args type2) (values t t))
+                 ((fun-type-wild-args type1) (values nil t))
+                 ((not (or (fun-type-simple-p type1)
+                           (fun-type-simple-p type2)))
+                  (values nil nil))
+                 (t (multiple-value-bind (min1 max1) (fun-type-nargs type1)
+                      (multiple-value-bind (min2 max2) (fun-type-nargs type2)
+                        (cond ((or (> max1 max2) (< min1 min2))
+                               (values nil t))
+                              ((and (= min1 min2) (= max1 max2))
+                               (3and (every-csubtypep (fun-type-required type1)
+                                                      (fun-type-required type2))
+                                     (every-csubtypep (fun-type-optional type1)
+                                                      (fun-type-optional type2))))
+                              (t (every-csubtypep
+                                  (concatenate 'list
+                                               (fun-type-required type1)
+                                               (fun-type-optional type1))
+                                  (concatenate 'list
+                                               (fun-type-required type2)
+                                               (fun-type-optional type2)))))))))))))
 
 (!define-superclasses function ((function)) !cold-init-forms)
 
     res))
 
 (!def-type-translator values (&rest values)
-  (let ((res (make-values-type)))
+  (let ((res (%make-values-type)))
     (parse-args-types values res)
     res))
 \f
 (defun args-type-op (type1 type2 operation nreq default-type)
   (declare (type ctype type1 type2 default-type)
           (type function operation nreq))
+  (when (eq type1 type2)
+    (values type1 t))
   (if (or (values-type-p type1) (values-type-p type2))
       (let ((type1 (coerce-to-values type1))
            (type2 (coerce-to-values type2)))
        nil)))
 
 (defun type-intersection (&rest input-types)
+  (%type-intersection input-types))
+(defun-cached (%type-intersection :hash-bits 8
+                                  :hash-function (lambda (x)
+                                                   (logand (sxhash x) #xff)))
+    ((input-types equal))
   (let ((simplified-types (simplified-compound-types input-types
                                                     #'intersection-type-p
                                                     #'type-intersection2)))
     (if (and (> (length simplified-types) 1)
             (some #'union-type-p simplified-types))
        (let* ((first-union (find-if #'union-type-p simplified-types))
-              (other-types (coerce (remove first-union simplified-types) 'list))
-              (distributed (maybe-distribute-one-union first-union other-types)))
+              (other-types (coerce (remove first-union simplified-types)
+                                   'list))
+              (distributed (maybe-distribute-one-union first-union
+                                                       other-types)))
          (if distributed
              (apply #'type-union distributed)
              (make-hairy-type
-              :specifier `(and ,@(map 'list #'type-specifier simplified-types)))))
+              :specifier `(and ,@(map 'list
+                                      #'type-specifier
+                                      simplified-types)))))
        (make-compound-type-or-something #'%make-intersection-type
                                         simplified-types
                                         (some #'type-enumerable
                                         *universal-type*))))
 
 (defun type-union (&rest input-types)
+  (%type-union input-types))
+(defun-cached (%type-union :hash-bits 8
+                           :hash-function (lambda (x)
+                                            (logand (sxhash x) #xff)))
+    ((input-types equal))
   (let ((simplified-types (simplified-compound-types input-types
                                                     #'union-type-p
                                                     #'type-union2)))
-    (make-compound-type-or-something #'%make-union-type
+    (make-compound-type-or-something #'make-union-type
                                     simplified-types
                                     (every #'type-enumerable simplified-types)
                                     *empty-type*)))
  (macrolet ((frob (name var)
              `(progn
                 (setq ,var (make-named-type :name ',name))
-                (setf (info :type :kind ',name) #+sb-xc-host :defined #-sb-xc-host :primitive)
+                (setf (info :type :kind ',name)
+                      #+sb-xc-host :defined #-sb-xc-host :primitive)
                 (setf (info :type :builtin ',name) ,var))))
    ;; KLUDGE: In ANSI, * isn't really the name of a type, it's just a
    ;; special symbol which can be stuck in some places where an
       (error 'simple-type-error
             :datum predicate-name
             :expected-type 'symbol
-            :format-control "~S is not a symbol."
+            :format-control "The SATISFIES predicate name is not a symbol: ~S"
             :format-arguments (list predicate-name))))
   ;; Create object.
   (make-hairy-type :specifier whole))
          (t
           (values nil t)))))
 
-(!define-superclasses number ((generic-number)) !cold-init-forms)
+(!define-superclasses number ((number)) !cold-init-forms)
 
 ;;; If the high bound of LOW is adjacent to the low bound of HIGH,
 ;;; then return true, otherwise NIL.
                                       >= > t)))))))
 
 (!cold-init-forms
-  (setf (info :type :kind 'number) #+sb-xc-host :defined #-sb-xc-host :primitive)
+  (setf (info :type :kind 'number)
+       #+sb-xc-host :defined #-sb-xc-host :primitive)
   (setf (info :type :builtin 'number)
        (make-numeric-type :complexp nil)))
 
        ;; previously we threw an error here:
        ;; (error "Lower bound ~S is greater than upper bound ~S." l h))
        ;; but ANSI doesn't say anything about that, so:
-       (specifier-type 'nil)
+       *empty-type*
       (make-numeric-type :class 'integer
                         :complexp :real
                         :enumerable (not (null (and l h)))
           ;; as above, previously we did
           ;; (error "Lower bound ~S is not less than upper bound ~S." low high))
           ;; but it is correct to do
-          (specifier-type 'nil)
-        (make-numeric-type :class ',class :format ',format :low lb :high hb)))))
+          *empty-type*
+        (make-numeric-type :class ',class
+                           :format ',format
+                           :low lb
+                           :high hb)))))
 
 (!def-bounded-type rational rational nil)
 
                 *empty-type*))))))
 
 (!define-type-method (member :complex-intersection2) (type1 type2)
-  (block punt               
+  (block punt
     (collect ((members))
       (let ((mem2 (member-type-members type2)))
         (dolist (member mem2)
                                       (dimensions '*))
   (specialize-array-type
    (make-array-type :dimensions (canonical-array-dimensions dimensions)
+                    :complexp :maybe
                    :element-type (specifier-type element-type))))
 
 (!def-type-translator simple-array (&optional (element-type '*)
                                              (dimensions '*))
   (specialize-array-type
    (make-array-type :dimensions (canonical-array-dimensions dimensions)
-                   :element-type (specifier-type element-type)
-                   :complexp nil)))
+                    :complexp nil
+                   :element-type (specifier-type element-type))))
 \f
 ;;;; utilities shared between cross-compiler and target system