0.8.7.2:
[sbcl.git] / src / code / early-type.lisp
index 10ac973..53137ba 100644 (file)
 
 (defun args-types (lambda-list-like-thing)
   (multiple-value-bind
-       (required optional restp rest keyp keys allowp auxp aux)
+       (required optional restp rest keyp keys allowp auxp aux
+                  morep more-context more-count llk-p)
       (parse-lambda-list-like-thing lambda-list-like-thing)
-    (declare (ignore aux))
+    (declare (ignore aux morep more-context more-count))
     (when auxp
       (error "&AUX in a FUNCTION or VALUES type: ~S." lambda-list-like-thing))
     (let ((required (mapcar #'single-value-specifier-type required))
             (key-info))))
       (multiple-value-bind (required optional rest)
          (canonicalize-args-type-args required optional rest)
-       (values required optional rest keyp keywords allowp)))))
+       (values required optional rest keyp keywords allowp llk-p)))))
 
 (defstruct (values-type
            (:include args-type
                      :rest rest
                      :allowp allowp))
 
-;;; FIXME: ANSI VALUES has a short form (without lambda list
-;;; keywords), which should be translated into a long one.
 (defun make-values-type (&key (args nil argsp)
                          required optional rest allowp)
   (if argsp
       (if (eq args '*)
          *wild-type*
-         (multiple-value-bind (required optional rest keyp keywords allowp)
+         (multiple-value-bind (required optional rest keyp keywords allowp
+                                llk-p)
              (args-types args)
             (declare (ignore keywords))
             (when keyp
               (error "&KEY appeared in a VALUES type specifier ~S."
                      `(values ,@args)))
-            (make-values-type :required required
-                              :optional optional
-                              :rest rest
-                              :allowp allowp)))
+            (if llk-p
+                (make-values-type :required required
+                                  :optional optional
+                                  :rest rest
+                                  :allowp allowp)
+                (make-short-values-type required))))
       (multiple-value-bind (required optional rest)
           (canonicalize-args-type-args required optional rest)
         (cond ((and (null required)
 ;;; (SPECIFIER-TYPE 'FUNCTION) and its subtypes
 (defstruct (fun-type (:include args-type
                               (class-info (type-class-or-lose 'function)))
-                     (:constructor %make-fun-type))
+                     (:constructor
+                      %make-fun-type (&key required optional rest
+                                           keyp keywords allowp
+                                           wild-args
+                                           returns
+                                      &aux (rest (if (eq rest *empty-type*)
+                                                     nil
+                                                     rest)))))
   ;; true if the arguments are unrestrictive, i.e. *
   (wild-args nil :type boolean)
   ;; type describing the return values. This is a values type
                     :enumerable enumerable))
 
 ;;; An ARRAY-TYPE is used to represent any array type, including
-;;; things such as SIMPLE-STRING.
+;;; things such as SIMPLE-BASE-STRING.
 (defstruct (array-type (:include ctype
                                 (class-info (type-class-or-lose 'array)))
                        (:constructor %make-array-type)
 ;;; A CONS-TYPE is used to represent a CONS type.
 (defstruct (cons-type (:include ctype (class-info (type-class-or-lose 'cons)))
                      (:constructor
-                      ;; ANSI says that for CAR and CDR subtype
-                      ;; specifiers '* is equivalent to T. In order
-                      ;; to avoid special cases in SUBTYPEP and
-                      ;; possibly elsewhere, we slam all CONS-TYPE
-                      ;; objects into canonical form w.r.t. this
-                      ;; equivalence at creation time.
-                      %make-cons-type (car-raw-type
-                                       cdr-raw-type
-                                       &aux
-                                       (car-type (type-*-to-t car-raw-type))
-                                       (cdr-type (type-*-to-t cdr-raw-type))))
+                      %make-cons-type (car-type
+                                       cdr-type))
                      (:copier nil))
   ;; the CAR and CDR element types (to support ANSI (CONS FOO BAR) types)
   ;;
   (car-type (missing-arg) :type ctype :read-only t)
   (cdr-type (missing-arg) :type ctype :read-only t))
 (defun make-cons-type (car-type cdr-type)
+  (aver (not (or (eq car-type *wild-type*)
+                 (eq cdr-type *wild-type*))))
   (if (or (eq car-type *empty-type*)
          (eq cdr-type *empty-type*))
       *empty-type*
       (%make-cons-type car-type cdr-type)))
+
+(defun cons-type-length-info (type)
+  (declare (type cons-type type))
+  (do ((min 1 (1+ min))
+       (cdr (cons-type-cdr-type type) (cons-type-cdr-type cdr)))
+      ((not (cons-type-p cdr))
+       (cond
+        ((csubtypep cdr (specifier-type 'null))
+         (values min t))
+        ((csubtypep *universal-type* cdr)
+         (values min nil))
+        ((type/= (type-intersection (specifier-type 'cons) cdr) *empty-type*)
+         (values min nil))
+        ((type/= (type-intersection (specifier-type 'null) cdr) *empty-type*)
+         (values min t))
+        (t (values min :maybe))))
+    ()))
+       
 \f
 ;;;; type utilities
 
                (or (built-in-classoid-translation spec) spec)
                spec))
           (t
-           (let* (;; FIXME: This automatic promotion of FOO-style
-                  ;; specs to (FOO)-style specs violates the ANSI
-                  ;; standard. Unfortunately, we can't fix the
-                  ;; problem just by removing it, since then things
-                  ;; downstream should break. But at some point we
-                  ;; should fix this and the things downstream too.
-                  (lspec (if (atom spec) (list spec) spec))
+           (when (and (atom spec)
+                      (member spec '(and or not member eql satisfies values)))
+             (error "The symbol ~S is not valid as a type specifier." spec))
+           (let* ((lspec (if (atom spec) (list spec) spec))
                   (fun (info :type :translator (car lspec))))
              (cond (fun
                     (funcall fun lspec))
-                   ((or (and (consp spec) (symbolp (car spec)))
-                        (symbolp spec))
+                   ((or (and (consp spec) (symbolp (car spec))
+                             (not (info :type :builtin (car spec))))
+                        (and (symbolp spec) (not (info :type :builtin spec))))
                     (when (and *type-system-initialized*
                                 (not (eq (info :type :kind spec)
                                          :forthcoming-defclass-type)))
 ;;; never return a VALUES type.
 (defun specifier-type (x)
   (let ((res (values-specifier-type x)))
-    (when (values-type-p res)
+    (when (or (values-type-p res)
+              ;; bootstrap magic :-(
+              (and (named-type-p res)
+                   (eq (named-type-name res) '*)))
       (error "VALUES type illegal in this context:~%  ~S" x))
     res))
 
 (defun single-value-specifier-type (x)
-  (let ((res (specifier-type x)))
-    (if (eq res *wild-type*)
-        *universal-type*
-        res)))
+  (if (eq x '*)
+      *universal-type*
+      (specifier-type x)))
 
 ;;; Similar to MACROEXPAND, but expands DEFTYPEs. We don't bother
 ;;; returning a second value.
   (let ((def (cond ((symbolp form)
                     (info :type :expander form))
                    ((and (consp form) (symbolp (car form)))
-                    (info :type :expander (car form)))
+                   (info :type :expander (car form)))
                    (t nil))))
     (if def
         (type-expand (funcall def (if (consp form) form (list form))))
   (when (boundp 'sb!kernel::*values-specifier-type-cache-vector*)
     (values-specifier-type-cache-clear))
   (values))
+
 \f
 (!defun-from-collected-cold-init-forms !early-type-cold-init)