X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Fearly-type.lisp;h=77698ddb075ea6c77a740138d075b7c9c8480811;hb=98a76d4426660876dec6649b1e228d2e5b47f579;hp=2eea09772a3a53b5bd43300c2e7238d96acebbd0;hpb=67d2b80e478824a46317419f076ab1f6b020f6b1;p=sbcl.git diff --git a/src/code/early-type.lisp b/src/code/early-type.lisp index 2eea097..77698dd 100644 --- a/src/code/early-type.lisp +++ b/src/code/early-type.lisp @@ -24,7 +24,7 @@ (defstruct (hairy-type (:include ctype (class-info (type-class-or-lose 'hairy)) (enumerable t) - (might-contain-other-types? t)) + (might-contain-other-types-p t)) (:copier nil) #!+cmu (:pure nil)) ;; the Common Lisp type-specifier of the type we represent @@ -38,6 +38,18 @@ (defstruct (unknown-type (:include hairy-type) (:copier nil))) +(defstruct (negation-type (:include ctype + (class-info (type-class-or-lose 'negation)) + ;; FIXME: is this right? It's + ;; what they had before, anyway + (enumerable t) + (might-contain-other-types-p t)) + (:copier nil) + #!+cmu (:pure nil)) + (type (missing-arg) :type ctype)) + +(!define-type-class negation) + ;;; ARGS-TYPE objects are used both to represent VALUES types and ;;; to represent FUNCTION types. (defstruct (args-type (:include ctype) @@ -55,21 +67,107 @@ ;; true if other &KEY arguments are allowed (allowp nil :type boolean)) +(defun canonicalize-args-type-args (required optional rest) + (when rest + (let ((last-distinct-optional (position rest optional + :from-end t + :test-not #'type=))) + (setf optional + (when last-distinct-optional + (subseq optional 0 (1+ last-distinct-optional)))))) + (values required optional rest)) + +(defun args-types (lambda-list-like-thing) + (multiple-value-bind + (required optional restp rest keyp keys allowp auxp aux) + (parse-lambda-list-like-thing lambda-list-like-thing) + (declare (ignore aux)) + (when auxp + (error "&AUX in a FUNCTION or VALUES type: ~S." lambda-list-like-thing)) + (let ((required (mapcar #'single-value-specifier-type required)) + (optional (mapcar #'single-value-specifier-type optional)) + (rest (when restp (single-value-specifier-type rest))) + (keywords + (collect ((key-info)) + (dolist (key keys) + (unless (proper-list-of-length-p key 2) + (error "Keyword type description is not a two-list: ~S." key)) + (let ((kwd (first key))) + (when (find kwd (key-info) :key #'key-info-name) + (error "~@" + kwd lambda-list-like-thing)) + (key-info + (make-key-info + :name kwd + :type (single-value-specifier-type (second key)))))) + (key-info)))) + (multiple-value-bind (required optional rest) + (canonicalize-args-type-args required optional rest) + (values required optional rest keyp keywords allowp))))) + (defstruct (values-type (:include args-type (class-info (type-class-or-lose 'values))) + (:constructor %make-values-type) (:copier nil))) +(defun make-values-type (&rest initargs + &key (args nil argsp) &allow-other-keys) + (if argsp + (if (eq args '*) + *wild-type* + (multiple-value-bind (required optional rest keyp keywords allowp) + (args-types args) + (if (and (null required) + (null optional) + (eq rest *universal-type*) + (not keyp)) + *wild-type* + (%make-values-type :required required + :optional optional + :rest rest + :keyp keyp + :keywords keywords + :allowp allowp)))) + (apply #'%make-values-type initargs))) + (!define-type-class values) ;;; (SPECIFIER-TYPE 'FUNCTION) and its subtypes (defstruct (fun-type (:include args-type - (class-info (type-class-or-lose 'function)))) + (class-info (type-class-or-lose 'function))) + (:constructor %make-fun-type)) ;; true if the arguments are unrestrictive, i.e. * (wild-args nil :type boolean) ;; type describing the return values. This is a values type ;; when multiple values were specified for the return. (returns (missing-arg) :type ctype)) +(defun make-fun-type (&rest initargs + &key (args nil argsp) returns &allow-other-keys) + (if argsp + (if (eq args '*) + (if (eq returns *wild-type*) + (specifier-type 'function) + (%make-fun-type :wild-args t :returns returns)) + (multiple-value-bind (required optional rest keyp keywords allowp) + (args-types args) + (if (and (null required) + (null optional) + (eq rest *universal-type*) + (not keyp)) + (if (eq returns *wild-type*) + (specifier-type 'function) + (%make-fun-type :wild-args t :returns returns)) + (%make-fun-type :required required + :optional optional + :rest rest + :keyp keyp + :keywords keywords + :allowp allowp + :returns returns)))) + ;; FIXME: are we really sure that we won't make something that + ;; looks like a completely wild function here? + (apply #'%make-fun-type initargs))) ;;; The CONSTANT-TYPE structure represents a use of the CONSTANT-ARG ;;; "type specifier", which is only meaningful in function argument @@ -162,25 +260,14 @@ (if (consp high) (1- (type-bound-number high)) high))) - #!+negative-zero-is-not-zero - (float - ;; Canonicalize a low bound of (-0.0) to 0.0, and a high - ;; bound of (+0.0) to -0.0. - (values (if (and (consp low) - (floatp (car low)) - (zerop (car low)) - (minusp (float-sign (car low)))) - (float 0.0 (car low)) - low) - (if (and (consp high) - (floatp (car high)) - (zerop (car high)) - (plusp (float-sign (car high)))) - (float -0.0 (car high)) - high))) (t ;; no canonicalization necessary (values low high))) + (when (and (eq class 'rational) + (integerp canonical-low) + (integerp canonical-high) + (= canonical-low canonical-high)) + (setf class 'integer)) (%make-numeric-type :class class :format format :complexp complexp @@ -207,6 +294,7 @@ ;;; things such as SIMPLE-STRING. (defstruct (array-type (:include ctype (class-info (type-class-or-lose 'array))) + (:constructor %make-array-type) (:copier nil)) ;; the dimensions of the array, or * if unspecified. If a dimension ;; is unspecified, it is *. @@ -217,6 +305,7 @@ (element-type (missing-arg) :type ctype) ;; the element type as it is specialized in this implementation (specialized-element-type *wild-type* :type ctype)) +(define-cached-synonym make-array-type) ;;; A MEMBER-TYPE represent a use of the MEMBER type specifier. We ;;; bother with this at this level because MEMBER types are fairly @@ -225,14 +314,46 @@ (class-info (type-class-or-lose 'member)) (enumerable t)) (:copier nil) + (:constructor %make-member-type (members)) #-sb-xc-host (:pure nil)) ;; the things in the set, with no duplications (members nil :type list)) +(defun make-member-type (&key members) + (declare (type list members)) + ;; make sure that we've removed duplicates + (aver (= (length members) (length (remove-duplicates members)))) + ;; if we have a pair of zeros (e.g. 0.0d0 and -0.0d0), then we can + ;; canonicalize to (DOUBLE-FLOAT 0.0d0 0.0d0), because numeric + ;; ranges are compared by arithmetic operators (while MEMBERship is + ;; compared by EQL). -- CSR, 2003-04-23 + (let ((singlep (subsetp '(-0.0f0 0.0f0) members)) + (doublep (subsetp '(-0.0d0 0.0d0) members)) + #!+long-float + (longp (subsetp '(-0.0l0 0.0l0) members))) + (if (or singlep doublep #!+long-float longp) + (let (union-types) + (when singlep + (push (ctype-of 0.0f0) union-types) + (setf members (set-difference members '(-0.0f0 0.0f0)))) + (when doublep + (push (ctype-of 0.0d0) union-types) + (setf members (set-difference members '(-0.0d0 0.0d0)))) + #!+long-float + (when longp + (push (ctype-of 0.0l0) union-types) + (setf members (set-difference members '(-0.0l0 0.0l0)))) + (aver (not (null union-types))) + (make-union-type t + (if (null members) + union-types + (cons (%make-member-type members) + union-types)))) + (%make-member-type members)))) ;;; A COMPOUND-TYPE is a type defined out of a set of types, the ;;; common parent of UNION-TYPE and INTERSECTION-TYPE. (defstruct (compound-type (:include ctype - (might-contain-other-types? t)) + (might-contain-other-types-p t)) (:constructor nil) (:copier nil)) (types nil :type list :read-only t)) @@ -248,6 +369,7 @@ (class-info (type-class-or-lose 'union))) (:constructor %make-union-type (enumerable types)) (:copier nil))) +(define-cached-synonym make-union-type) ;;; An INTERSECTION-TYPE represents a use of the AND type specifier ;;; which we couldn't canonicalize to something simpler. Canonical form: @@ -285,17 +407,22 @@ ;; 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-raw-type + cdr-raw-type + &aux + (car-type (type-*-to-t car-raw-type)) + (cdr-type (type-*-to-t cdr-raw-type)))) (:copier nil)) ;; the CAR and CDR element types (to support ANSI (CONS FOO BAR) types) ;; ;; FIXME: Most or all other type structure slots could also be :READ-ONLY. (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) + (if (or (eq car-type *empty-type*) + (eq cdr-type *empty-type*)) + *empty-type* + (%make-cons-type car-type cdr-type))) ;;;; type utilities @@ -309,7 +436,7 @@ (logand (sxhash x) #x3FF)) :hash-bits 10 :init-wrapper !cold-init-forms) - ((orig eq)) + ((orig equal-but-no-car-recursion)) (let ((u (uncross orig))) (or (info :type :builtin u) (let ((spec (type-expand u))) @@ -317,15 +444,15 @@ ((and (not (eq spec u)) (info :type :builtin spec))) ((eq (info :type :kind spec) :instance) - (sb!xc:find-class spec)) - ((typep spec 'class) + (find-classoid spec)) + ((typep spec 'classoid) ;; There doesn't seem to be any way to translate ;; (TYPEP SPEC 'BUILT-IN-CLASS) into something which can be ;; executed on the host Common Lisp at cross-compilation time. #+sb-xc-host (error "stub: (TYPEP SPEC 'BUILT-IN-CLASS) on xc host") - (if (typep spec 'built-in-class) - (or (built-in-class-translation spec) spec) + (if (typep spec 'built-in-classoid) + (or (built-in-classoid-translation spec) spec) spec)) (t (let* (;; FIXME: This automatic promotion of FOO-style @@ -359,6 +486,12 @@ (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))) + ;;; Similar to MACROEXPAND, but expands DEFTYPEs. We don't bother ;;; returning a second value. (defun type-expand (form)