(defun vector-t-p (x)
(or (simple-vector-p x)
(and (complex-vector-p x)
- (simple-vector-p (%array-data-vector x)))))
+ (do ((data (%array-data-vector x) (%array-data-vector data)))
+ ((not (array-header-p data)) (simple-vector-p data))))))
\f
;;;; primitive predicates. These must be supported directly by the
;;;; compiler.
;;; All the primitive type predicate wrappers share a parallel form..
(macrolet ((def-type-predicate-wrapper (pred)
- (let* ((name (symbol-name pred))
- (stem (string-left-trim "%" (string-right-trim "P-" name)))
- (article (if (position (schar name 0) "AEIOU") "an" "a")))
- `(defun ,pred (object)
- ,(format nil
- "Return true if OBJECT is ~A ~A, and NIL otherwise."
- article
- stem)
- ;; (falling through to low-level implementation)
- (,pred object)))))
+ (let* ((name (symbol-name pred))
+ (stem (string-left-trim "%" (string-right-trim "P-" name)))
+ (article (if (position (schar name 0) "AEIOU") "an" "a")))
+ `(defun ,pred (object)
+ ,(format nil
+ "Return true if OBJECT is ~A ~A, and NIL otherwise."
+ article
+ stem)
+ ;; (falling through to low-level implementation)
+ (,pred object)))))
(def-type-predicate-wrapper array-header-p)
(def-type-predicate-wrapper arrayp)
(def-type-predicate-wrapper atom)
(def-type-predicate-wrapper base-char-p)
+ (def-type-predicate-wrapper base-string-p)
+ #!+sb-unicode (def-type-predicate-wrapper character-string-p)
(def-type-predicate-wrapper bignump)
(def-type-predicate-wrapper bit-vector-p)
(def-type-predicate-wrapper characterp)
;; the type it tests for in the Common Lisp type system, and since it's
;; only used in the implementation of a few specialized things.)
(def-type-predicate-wrapper double-float-p)
+ (def-type-predicate-wrapper extended-char-p)
(def-type-predicate-wrapper fdefn-p)
(def-type-predicate-wrapper fixnump)
(def-type-predicate-wrapper floatp)
(def-type-predicate-wrapper integerp)
(def-type-predicate-wrapper listp)
(def-type-predicate-wrapper long-float-p)
+ #!+(and sb-thread sb-lutex)
+ (def-type-predicate-wrapper lutexp)
(def-type-predicate-wrapper lra-p)
(def-type-predicate-wrapper null)
(def-type-predicate-wrapper numberp)
(def-type-predicate-wrapper ratiop)
(def-type-predicate-wrapper realp)
(def-type-predicate-wrapper short-float-p)
- (def-type-predicate-wrapper sb!kernel:simple-array-p)
+ (def-type-predicate-wrapper simple-array-p)
(def-type-predicate-wrapper simple-bit-vector-p)
+ (def-type-predicate-wrapper simple-base-string-p)
+ #!+sb-unicode (def-type-predicate-wrapper simple-character-string-p)
(def-type-predicate-wrapper simple-string-p)
(def-type-predicate-wrapper simple-vector-p)
(def-type-predicate-wrapper single-float-p)
(def-type-predicate-wrapper system-area-pointer-p)
(def-type-predicate-wrapper weak-pointer-p)
(def-type-predicate-wrapper vectorp)
+ #!+#.(cl:if (cl:= 32 sb!vm:n-word-bits) '(and) '(or))
(def-type-predicate-wrapper unsigned-byte-32-p)
+ #!+#.(cl:if (cl:= 32 sb!vm:n-word-bits) '(and) '(or))
(def-type-predicate-wrapper signed-byte-32-p)
+ #!+#.(cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or))
+ (def-type-predicate-wrapper unsigned-byte-64-p)
+ #!+#.(cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or))
+ (def-type-predicate-wrapper signed-byte-64-p)
+ (def-type-predicate-wrapper simple-array-nil-p)
(def-type-predicate-wrapper simple-array-unsigned-byte-2-p)
(def-type-predicate-wrapper simple-array-unsigned-byte-4-p)
(def-type-predicate-wrapper simple-array-unsigned-byte-8-p)
#!+long-float (def-type-predicate-wrapper simple-array-long-float-p)
(def-type-predicate-wrapper simple-array-complex-single-float-p)
(def-type-predicate-wrapper simple-array-complex-double-float-p)
- #!+long-float (def-type-predicate-wrapper simple-array-complex-long-float-p))
+ #!+long-float (def-type-predicate-wrapper simple-array-complex-long-float-p)
+ (def-type-predicate-wrapper vector-nil-p))
\f
;;; Return the specifier for the type of object. This is not simply
;;; (TYPE-SPECIFIER (CTYPE-OF OBJECT)) because CTYPE-OF has different
(defun type-of (object)
#!+sb-doc
"Return the type of OBJECT."
- (if (typep object '(or function array complex))
- (type-specifier (ctype-of object))
- (let* ((classoid (layout-classoid (layout-of object)))
- (name (classoid-name classoid)))
- (if (typep object 'instance)
- (case name
- (sb!alien-internals:alien-value
- `(sb!alien:alien
- ,(sb!alien-internals:unparse-alien-type
- (sb!alien-internals:alien-value-type object))))
- (t
- (classoid-proper-name classoid)))
- name))))
+ (typecase object
+ (fixnum
+ (cond
+ ((<= 0 object 1) 'bit)
+ ((< object 0) 'fixnum)
+ (t '(integer 0 #.sb!xc:most-positive-fixnum))))
+ (integer
+ (if (>= object 0)
+ '(integer #.(1+ sb!xc:most-positive-fixnum))
+ 'bignum))
+ (standard-char 'standard-char)
+ (base-char 'base-char)
+ (extended-char 'extended-char)
+ ((member t) 'boolean)
+ (keyword 'keyword)
+ ((or array complex) (type-specifier (ctype-of object)))
+ (t
+ (let* ((classoid (layout-classoid (layout-of object)))
+ (name (classoid-name classoid)))
+ (if (%instancep object)
+ (case name
+ (sb!alien-internals:alien-value
+ `(sb!alien:alien
+ ,(sb!alien-internals:unparse-alien-type
+ (sb!alien-internals:alien-value-type object))))
+ (t
+ (let ((pname (classoid-proper-name classoid)))
+ (if (classoid-p pname)
+ (classoid-pcl-class pname)
+ pname))))
+ name)))))
\f
;;;; equality predicates
"Return T if OBJ1 and OBJ2 are the same object, otherwise NIL."
(eq obj1 obj2))
+(declaim (inline %eql))
+(defun %eql (obj1 obj2)
+ #!+sb-doc
+ "Return T if OBJ1 and OBJ2 represent the same object, otherwise NIL."
+ (or (eq obj1 obj2)
+ (if (or (typep obj2 'fixnum)
+ (not (typep obj2 'number)))
+ nil
+ (macrolet ((foo (&rest stuff)
+ `(typecase obj2
+ ,@(mapcar (lambda (foo)
+ (let ((type (car foo))
+ (fn (cadr foo)))
+ `(,type
+ (and (typep obj1 ',type)
+ (,fn obj1 obj2)))))
+ stuff))))
+ (foo
+ (single-float eql)
+ (double-float eql)
+ #!+long-float
+ (long-float eql)
+ (bignum
+ (lambda (x y)
+ (zerop (bignum-compare x y))))
+ (ratio
+ (lambda (x y)
+ (and (eql (numerator x) (numerator y))
+ (eql (denominator x) (denominator y)))))
+ (complex
+ (lambda (x y)
+ (and (eql (realpart x) (realpart y))
+ (eql (imagpart x) (imagpart y))))))))))
+
+(defun eql (x y)
+ (%eql x y))
+
(defun bit-vector-= (x y)
(declare (type bit-vector x y))
(if (and (simple-bit-vector-p x)
- (simple-bit-vector-p y))
+ (simple-bit-vector-p y))
(bit-vector-= x y) ; DEFTRANSFORM
(and (= (length x) (length y))
- (do ((i 0 (1+ i))
- (length (length x)))
- ((= i length) t)
- (declare (fixnum i))
- (unless (= (bit x i) (bit y i))
- (return nil))))))
+ (do ((i 0 (1+ i))
+ (length (length x)))
+ ((= i length) t)
+ (declare (fixnum i))
+ (unless (= (bit x i) (bit y i))
+ (return nil))))))
(defun equal (x y)
#!+sb-doc
- "Return T if X and Y are EQL or if they are structured components
- whose elements are EQUAL. Strings and bit-vectors are EQUAL if they
- are the same length and have identical components. Other arrays must be
- EQ to be EQUAL."
- (cond ((eql x y) t)
- ((consp x)
- (and (consp y)
- (equal (car x) (car y))
- (equal (cdr x) (cdr y))))
- ((stringp x)
- (and (stringp y) (string= x y)))
- ((pathnamep x)
- (and (pathnamep y) (pathname= x y)))
- ((bit-vector-p x)
- (and (bit-vector-p y)
- (bit-vector-= x y)))
- (t nil)))
+ "Return T if X and Y are EQL or if they are structured components whose
+elements are EQUAL. Strings and bit-vectors are EQUAL if they are the same
+length and have identical components. Other arrays must be EQ to be EQUAL."
+ ;; Non-tail self-recursion implemented with a local auxiliary function
+ ;; is a lot faster than doing it the straightforward way (at least
+ ;; on x86oids) due to calling convention differences. -- JES, 2005-12-30
+ (labels ((equal-aux (x y)
+ (cond ((%eql x y)
+ t)
+ ((consp x)
+ (and (consp y)
+ (equal-aux (car x) (car y))
+ (equal-aux (cdr x) (cdr y))))
+ ((stringp x)
+ (and (stringp y) (string= x y)))
+ ((pathnamep x)
+ (and (pathnamep y) (pathname= x y)))
+ ((bit-vector-p x)
+ (and (bit-vector-p y)
+ (bit-vector-= x y)))
+ (t nil))))
+ ;; Use MAYBE-INLINE to get the inline expansion only once (instead
+ ;; of 200 times with INLINE). -- JES, 2005-12-30
+ (declare (maybe-inline equal-aux))
+ (equal-aux x y)))
;;; EQUALP comparison of HASH-TABLE values
(defun hash-table-equalp (x y)
(declare (type hash-table x y))
(or (eq x y)
(and (hash-table-p y)
- (eql (hash-table-count x) (hash-table-count y))
- (eql (hash-table-test x) (hash-table-test y))
- (block comparison-of-entries
- (maphash (lambda (key x-value)
- (multiple-value-bind (y-value y-value-p)
- (gethash key y)
- (unless (and y-value-p (equalp x-value y-value))
- (return-from comparison-of-entries nil))))
- x)
- t))))
+ (eql (hash-table-count x) (hash-table-count y))
+ (eql (hash-table-test x) (hash-table-test y))
+ (block comparison-of-entries
+ (maphash (lambda (key x-value)
+ (multiple-value-bind (y-value y-value-p)
+ (gethash key y)
+ (unless (and y-value-p (equalp x-value y-value))
+ (return-from comparison-of-entries nil))))
+ x)
+ t))))
(defun equalp (x y)
#+nil ; KLUDGE: If doc string, should be accurate: Talk about structures
arrays must have identical dimensions and EQUALP elements, but may differ
in their type restriction."
(cond ((eq x y) t)
- ((characterp x) (and (characterp y) (char-equal x y)))
- ((numberp x) (and (numberp y) (= x y)))
- ((consp x)
- (and (consp y)
- (equalp (car x) (car y))
- (equalp (cdr x) (cdr y))))
- ((pathnamep x)
- (and (pathnamep y) (pathname= x y)))
- ((hash-table-p x)
- (and (hash-table-p y)
- (hash-table-equalp x y)))
- ((typep x 'instance)
- (let* ((layout-x (%instance-layout x))
- (len (layout-length layout-x)))
- (and (typep y 'instance)
- (eq layout-x (%instance-layout y))
- (structure-classoid-p (layout-classoid layout-x))
- (do ((i 1 (1+ i)))
- ((= i len) t)
- (declare (fixnum i))
- (let ((x-el (%instance-ref x i))
- (y-el (%instance-ref y i)))
- (unless (or (eq x-el y-el)
- (equalp x-el y-el))
- (return nil)))))))
- ((vectorp x)
- (let ((length (length x)))
- (and (vectorp y)
- (= length (length y))
- (dotimes (i length t)
- (let ((x-el (aref x i))
- (y-el (aref y i)))
- (unless (or (eq x-el y-el)
- (equalp x-el y-el))
- (return nil)))))))
- ((arrayp x)
- (and (arrayp y)
- (= (array-rank x) (array-rank y))
- (dotimes (axis (array-rank x) t)
- (unless (= (array-dimension x axis)
- (array-dimension y axis))
- (return nil)))
- (dotimes (index (array-total-size x) t)
- (let ((x-el (row-major-aref x index))
- (y-el (row-major-aref y index)))
- (unless (or (eq x-el y-el)
- (equalp x-el y-el))
- (return nil))))))
- (t nil)))
+ ((characterp x) (and (characterp y) (char-equal x y)))
+ ((numberp x) (and (numberp y) (= x y)))
+ ((consp x)
+ (and (consp y)
+ (equalp (car x) (car y))
+ (equalp (cdr x) (cdr y))))
+ ((pathnamep x)
+ (and (pathnamep y) (pathname= x y)))
+ ((hash-table-p x)
+ (and (hash-table-p y)
+ (hash-table-equalp x y)))
+ ((%instancep x)
+ (let* ((layout-x (%instance-layout x))
+ (len (layout-length layout-x)))
+ (and (%instancep y)
+ (eq layout-x (%instance-layout y))
+ (structure-classoid-p (layout-classoid layout-x))
+ (do ((i 1 (1+ i)))
+ ((= i len) t)
+ (declare (fixnum i))
+ (let ((x-el (%instance-ref x i))
+ (y-el (%instance-ref y i)))
+ (unless (or (eq x-el y-el)
+ (equalp x-el y-el))
+ (return nil)))))))
+ ((vectorp x)
+ (let ((length (length x)))
+ (and (vectorp y)
+ (= length (length y))
+ (dotimes (i length t)
+ (let ((x-el (aref x i))
+ (y-el (aref y i)))
+ (unless (or (eq x-el y-el)
+ (equalp x-el y-el))
+ (return nil)))))))
+ ((arrayp x)
+ (and (arrayp y)
+ (= (array-rank x) (array-rank y))
+ (dotimes (axis (array-rank x) t)
+ (unless (= (array-dimension x axis)
+ (array-dimension y axis))
+ (return nil)))
+ (dotimes (index (array-total-size x) t)
+ (let ((x-el (row-major-aref x index))
+ (y-el (row-major-aref y index)))
+ (unless (or (eq x-el y-el)
+ (equalp x-el y-el))
+ (return nil))))))
+ (t nil)))
(/show0 "about to do test cases in pred.lisp")
#!+sb-test
(let ((test-cases `((0.0 ,(load-time-value (make-unportable-float :single-float-negative-zero)) t)
- (0.0 1.0 nil)
- (#c(1 0) #c(1.0 0) t)
- (#c(1.1 0) #c(11/10 0) nil) ; due to roundoff error
- ("Hello" "hello" t)
- ("Hello" #(#\h #\E #\l #\l #\o) t)
- ("Hello" "goodbye" nil))))
+ (0.0 1.0 nil)
+ (#c(1 0) #c(1.0 0) t)
+ (#c(1.1 0) #c(11/10 0) nil) ; due to roundoff error
+ ("Hello" "hello" t)
+ ("Hello" #(#\h #\E #\l #\l #\o) t)
+ ("Hello" "goodbye" nil))))
(/show0 "TEST-CASES bound in pred.lisp")
(dolist (test-case test-cases)
(/show0 "about to do a TEST-CASE in pred.lisp")
(destructuring-bind (x y expected-result) test-case
(let* ((result (equalp x y))
- (bresult (if result 1 0))
- (expected-bresult (if expected-result 1 0)))
- (unless (= bresult expected-bresult)
- (/show0 "failing test in pred.lisp")
- (error "failed test (EQUALP ~S ~S)" x y))))))
+ (bresult (if result 1 0))
+ (expected-bresult (if expected-result 1 0)))
+ (unless (= bresult expected-bresult)
+ (/show0 "failing test in pred.lisp")
+ (error "failed test (EQUALP ~S ~S)" x y))))))
(/show0 "done with test cases in pred.lisp")