comparison lisp/cl-macs.el @ 4794:8484c6c76837

Merge.
author Aidan Kehoe <kehoea@parhasard.net>
date Thu, 31 Dec 2009 15:47:03 +0000
parents 8b50bee3c88c 95b04754ea8c
children 6ee5e50a8772
comparison
equal deleted inserted replaced
4793:8b50bee3c88c 4794:8484c6c76837
3348 (define-compiler-macro regexp-quote (&whole form string) 3348 (define-compiler-macro regexp-quote (&whole form string)
3349 (if (stringp string) 3349 (if (stringp string)
3350 (regexp-quote string) 3350 (regexp-quote string)
3351 form)) 3351 form))
3352 3352
3353 (define-compiler-macro equalp (&whole form x y)
3354 "Expand calls to `equalp' where X or Y is a constant expression.
3355
3356 Much of the processing that `equalp' does is dependent on the types of both
3357 of its arguments, and with type information for one of them, we can
3358 eliminate much of the body of the function at compile time.
3359
3360 Where both X and Y are constant expressions, `equalp' is evaluated at
3361 compile time by byte-optimize.el--this compiler macro passes FORM through to
3362 the byte optimizer in those cases."
3363 ;; Cases where both arguments are constant are handled in
3364 ;; byte-optimize.el, we only need to handle those cases where one is
3365 ;; constant here.
3366 (let* ((equalp-sym (eval-when-compile (gensym)))
3367 (let-form '(progn))
3368 (check-bit-vector t)
3369 (check-string t)
3370 (original-y y)
3371 equalp-temp checked)
3372 (macrolet
3373 ((unordered-check (check)
3374 `(prog1
3375 (setq checked
3376 (or ,check
3377 (prog1 ,(sublis '((x . y) (y . x)) check :test #'eq)
3378 (setq equalp-temp x x y y equalp-temp))))
3379 (when checked
3380 (unless (symbolp y)
3381 (setq let-form `(let ((,equalp-sym ,y))) y equalp-sym))))))
3382 ;; In the bodies of the below clauses, x is always a constant expression
3383 ;; of the type we're interested in, and y is always a symbol that refers
3384 ;; to the result non-constant side of the comparison.
3385 (cond ((unordered-check (and (arrayp x) (not (cl-const-expr-p y))))
3386 ;; Strings and other arrays. A vector containing the same
3387 ;; character elements as a given string is equalp to that string;
3388 ;; a bit-vector can only be equalp to a string if both are
3389 ;; zero-length.
3390 (cond
3391 ((member x '("" #* []))
3392 ;; No need to protect against multiple evaluation here:
3393 `(and (member ,original-y '("" #* [])) t))
3394 ((stringp x)
3395 `(,@let-form
3396 (if (stringp ,y)
3397 (eq t (compare-strings ,x nil nil
3398 ,y nil nil t))
3399 (if (vectorp ,y)
3400 (cl-string-vector-equalp ,x ,y)))))
3401 ((bit-vector-p x)
3402 `(,@let-form
3403 (if (bit-vector-p ,y)
3404 ;; No need to call equalp on each element here:
3405 (equal ,x ,y)
3406 (if (vectorp ,y)
3407 (cl-bit-vector-vector-equalp ,x ,y)))))
3408 (t
3409 (loop
3410 for elt across x
3411 ;; We may not need to check the other argument if it's a
3412 ;; string or bit vector, depending on the contents of x:
3413 always (progn
3414 (unless (characterp elt) (setq check-string nil))
3415 (unless (and (numberp elt) (or (= elt 0) (= elt 1)))
3416 (setq check-bit-vector nil))
3417 (or check-string check-bit-vector)))
3418 `(,@let-form
3419 (cond
3420 ,@(if check-string
3421 `(((stringp ,y)
3422 (cl-string-vector-equalp ,y ,x))))
3423 ,@(if check-bit-vector
3424 `(((bit-vector-p ,y)
3425 (cl-bit-vector-vector-equalp ,y ,x))))
3426 ((vectorp ,y)
3427 (cl-vector-array-equalp ,x ,y)))))))
3428 ((unordered-check (and (characterp x) (not (cl-const-expr-p y))))
3429 `(,@let-form
3430 (or (eq ,x ,y)
3431 ;; eq has a bytecode, char-equal doesn't.
3432 (and (characterp ,y)
3433 (eq (downcase ,x) (downcase ,y))))))
3434 ((unordered-check (and (numberp x) (not (cl-const-expr-p y))))
3435 `(,@let-form
3436 (and (numberp ,y)
3437 (= ,x ,y))))
3438 ((unordered-check (and (hash-table-p x) (not (cl-const-expr-p y))))
3439 ;; Hash tables; follow the CL spec.
3440 `(,@let-form
3441 (and (hash-table-p ,y)
3442 (eq ',(hash-table-test x) (hash-table-test ,y))
3443 (= ,(hash-table-count x) (hash-table-count ,y))
3444 (cl-hash-table-contents-equalp ,x ,y))))
3445 ((unordered-check
3446 ;; Symbols; eq.
3447 (and (not (cl-const-expr-p y))
3448 (or (memq x '(nil t))
3449 (and (eq (car-safe x) 'quote) (symbolp (second x))))))
3450 (cons 'eq (cdr form)))
3451 ((unordered-check
3452 ;; Compare conses at runtime, there's no real upside to
3453 ;; unrolling the function -> they fall through to the next
3454 ;; clause in this function.
3455 (and (cl-const-expr-p x) (not (consp x))
3456 (not (cl-const-expr-p y))))
3457 ;; All other types; use equal.
3458 (cons 'equal (cdr form)))
3459 ;; Neither side is a constant expression, do all our evaluation at
3460 ;; runtime (or both are, and equalp will be called from
3461 ;; byte-optimize.el).
3462 (t form)))))
3463
3353 (mapc 3464 (mapc
3354 #'(lambda (y) 3465 #'(lambda (y)
3355 (put (car y) 'side-effect-free t) 3466 (put (car y) 'side-effect-free t)
3356 (put (car y) 'byte-compile 'cl-byte-compile-compiler-macro) 3467 (put (car y) 'byte-compile 'cl-byte-compile-compiler-macro)
3357 (put (car y) 'cl-compiler-macro 3468 (put (car y) 'cl-compiler-macro