Record XREFs for symbols that name functions.
[sbcl.git] / src / code / pred.lisp
bloba4f1f5cd78fda5baf214f7369ca908b0edb11e5b
1 ;;;; predicate functions (EQUAL and friends, and type predicates)
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
12 (in-package "SB-IMPL")
14 ;;;; miscellaneous non-primitive predicates
16 (declaim (inline streamp))
17 (defun streamp (stream)
18 (typep stream 'stream))
20 ;;; These would only be called from %%TYPEP given a built-in-classoid.
21 ;;; Ordinarily TYPEP on either one would be transformed.
22 (defun sb-kernel::file-stream-p (x) (typep x 'file-stream))
23 (defun sb-kernel::string-stream-p (x) (typep x 'string-stream))
25 ;;; various (VECTOR FOO) type predicates, not implemented as simple
26 ;;; widetag tests
27 (macrolet
28 ((def ()
29 `(progn
30 ,@(loop for (name spec) in *vector-without-complex-typecode-infos*
31 collect `(defun ,name (x)
32 (or (typep x '(simple-array ,spec (*)))
33 (and (complex-vector-p x)
34 (do ((data (%array-data x) (%array-data data)))
35 ((not (array-header-p data)) (typep data '(simple-array ,spec (*))))))))))))
36 (def))
38 ;;; Is X an extended sequence?
39 (declaim (maybe-inline extended-sequence-p))
40 (defun extended-sequence-p (sb-c::object) ; name the argugment as required by transform
41 (macrolet ((transform ()
42 (sb-c::transform-instance-typep (find-classoid 'sequence))))
43 (transform)))
45 ;;; Is X a SEQUENCE? Harder than just (OR VECTOR LIST)
46 (defun sequencep (x)
47 (declare (inline extended-sequence-p))
48 (or (listp x) (vectorp x) (extended-sequence-p x)))
50 ;;;; primitive predicates. These must be supported directly by the
51 ;;;; compiler.
53 (defun not (object)
54 "Return T if X is NIL, otherwise return NIL."
55 (not object))
57 ;;; All the primitive type predicate wrappers share a parallel form.
58 ;;; These aren't so much "wrappers" as they are the actual installed DEFUNs.
59 ;;; I supposed they "wrap" a vop or source-transform.
60 (macrolet ((def-type-predicate-wrapper (pred)
61 `(defun ,pred (object)
62 ;; Document the standardized predicates and not the internal ones.
63 ,@(when (eq (sb-xc:symbol-package pred) *cl-package*)
64 (let* ((name (symbol-name pred))
65 (stem (string-left-trim "%" (string-right-trim "P-" name)))
66 (article (if (position (schar name 0) "AEIOU") "an" "a")))
67 (list (format nil
68 "Return true if OBJECT is ~A ~A, and NIL otherwise."
69 article
70 stem))))
71 ;; (falling through to low-level implementation)
72 (,pred object))))
73 (def-type-predicate-wrapper array-header-p)
74 (def-type-predicate-wrapper simple-array-header-p)
75 (def-type-predicate-wrapper arrayp)
76 (def-type-predicate-wrapper atom)
77 ;; Testing for BASE-CHAR-P is usually redundant on #-sb-unicode,
78 ;; remove it there completely so that #-sb-unicode build will
79 ;; break when it's used.
80 #+sb-unicode (def-type-predicate-wrapper base-char-p)
81 (def-type-predicate-wrapper base-string-p)
82 #+sb-unicode (def-type-predicate-wrapper character-string-p)
83 (def-type-predicate-wrapper bignump)
84 (def-type-predicate-wrapper bit-vector-p)
85 (def-type-predicate-wrapper characterp)
86 (def-type-predicate-wrapper code-component-p)
87 (def-type-predicate-wrapper consp)
88 (def-type-predicate-wrapper compiled-function-p)
89 (def-type-predicate-wrapper complexp)
90 (def-type-predicate-wrapper complex-double-float-p)
91 (def-type-predicate-wrapper complex-float-p)
92 #+long-float (def-type-predicate-wrapper complex-long-float-p)
93 (def-type-predicate-wrapper complex-rational-p)
94 (def-type-predicate-wrapper complex-single-float-p)
95 ;; (COMPLEX-VECTOR-P is not included here since it's awkward to express
96 ;; the type it tests for in the Common Lisp type system, and since it's
97 ;; only used in the implementation of a few specialized things.)
98 (def-type-predicate-wrapper double-float-p)
99 (def-type-predicate-wrapper fdefn-p)
100 (def-type-predicate-wrapper fixnump)
101 (def-type-predicate-wrapper floatp)
102 (def-type-predicate-wrapper functionp)
103 ;; SIMPLE-FUN-P is needed for constant folding in early warm load,
104 ;; and its absence would be obscured by the fact that
105 ;; CONSTANT-FUNCTION-CALL-P allows the call to fail.
106 (def-type-predicate-wrapper closurep)
107 (def-type-predicate-wrapper simple-fun-p)
108 (def-type-predicate-wrapper integerp)
109 (def-type-predicate-wrapper listp)
110 (def-type-predicate-wrapper long-float-p)
111 #-(or x86 x86-64 arm64 riscv) (def-type-predicate-wrapper lra-p)
112 (def-type-predicate-wrapper null)
113 (def-type-predicate-wrapper numberp)
114 (sb-c::when-vop-existsp (:translate pointerp)
115 (def-type-predicate-wrapper pointerp))
116 (def-type-predicate-wrapper rationalp)
117 (def-type-predicate-wrapper ratiop)
118 (def-type-predicate-wrapper realp)
119 (def-type-predicate-wrapper single-float-p)
120 #+sb-simd-pack (def-type-predicate-wrapper simd-pack-p)
121 #+sb-simd-pack-256 (def-type-predicate-wrapper simd-pack-256-p)
122 (def-type-predicate-wrapper %instancep)
123 (def-type-predicate-wrapper funcallable-instance-p)
124 (def-type-predicate-wrapper symbolp)
125 ;; The interpreter needs this because it assumes that any type spec
126 ;; in SB-C::*BACKEND-TYPE-PREDICATES* has a callable predicate.
127 (def-type-predicate-wrapper non-null-symbol-p)
128 (def-type-predicate-wrapper %other-pointer-p)
129 (def-type-predicate-wrapper system-area-pointer-p)
130 (def-type-predicate-wrapper unbound-marker-p)
131 (def-type-predicate-wrapper weak-pointer-p)
133 (sb-c::when-vop-existsp (:translate signed-byte-8-p)
134 (def-type-predicate-wrapper signed-byte-8-p))
135 (sb-c::when-vop-existsp (:translate signed-byte-16-p)
136 (def-type-predicate-wrapper signed-byte-16-p))
137 (sb-c::when-vop-existsp (:translate signed-byte-32-p)
138 (def-type-predicate-wrapper signed-byte-32-p))
139 #-64-bit
140 (def-type-predicate-wrapper unsigned-byte-32-p)
141 #+64-bit
142 (progn
143 (def-type-predicate-wrapper unsigned-byte-64-p)
144 (def-type-predicate-wrapper signed-byte-64-p))
145 ;; Specialized array types
146 (macrolet ((saetp-defs ()
147 `(progn
148 ,@(map 'list
149 (lambda (saetp)
150 `(def-type-predicate-wrapper
151 ,(symbolicate (sb-vm:saetp-primitive-type-name saetp) "-P")))
152 sb-vm:*specialized-array-element-type-properties*))))
153 (saetp-defs))
154 ;; Other array types
155 (def-type-predicate-wrapper simple-array-p)
156 (def-type-predicate-wrapper simple-rank-1-array-*-p)
157 (def-type-predicate-wrapper simple-string-p)
158 (def-type-predicate-wrapper stringp)
159 (def-type-predicate-wrapper vectorp))
161 (sb-c::when-vop-existsp (:translate car-eq-if-listp)
162 (defun car-eq-if-listp (value object)
163 (car-eq-if-listp value object)))
166 ;;; Return the specifier for the type of object. This is not simply
167 ;;; (TYPE-SPECIFIER (CTYPE-OF OBJECT)) because CTYPE-OF has different
168 ;;; goals than TYPE-OF. In particular, speed is more important than
169 ;;; precision here, and it is not permitted to return member types,
170 ;;; negation, union, or intersection types.
171 (defun type-of (object)
172 "Return the type of OBJECT."
173 (declare (explicit-check))
174 ;; We have special logic for everything except arrays.
175 ;; Arrays use CTYPE-OF and then convert the answer to a specifier.
176 (typecase object
177 (fixnum
178 (cond
179 ((<= 0 object 1) 'bit)
180 ((< object 0) 'fixnum)
181 (t `(integer 0 ,most-positive-fixnum))))
182 (integer
183 (if (>= object 0)
184 `(integer ,(1+ most-positive-fixnum))
185 'bignum))
186 (character
187 (typecase object
188 (standard-char 'standard-char)
189 (base-char 'base-char)
190 (extended-char 'extended-char)))
191 ;; We "have to" (or have chosen to) pick off KEYWORD and BOOLEAN,
192 ;; so we may as well have a branch that returns early for any SYMBOL
193 ;; rather than falling into the CLASSOID-based test. But then since we
194 ;; do that, we also have to pick off NIL so that it doesn't say SYMBOL.
195 (symbol
196 (cond ((eq object t) 'boolean)
197 ((eq object nil) 'null)
198 ((eq (sb-xc:symbol-package object) *keyword-package*) 'keyword)
199 (t 'symbol)))
200 (array
201 (let ((etype (sb-vm::array-element-ctype object)))
202 ;; Obviously :COMPLEXP is known to be T or NIL, but it's not allowed to
203 ;; return (NOT SIMPLE-ARRAY), so use :MAYBE in lieu of T.
204 (type-specifier
205 (make-array-type (array-dimensions object)
206 :complexp (if (typep object 'simple-array) nil :maybe)
207 :element-type etype
208 :specialized-element-type etype))))
209 ((or complex #+sb-simd-pack simd-pack #+sb-simd-pack-256 simd-pack-256)
210 (type-specifier (ctype-of object)))
211 (simple-fun 'compiled-function)
213 (let ((layout (layout-of object)))
214 (when (= (get-lisp-obj-address layout) 0)
215 (return-from type-of
216 (if (functionp object) 'funcallable-instance 'instance)))
217 (let* ((classoid (layout-classoid layout))
218 (name (classoid-name classoid)))
219 ;; FIXME: should the first test be (not (or (%instancep) (%funcallable-instance-p)))?
220 ;; God forbid anyone makes anonymous classes of generic functions.
221 (cond ((not (%instancep object))
222 name)
223 ((eq name 'sb-alien-internals:alien-value)
224 `(alien ,(sb-alien-internals:unparse-alien-type
225 (sb-alien-internals:alien-value-type object))))
227 (let ((pname (classoid-proper-name classoid)))
228 (if (classoid-p pname)
229 (classoid-pcl-class pname)
230 pname)))))))))
232 ;;;; equality predicates
234 ;;; This is real simple, 'cause the compiler takes care of it.
235 (defun eq (obj1 obj2)
236 "Return T if OBJ1 and OBJ2 are the same object, otherwise NIL."
237 (eq obj1 obj2))
239 (declaim (inline %eql))
240 (defun %eql (obj1 obj2)
241 #+x86-64 (eql obj1 obj2) ; vop fully implements all cases of EQL
242 #-x86-64 ; else this is the only full implementation of EQL
243 (or (eq obj1 obj2)
244 (if (or (typep obj2 'fixnum)
245 (not (typep obj2 'number)))
247 (macrolet ((foo (&rest stuff)
248 `(typecase obj2
249 ,@(mapcar (lambda (foo)
250 (let ((type (car foo))
251 (fn (cadr foo)))
252 `(,type
253 (and (typep obj1 ',type)
254 (,fn obj1 obj2)))))
255 stuff))))
256 (foo
257 (single-float eql)
258 (double-float eql)
259 #+long-float
260 (long-float eql)
261 (bignum
262 #.(sb-c::if-vop-existsp (:named sb-vm::%eql/integer)
263 'eql
264 '(lambda (x y)
265 (zerop (bignum-compare x y)))))
266 (ratio
267 (lambda (x y)
268 (and (eql (numerator x) (numerator y))
269 (eql (denominator x) (denominator y)))))
270 ((complex single-float)
271 (lambda (x y)
272 (and (eql (realpart x) (realpart y))
273 (eql (imagpart x) (imagpart y)))))
274 ((complex double-float)
275 (lambda (x y)
276 (and (eql (realpart x) (realpart y))
277 (eql (imagpart x) (imagpart y)))))
278 ((complex rational)
279 (lambda (x y)
280 (and (eql (realpart x) (realpart y))
281 (eql (imagpart x) (imagpart y))))))))))
283 (defun eql (x y)
284 "Return T if OBJ1 and OBJ2 represent the same object, otherwise NIL."
285 ;; On x86-64, EQL is just an interpreter stub for a vop.
286 ;; For others it's a call to the implementation of generic EQL.
287 (#+x86-64 eql #-x86-64 %eql x y))
289 (defun bit-vector-= (x y)
290 (declare (type bit-vector x y))
291 (cond ((eq x y))
292 ((and (simple-bit-vector-p x)
293 (simple-bit-vector-p y))
294 (bit-vector-= x y)) ; DEFTRANSFORM
296 (and (= (length x) (length y))
297 (with-array-data ((x x) (start-x) (end-x) :force-inline t
298 :check-fill-pointer t)
299 (with-array-data ((y y) (start-y) (end-y) :force-inline t
300 :check-fill-pointer t)
301 (declare (ignore end-y))
302 (loop for x-i fixnum from start-x below end-x
303 for y-i fixnum from start-y
304 always (or (= (sbit x x-i)
305 (sbit y y-i))))))))))
307 (defun equal (x y)
308 "Return T if X and Y are EQL or if they are structured components whose
309 elements are EQUAL. Strings and bit-vectors are EQUAL if they are the same
310 length and have identical components. Other arrays must be EQ to be EQUAL."
311 ;; Non-tail self-recursion implemented with a local auxiliary function
312 ;; is a lot faster than doing it the straightforward way (at least
313 ;; on x86oids) due to calling convention differences. -- JES, 2005-12-30
314 (labels ((equal-aux (x y)
315 (cond ((%eql x y)
317 ((consp x)
318 (and (consp y)
319 (equal-aux (car x) (car y))
320 (equal-aux (cdr x) (cdr y))))
321 ((stringp x)
322 (and (stringp y) (string= x y)))
323 ;; We could remove this case by ensuring that MAKE-PATHNAME,
324 ;; PARSE-NAMESTRING, MERGE-PATHNAME, etc look in a weak hash-based
325 ;; thing first for an EQUAL pathname, ensuring that if two pathnames
326 ;; are EQUAL then they are EQ. That would elide this test at the
327 ;; expense of pathname construction which seems like a good tradeoff.
328 ((pathnamep x)
329 (and (pathnamep y) (pathname= x y)))
330 ((bit-vector-p x)
331 (and (bit-vector-p y)
332 (bit-vector-= x y)))
333 (t nil))))
334 ;; Use MAYBE-INLINE to get the inline expansion only once (instead
335 ;; of 200 times with INLINE). -- JES, 2005-12-30
336 (declare (maybe-inline equal-aux))
337 (equal-aux x y)))
339 ;;; Like EQUAL, but any two gensyms whose names are STRING= are equalish.
340 (defun fun-names-equalish (x y)
341 (named-let recurse ((x x) (y y))
342 (cond ((eql x y) t) ; not performance-critical: don't inline %EQL here
343 ((consp x) (and (consp y)
344 (recurse (car x) (car y))
345 (recurse (cdr x) (cdr y))))
346 ((and (symbolp x) (not (sb-xc:symbol-package x)))
347 (and (symbolp y) (not (sb-xc:symbol-package y)) (string= x y)))
349 (equal x y)))))
351 ;;; EQUALP comparison of HASH-TABLE values
352 ;;; Can be called only if both X and Y are definitely hash-tables.
353 (defun hash-table-equalp (x y)
354 (declare (type hash-table x y) (explicit-check))
355 (or (eq x y)
356 (and (eql (hash-table-count x) (hash-table-count y))
357 (eql (hash-table-test x) (hash-table-test y))
358 (block comparison-of-entries
359 (maphash (lambda (key x-value)
360 (multiple-value-bind (y-value y-value-p)
361 (gethash key y)
362 (unless (and y-value-p (equalp x-value y-value))
363 (return-from comparison-of-entries nil))))
365 t))))
367 (macrolet ((slot-ref-equalp ()
368 `(let ((x-el (%instance-ref x i))
369 (y-el (%instance-ref y i)))
370 (or (eq x-el y-el) (equalp x-el y-el)))))
371 (defun instance-equalp (x y)
372 (declare (optimize (safety 0)))
373 (loop for i downfrom (1- (%instance-length x)) to sb-vm:instance-data-start
374 always (slot-ref-equalp)))
375 (defun instance-equalp* (comparators x y)
376 (declare (optimize (safety 0))
377 (simple-vector comparators)
378 (type instance x y))
379 ;; See remark at the source code for %TARGET-DEFSTRUCT
380 ;; explaining how to use the vector of comparators.
381 (loop for i downfrom (1- (%instance-length x)) to sb-vm:instance-data-start
382 for test = (data-vector-ref comparators (- i sb-vm:instance-data-start))
383 always (cond ((eql test 0) (slot-ref-equalp))
384 ((functionp test) (funcall test i x y))
385 (t)))))
387 (macrolet ((numericp (v)
388 (let ((widetags
389 (map 'list #'sb-vm:saetp-typecode
390 (remove-if (lambda (x)
391 (not (typep (sb-vm:saetp-ctype x) 'numeric-type)))
392 sb-vm:*specialized-array-element-type-properties*))))
393 `(%other-pointer-subtype-p ,v ',widetags)))
394 (compare-loop (typespec)
395 `(let ((x (truly-the (simple-array ,typespec 1) x))
396 (y (truly-the (simple-array ,typespec 1) y)))
397 (loop for x-i fixnum from start-x below end-x
398 for y-i fixnum from start-y
399 always (= (aref x x-i) (aref y y-i))))))
400 (defun array-equalp (a b)
401 (flet
402 ((data-vector-compare (x y start-x end-x start-y)
403 (declare (index start-x end-x start-y)
404 (optimize (sb-c:insert-array-bounds-checks 0)))
405 (let ((xtag (%other-pointer-widetag (truly-the (simple-array * 1) x)))
406 (ytag (%other-pointer-widetag (truly-the (simple-array * 1) y))))
407 (case (if (= xtag ytag) xtag 0)
408 (#.sb-vm:simple-vector-widetag
409 (let ((x (truly-the simple-vector x))
410 (y (truly-the simple-vector y)))
411 (loop for x-i fixnum from start-x below end-x
412 for y-i fixnum from start-y
413 always (let ((a (svref x x-i)) (b (svref y y-i)))
414 (or (eq a b) (equalp a b))))))
415 ;; Special-case the important array types that would cause consing in aref.
416 ;; Though (UNSIGNED-BYTE 62) and (UNSIGNED-BYTE 63) arrays exist,
417 ;; I highly doubt that they occur anywhere except in contrived code
418 ;; that does nothing but test that those types exist. i.e. They are
419 ;; beyond worthless, and are frankly wasteful of space in array dispatch
420 ;; scenarios, or to put it mildy: I disagree with their existence per se.
421 #+64-bit (#.sb-vm:simple-array-unsigned-byte-64-widetag
422 (compare-loop (unsigned-byte 64)))
423 #+64-bit (#.sb-vm:simple-array-signed-byte-64-widetag
424 (compare-loop (signed-byte 64)))
425 #-64-bit (#.sb-vm:simple-array-unsigned-byte-32-widetag
426 (compare-loop (unsigned-byte 32)))
427 #-64-bit (#.sb-vm:simple-array-signed-byte-32-widetag
428 (compare-loop (signed-byte 32)))
429 ;; SINGLE-FLOAT wouldn't cons on 64-bit, but it should be treated
430 ;; no less efficiently than DOUBLE-FLOAT.
431 (#.sb-vm:simple-array-single-float-widetag
432 (compare-loop single-float))
433 (#.sb-vm:simple-array-double-float-widetag
434 (compare-loop double-float))
435 (#.sb-vm:simple-array-complex-single-float-widetag
436 (compare-loop (complex single-float)))
437 (#.sb-vm:simple-array-complex-double-float-widetag
438 (compare-loop (complex double-float)))
440 (let* ((reffers %%data-vector-reffers%%)
441 (getter-x (truly-the function (svref reffers xtag)))
442 (getter-y (truly-the function (svref reffers ytag))))
443 ;; The arrays won't both be strings, because EQUALP has a case for that.
444 ;; If they're both numeric, use = as the test.
445 (if (and (numericp x) (numericp y))
446 (loop for x-i fixnum from start-x below end-x
447 for y-i fixnum from start-y
448 always (= (funcall getter-x x x-i) (funcall getter-y y y-i)))
449 ;; Everything else
450 (loop for x-i fixnum from start-x below end-x
451 for y-i fixnum from start-y
452 for x-el = (funcall getter-x x x-i)
453 for y-el = (funcall getter-y y y-i)
454 always (or (eq x-el y-el)
455 (equalp x-el y-el))))))))))
456 (if (vectorp (truly-the array a))
457 (and (vectorp (truly-the array b))
458 (= (length a) (length b))
459 (with-array-data ((x a) (start-x) (end-x)
460 :force-inline t :check-fill-pointer t)
461 (with-array-data ((y b) (start-y) (end-y)
462 :force-inline t :check-fill-pointer t)
463 (declare (ignore end-y))
464 (data-vector-compare x y start-x end-x start-y))))
465 (let ((rank (array-rank (truly-the array a))))
466 (and (= rank (array-rank (truly-the array b)))
467 (dotimes (axis rank t)
468 (unless (= (%array-dimension a axis)
469 (%array-dimension b axis))
470 (return nil)))
471 (with-array-data ((x a) (start-x) (end-x)
472 :force-inline t :array-header-p t)
473 (with-array-data ((y b) (start-y) (end-y)
474 :force-inline t :array-header-p t)
475 (declare (ignore end-y))
476 (data-vector-compare x y start-x end-x start-y)))))))))
478 (defun equalp (x y)
479 "Just like EQUAL, but more liberal in several respects.
480 Numbers may be of different types, as long as the values are identical
481 after coercion. Characters may differ in alphabetic case. Vectors and
482 arrays must have identical dimensions and EQUALP elements, but may differ
483 in their type restriction. The elements of structured components
484 are compared with EQUALP."
485 (cond ((eq x y) t)
486 ((characterp x) (and (characterp y) (char-equal x y)))
487 ((numberp x) (and (numberp y) (= x y)))
488 ((consp x)
489 (and (consp y)
490 (equalp (car x) (car y))
491 (equalp (cdr x) (cdr y))))
492 ((%instancep x)
493 (and (%instancep y)
494 (let ((layout (%instance-layout x)))
495 (and (logtest (logior +structure-layout-flag+ +pathname-layout-flag+)
496 (layout-flags layout))
497 (eq (%instance-layout y) layout)
498 (funcall (layout-equalp-impl layout) x y)))))
499 ((arrayp x)
500 (and (arrayp y)
501 ;; string-equal is nearly 2x the speed of array-equalp for comparing strings
502 (cond ((and (stringp x) (stringp y)) (string-equal x y))
503 ((and (bit-vector-p x) (bit-vector-p y)) (bit-vector-= x y))
504 (t (array-equalp x y)))))
505 (t nil)))
507 #-sb-show ;; I don't know why these tests crash with #+sb-show
508 (let ((test-cases '((0.0 -0.0 t)
509 (0.0 1.0 nil)
510 (#c(1 0) #c(1.0 0.0) t)
511 (#c(0 1) #c(0.0 1.0) t)
512 ;; 11/10 is unequal to real 1.1 due to roundoff error.
513 ;; COMPLEX here is a red herring
514 (#c(1.1 0.0) #c(11/10 0) nil)
515 ("Hello" "hello" t)
516 ("Hello" #(#\h #\E #\l #\l #\o) t)
517 ("Hello" "goodbye" nil))))
518 (dolist (test-case test-cases)
519 (destructuring-bind (x y expected-result) test-case
520 (let* ((result (equalp x y))
521 (bresult (if result 1 0))
522 (expected-bresult (if expected-result 1 0)))
523 (unless (= bresult expected-bresult)
524 ;; If a test fails, there's a chance of getting into a recursive error here
525 ;; because, among other things, *BASE-CHAR-NAME-ALIST* has not been filled in,
526 ;; so then you're get into an error printing#(#\h #\E #\l #\l #\o).
527 ;; Hopefully the write-string calls will work though.
528 (progn
529 (write-string "test failed: ")
530 (write (get-lisp-obj-address x) :base 16 :radix t)
531 (write-char #\space)
532 (write (get-lisp-obj-address y) :base 16 :radix t)
533 (terpri))
534 (error "failed test (EQUALP ~S ~S)" x y))))))