X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Fearly-type.lisp;h=53137bacba2d2b04c1ba8a13b60457c90c0f2f66;hb=020de3c04699323437f0c746fe986506b716ab97;hp=10ac973d998b659825f02f2e4d14ebf2f74d267d;hpb=05525d3a5906d7a89fcb689c26177732493c40ce;p=sbcl.git diff --git a/src/code/early-type.lisp b/src/code/early-type.lisp index 10ac973..53137ba 100644 --- a/src/code/early-type.lisp +++ b/src/code/early-type.lisp @@ -86,9 +86,10 @@ (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)) @@ -110,7 +111,7 @@ (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 @@ -138,23 +139,24 @@ :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) @@ -171,7 +173,14 @@ ;;; (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 @@ -326,7 +335,7 @@ :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) @@ -436,17 +445,8 @@ ;;; 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) ;; @@ -454,10 +454,30 @@ (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)))) + ())) + ;;;; type utilities @@ -490,18 +510,16 @@ (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))) @@ -517,15 +535,17 @@ ;;; 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. @@ -533,7 +553,7 @@ (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)))) @@ -547,5 +567,6 @@ (when (boundp 'sb!kernel::*values-specifier-type-cache-vector*) (values-specifier-type-cache-clear)) (values)) + (!defun-from-collected-cold-init-forms !early-type-cold-init)