comparison lisp/cl-macs.el @ 5420:b9167d522a9a

Rebase with 21.5 trunk.
author Mats Lidell <matsl@xemacs.org>
date Thu, 28 Oct 2010 23:53:24 +0200
parents 308d34e9f07d bbff29a01820
children 002cb5224e4f
comparison
equal deleted inserted replaced
5419:eaf01113cd42 5420:b9167d522a9a
131 (defun cl-const-exprs-p (xs) 131 (defun cl-const-exprs-p (xs)
132 (while (and xs (cl-const-expr-p (car xs))) 132 (while (and xs (cl-const-expr-p (car xs)))
133 (setq xs (cdr xs))) 133 (setq xs (cdr xs)))
134 (not xs)) 134 (not xs))
135 135
136 (defun cl-const-expr-val (x) 136 (defun cl-const-expr-val (x &optional cl-not-constant)
137 (and (eq (cl-const-expr-p x) t) (if (consp x) (nth 1 x) x))) 137 (let ((cl-const-expr-p (cl-const-expr-p x)))
138 (cond ((eq cl-const-expr-p t) (if (consp x) (nth 1 x) x))
139 ((eq cl-const-expr-p 'func) (nth 1 x))
140 (cl-not-constant))))
138 141
139 (defun cl-expr-access-order (x v) 142 (defun cl-expr-access-order (x v)
140 (if (cl-const-expr-p x) v 143 (if (cl-const-expr-p x) v
141 (if (consp x) 144 (if (consp x)
142 (progn 145 (progn
2403 (store-temp (gensym "--getf-store--"))) 2406 (store-temp (gensym "--getf-store--")))
2404 (list (append (car method) (list tag-temp def-temp)) 2407 (list (append (car method) (list tag-temp def-temp))
2405 (append (nth 1 method) (list tag def)) 2408 (append (nth 1 method) (list tag def))
2406 (list store-temp) 2409 (list store-temp)
2407 (list 'let (list (list (car (nth 2 method)) 2410 (list 'let (list (list (car (nth 2 method))
2408 (list 'cl-set-getf (nth 4 method) 2411 (list 'plist-put (nth 4 method)
2409 tag-temp store-temp))) 2412 tag-temp store-temp)))
2410 (nth 3 method) store-temp) 2413 (nth 3 method) store-temp)
2411 (list 'getf (nth 4 method) tag-temp def-temp)))) 2414 (list 'getf (nth 4 method) tag-temp def-temp))))
2412 2415
2413 (define-setf-method substring (place from &optional to) 2416 (define-setf-method substring (place from &optional to)
2593 (and tag-temp (list (list tag-temp tag)))) 2596 (and tag-temp (list (list tag-temp tag))))
2594 (list 'if (list 'eq ttag (list 'car tval)) 2597 (list 'if (list 'eq ttag (list 'car tval))
2595 (list 'progn 2598 (list 'progn
2596 (cl-setf-do-store (nth 1 method) (list 'cddr tval)) 2599 (cl-setf-do-store (nth 1 method) (list 'cddr tval))
2597 t) 2600 t)
2598 (list 'cl-do-remf tval ttag))))) 2601 (list 'plist-remprop tval ttag)))))
2599 2602
2600 ;;;###autoload 2603 ;;;###autoload
2601 (defmacro shiftf (place &rest args) 2604 (defmacro shiftf (place &rest args)
2602 "(shiftf PLACE PLACE... VAL): shift left among PLACEs. 2605 "(shiftf PLACE PLACE... VAL): shift left among PLACEs.
2603 Example: (shiftf A B C) sets A to B, B to C, and returns the old A. 2606 Example: (shiftf A B C) sets A to B, B to C, and returns the old A.
3260 3263
3261 ;;; Compile-time optimizations for some functions defined in this package. 3264 ;;; Compile-time optimizations for some functions defined in this package.
3262 ;;; Note that cl.el arranges to force cl-macs to be loaded at compile-time, 3265 ;;; Note that cl.el arranges to force cl-macs to be loaded at compile-time,
3263 ;;; mainly to make sure these macros will be present. 3266 ;;; mainly to make sure these macros will be present.
3264 3267
3268 (defun cl-non-fixnum-number-p (object)
3269 (and (numberp object) (not (fixnump object))))
3270
3265 (put 'eql 'byte-compile nil) 3271 (put 'eql 'byte-compile nil)
3266 (define-compiler-macro eql (&whole form a b) 3272 (define-compiler-macro eql (&whole form a b)
3267 (cond ((eq (cl-const-expr-p a) t) 3273 (cond ((eq (cl-const-expr-p a) t)
3268 (let ((val (cl-const-expr-val a))) 3274 (let ((val (cl-const-expr-val a)))
3269 (if (and (numberp val) (not (fixnump val))) 3275 (if (cl-non-fixnum-number-p val)
3270 (list 'equal a b) 3276 (list 'equal a b)
3271 (list 'eq a b)))) 3277 (list 'eq a b))))
3272 ((eq (cl-const-expr-p b) t) 3278 ((eq (cl-const-expr-p b) t)
3273 (let ((val (cl-const-expr-val b))) 3279 (let ((val (cl-const-expr-val b)))
3274 (if (and (numberp val) (not (fixnump val))) 3280 (if (cl-non-fixnum-number-p val)
3275 (list 'equal a b) 3281 (list 'equal a b)
3276 (list 'eq a b)))) 3282 (list 'eq a b))))
3277 ((cl-simple-expr-p a 5) 3283 ((cl-simple-expr-p a 5)
3278 (list 'if (list 'numberp a) 3284 (list 'if (list 'numberp a)
3279 (list 'equal a b) 3285 (list 'equal a b)
3283 (list 'if (list 'numberp b) 3289 (list 'if (list 'numberp b)
3284 (list 'equal a b) 3290 (list 'equal a b)
3285 (list 'eq a b))) 3291 (list 'eq a b)))
3286 (t form))) 3292 (t form)))
3287 3293
3288 (define-compiler-macro member* (&whole form a list &rest keys) 3294 (macrolet
3289 (let ((test (and (= (length keys) 2) (eq (car keys) :test) 3295 ((define-star-compiler-macros (&rest macros)
3290 (cl-const-expr-val (nth 1 keys)))) 3296 "For `member*', `assoc*' and `rassoc*' with constant ITEM or
3291 a-val) 3297 :test arguments, use the versions with explicit tests if that makes sense."
3292 (cond ((eq test 'eq) (list 'memq a list)) 3298 (list*
3293 ((eq test 'equal) (list 'member a list)) 3299 'progn
3294 ((or (null keys) (eq test 'eql)) 3300 (mapcar
3295 (if (eq (cl-const-expr-p a) t) 3301 (function*
3296 (list (if (and (numberp (setq a-val (cl-const-expr-val a))) 3302 (lambda ((star-function eq-function equal-function))
3297 (not (fixnump a-val))) 3303 `(define-compiler-macro ,star-function (&whole form item list
3298 'member 3304 &rest keys)
3299 'memq) 3305 (condition-case nil
3300 a list) 3306 (symbol-macrolet ((not-constant '#:not-constant))
3301 (if (eq (cl-const-expr-p list) t) 3307 (let* ((test-expr (plist-get keys :test ''eql))
3302 (let ((p (cl-const-expr-val list)) (mb nil) (mq nil)) 3308 (test (cl-const-expr-val test-expr not-constant))
3303 (if (not (cdr p)) 3309 (item-val (cl-const-expr-val item not-constant))
3304 (and p (list 'eql a (list 'quote (car p)))) 3310 (list-val (cl-const-expr-val list not-constant)))
3305 (while p 3311 (if (and keys
3306 (if (and (numberp (car p)) (not (fixnump (car p)))) 3312 (not (and (eq :test (car keys))
3307 (setq mb t) 3313 (eql 2 (length keys)))))
3308 (or (fixnump (car p)) (symbolp (car p)) (setq mq t))) 3314 form
3309 (setq p (cdr p))) 3315 (cond ((eq test 'eq) `(,',eq-function ,item ,list))
3310 (if (not mb) (list 'memq a list) 3316 ((eq test 'equal)
3311 (if (not mq) (list 'member a list) form)))) 3317 `(,',equal-function ,item ,list))
3312 form))) 3318 ((and (eq test 'eql)
3313 (t form)))) 3319 (not (eq not-constant item-val)))
3314 3320 (if (cl-non-fixnum-number-p item-val)
3315 (define-compiler-macro assoc* (&whole form a list &rest keys) 3321 `(,',equal-function ,item ,list)
3316 (let ((test (and (= (length keys) 2) (eq (car keys) :test) 3322 `(,',eq-function ,item ,list)))
3317 (cl-const-expr-val (nth 1 keys)))) 3323 ((and (eq test 'eql) (not (eq not-constant
3318 a-val) 3324 list-val)))
3319 (cond ((eq test 'eq) (list 'assq a list)) 3325 (if (some 'cl-non-fixnum-number-p list-val)
3320 ((eq test 'equal) (list 'assoc a list)) 3326 `(,',equal-function ,item ,list)
3321 ((and (eq (cl-const-expr-p a) t) (or (null keys) (eq test 'eql))) 3327 ;; This compiler macro used to limit calls
3322 (if (and (numberp (setq a-val (cl-const-expr-val a))) 3328 ;; to ,,eq-function to lists where all
3323 (not (fixnump a-val))) 3329 ;; elements were either fixnums or
3324 (list 'assoc a list) (list 'assq a list))) 3330 ;; symbols. There's no
3325 (t form)))) 3331 ;; reason to do this.
3332 `(,',eq-function ,item ,list)))
3333 ;; This is a hilariously specific case; see
3334 ;; add-to-list in subr.el.
3335 ((and (eq test not-constant)
3336 (eq 'or (car-safe test-expr))
3337 (eql 3 (length test-expr))
3338 (every #'cl-safe-expr-p (cdr form))
3339 `(if ,(second test-expr)
3340 (,',star-function ,item ,list :test
3341 ,(second test-expr))
3342 (,',star-function
3343 ,item ,list :test ,(third test-expr)))))
3344 (t form)))))
3345 ;; No need to warn about a malformed property list,
3346 ;; #'byte-compile-normal-call will do that for us.
3347 (malformed-property-list form)))))
3348 macros))))
3349 (define-star-compiler-macros
3350 (member* memq member)
3351 (assoc* assq assoc)
3352 (rassoc* rassq rassoc)))
3326 3353
3327 (define-compiler-macro adjoin (&whole form a list &rest keys) 3354 (define-compiler-macro adjoin (&whole form a list &rest keys)
3328 (if (and (cl-simple-expr-p a) (cl-simple-expr-p list) 3355 (if (and (cl-simple-expr-p a) (cl-simple-expr-p list)
3329 (not (memq :key keys))) 3356 (not (memq :key keys)))
3330 (list 'if (list* 'member* a list keys) list (list 'cons a list)) 3357 (list 'if (list* 'member* a list keys) list (list 'cons a list))
3331 form)) 3358 form))
3359
3360 (define-compiler-macro remove (item sequence)
3361 `(remove* ,item ,sequence :test #'equal))
3362
3363 (define-compiler-macro remq (item sequence)
3364 `(remove* ,item ,sequence :test #'eq))
3365
3366 (macrolet
3367 ((define-foo-if-compiler-macros (&rest alist)
3368 "Avoid the funcall, variable binding and keyword parsing overhead
3369 for the FOO-IF and FOO-IF-NOT functions, transforming to forms using the
3370 non-standard :if and :if-not keywords at compile time."
3371 (cons
3372 'progn
3373 (mapcar
3374 (function*
3375 (lambda ((function-if . function))
3376 (let ((keyword (if (equal (substring (symbol-name function-if) -3)
3377 "not")
3378 :if-not
3379 :if)))
3380 `(define-compiler-macro ,function-if (&whole form &rest args)
3381 (if (and (nthcdr 2 form)
3382 (or (consp (cl-const-expr-val (second form)))
3383 (cl-safe-expr-p (second form))))
3384 ;; It doesn't matter what the second argument is, it's
3385 ;; ignored by FUNCTION. We know that the symbol
3386 ;; FUNCTION is in the constants vector, so use it.
3387 `(,',function ',',function ,(third form) ,,keyword
3388 ,(second form) ,@(nthcdr 3 form))
3389 form)))))
3390 alist))))
3391 (define-foo-if-compiler-macros
3392 (remove-if . remove*)
3393 (remove-if-not . remove*)
3394 (delete-if . delete*)
3395 (delete-if-not . delete*)
3396 (find-if . find)
3397 (find-if-not . find)
3398 (position-if . position)
3399 (position-if-not . position)
3400 (count-if . count)
3401 (count-if-not . count)
3402 (member-if . member*)
3403 (member-if-not . member*)
3404 (assoc-if . assoc*)
3405 (assoc-if-not . assoc*)
3406 (rassoc-if . rassoc*)
3407 (rassoc-if-not . rassoc*)))
3408
3409 (macrolet
3410 ((define-substitute-if-compiler-macros (&rest alist)
3411 "Like the above, but for `substitute-if' and friends."
3412 (cons
3413 'progn
3414 (mapcar
3415 (function*
3416 (lambda ((function-if . function))
3417 (let ((keyword (if (equal (substring (symbol-name function-if) -3)
3418 "not")
3419 :if-not
3420 :if)))
3421 `(define-compiler-macro ,function-if (&whole form &rest args)
3422 (if (and (nthcdr 3 form)
3423 (or (consp (cl-const-expr-val (third form)))
3424 (cl-safe-expr-p (third form))))
3425 `(,',function ,(second form) ',',function ,(fourth form)
3426 ,,keyword ,(third form) ,@(nthcdr 4 form))
3427 form)))))
3428 alist))))
3429 (define-substitute-if-compiler-macros
3430 (substitute-if . substitute)
3431 (substitute-if-not . substitute)
3432 (nsubstitute-if . nsubstitute)
3433 (nsubstitute-if-not . nsubstitute)))
3434
3435 (macrolet
3436 ((define-subst-if-compiler-macros (&rest alist)
3437 "Like the above, but for `subst-if' and friends."
3438 (cons
3439 'progn
3440 (mapcar
3441 (function*
3442 (lambda ((function-if . function))
3443 (let ((keyword (if (equal (substring (symbol-name function-if) -3)
3444 "not")
3445 :if-not
3446 :if)))
3447 `(define-compiler-macro ,function-if (&whole form &rest args)
3448 (if (and (nthcdr 3 form)
3449 (or (consp (cl-const-expr-val (third form)))
3450 (cl-safe-expr-p (third form))))
3451 `(,',function ,(if (cl-const-expr-p (second form))
3452 `'((nil . ,(cl-const-expr-val
3453 (second form))))
3454 `(list (cons ',',function
3455 ,(second form))))
3456 ,(fourth form) ,,keyword ,(third form)
3457 ,@(nthcdr 4 form))
3458 form)))))
3459 alist))))
3460 (define-subst-if-compiler-macros
3461 (subst-if . sublis)
3462 (subst-if-not . sublis)
3463 (nsubst-if . nsublis)
3464 (nsubst-if-not . nsublis)))
3332 3465
3333 (define-compiler-macro list* (arg &rest others) 3466 (define-compiler-macro list* (arg &rest others)
3334 (let* ((args (reverse (cons arg others))) 3467 (let* ((args (reverse (cons arg others)))
3335 (form (car args))) 3468 (form (car args)))
3336 (while (setq args (cdr args)) 3469 (while (setq args (cdr args))
3358 3491
3359 ;; XEmacs; inline delete-duplicates if it's called with one of the 3492 ;; XEmacs; inline delete-duplicates if it's called with one of the
3360 ;; common compile-time constant tests and an optional :from-end 3493 ;; common compile-time constant tests and an optional :from-end
3361 ;; argument, we want the speed in font-lock.el. 3494 ;; argument, we want the speed in font-lock.el.
3362 (define-compiler-macro delete-duplicates (&whole form cl-seq &rest cl-keys) 3495 (define-compiler-macro delete-duplicates (&whole form cl-seq &rest cl-keys)
3363 (let ((listp-check 3496 (if (not (or (memq (car-safe cl-seq)
3364 (cond 3497 ;; No need to check for a list at runtime with
3365 ((memq (car-safe cl-seq) 3498 ;; these. We could expand the list, but these are all
3366 ;; No need to check for a list at runtime with these. We 3499 ;; the functions in the relevant context at the moment.
3367 ;; could expand the list, but these are all the functions 3500 '(nreverse append nconc mapcan mapcar string-to-list))
3368 ;; in the relevant context at the moment. 3501 (and (listp cl-seq) (equal (butlast cl-seq) '(the list)))))
3369 '(nreverse append nconc mapcan mapcar string-to-list)) 3502 form
3370 t) 3503 (cond
3371 ((and (listp cl-seq) (eq (first cl-seq) 'the) 3504 ((or (plists-equal cl-keys '(:test 'eq) t)
3372 (eq (second cl-seq) 'list)) 3505 (plists-equal cl-keys '(:test #'eq) t))
3373 ;; Allow users to force this, if they really want to. 3506 `(let* ((begin ,cl-seq)
3374 t) 3507 cl-seq)
3375 (t 3508 (while (memq (car begin) (cdr begin))
3376 '(listp begin))))) 3509 (setq begin (cdr begin)))
3377 (cond ((loop 3510 (setq cl-seq begin)
3378 for relevant-key-values 3511 (while (cddr cl-seq)
3379 in '((:test 'eq) 3512 (if (memq (cadr cl-seq) (cddr cl-seq))
3380 (:test #'eq) 3513 (setcdr (cdr cl-seq) (cddr cl-seq)))
3381 (:test 'eq :from-end nil) 3514 (setq cl-seq (cdr cl-seq)))
3382 (:test #'eq :from-end nil)) 3515 begin))
3383 ;; One of the above corresponds exactly to CL-KEYS: 3516 ((or (plists-equal cl-keys '(:test 'eq :from-end t) t)
3384 thereis (not (set-difference cl-keys relevant-key-values 3517 (plists-equal cl-keys '(:test #'eq :from-end t) t))
3385 :test #'equal))) 3518 `(let* ((begin ,cl-seq)
3386 `(let* ((begin ,cl-seq) 3519 (cl-seq begin))
3387 cl-seq) 3520 (while cl-seq
3388 (if ,listp-check 3521 (setq cl-seq (setcdr cl-seq
3389 (progn 3522 (delq (car cl-seq) (cdr cl-seq)))))
3390 (while (memq (car begin) (cdr begin)) 3523 begin))
3391 (setq begin (cdr begin))) 3524 ((or (plists-equal cl-keys '(:test 'equal) t)
3392 (setq cl-seq begin) 3525 (plists-equal cl-keys '(:test #'equal) t))
3393 (while (cddr cl-seq) 3526 `(let* ((begin ,cl-seq)
3394 (if (memq (cadr cl-seq) (cddr cl-seq)) 3527 cl-seq)
3395 (setcdr (cdr cl-seq) (cddr cl-seq))) 3528 (while (member (car begin) (cdr begin))
3396 (setq cl-seq (cdr cl-seq))) 3529 (setq begin (cdr begin)))
3397 begin) 3530 (setq cl-seq begin)
3398 ;; Call cl-delete-duplicates explicitly, to avoid the form 3531 (while (cddr cl-seq)
3399 ;; getting compiler-macroexpanded again: 3532 (if (member (cadr cl-seq) (cddr cl-seq))
3400 (cl-delete-duplicates begin ',cl-keys nil)))) 3533 (setcdr (cdr cl-seq) (cddr cl-seq)))
3401 ((loop 3534 (setq cl-seq (cdr cl-seq)))
3402 for relevant-key-values 3535 begin))
3403 in '((:test 'eq :from-end t) 3536 ((or (plists-equal cl-keys '(:test 'equal :from-end t) t)
3404 (:test #'eq :from-end t)) 3537 (plists-equal cl-keys '(:test #'equal :from-end t) t))
3405 ;; One of the above corresponds exactly to CL-KEYS: 3538 `(let* ((begin ,cl-seq)
3406 thereis (not (set-difference cl-keys relevant-key-values 3539 (cl-seq begin))
3407 :test #'equal))) 3540 (while cl-seq
3408 `(let* ((begin ,cl-seq) 3541 (setq cl-seq (setcdr cl-seq (delete (car cl-seq)
3409 (cl-seq begin)) 3542 (cdr cl-seq)))))
3410 (if ,listp-check 3543 begin))
3411 (progn 3544 (t form))))
3412 (while cl-seq
3413 (setq cl-seq (setcdr cl-seq
3414 (delq (car cl-seq) (cdr cl-seq)))))
3415 begin)
3416 ;; Call cl-delete-duplicates explicitly, to avoid the form
3417 ;; getting compiler-macroexpanded again:
3418 (cl-delete-duplicates begin ',cl-keys nil))))
3419
3420 ((loop
3421 for relevant-key-values
3422 in '((:test 'equal)
3423 (:test #'equal)
3424 (:test 'equal :from-end nil)
3425 (:test #'equal :from-end nil))
3426 ;; One of the above corresponds exactly to CL-KEYS:
3427 thereis (not (set-difference cl-keys relevant-key-values
3428 :test #'equal)))
3429 `(let* ((begin ,cl-seq)
3430 cl-seq)
3431 (if ,listp-check
3432 (progn
3433 (while (member (car begin) (cdr begin))
3434 (setq begin (cdr begin)))
3435 (setq cl-seq begin)
3436 (while (cddr cl-seq)
3437 (if (member (cadr cl-seq) (cddr cl-seq))
3438 (setcdr (cdr cl-seq) (cddr cl-seq)))
3439 (setq cl-seq (cdr cl-seq)))
3440 begin)
3441 ;; Call cl-delete-duplicates explicitly, to avoid the form
3442 ;; getting compiler-macroexpanded again:
3443 (cl-delete-duplicates begin ',cl-keys nil))))
3444 ((loop
3445 for relevant-key-values
3446 in '((:test 'equal :from-end t)
3447 (:test #'equal :from-end t))
3448 ;; One of the above corresponds exactly to CL-KEYS:
3449 thereis (not (set-difference cl-keys relevant-key-values
3450 :test #'equal)))
3451 `(let* ((begin ,cl-seq)
3452 (cl-seq begin))
3453 (if ,listp-check
3454 (progn
3455 (while cl-seq
3456 (setq cl-seq
3457 (setcdr cl-seq (delete (car cl-seq) (cdr cl-seq)))))
3458 begin)
3459 ;; Call cl-delete-duplicates explicitly, to avoid the form
3460 ;; getting compiler-macroexpanded again:
3461 (cl-delete-duplicates begin ',cl-keys nil))))
3462 (t form))))
3463 3545
3464 ;; XEmacs; it's perfectly reasonable, and often much clearer to those 3546 ;; XEmacs; it's perfectly reasonable, and often much clearer to those
3465 ;; reading the code, to call regexp-quote on a constant string, which is 3547 ;; reading the code, to call regexp-quote on a constant string, which is
3466 ;; something we can optimise here easily. 3548 ;; something we can optimise here easily.
3467 (define-compiler-macro regexp-quote (&whole form string) 3549 (define-compiler-macro regexp-quote (&whole form string)
3556 ;; Neither side is a constant expression, do all our evaluation at 3638 ;; Neither side is a constant expression, do all our evaluation at
3557 ;; runtime (or both are, and equalp will be called from 3639 ;; runtime (or both are, and equalp will be called from
3558 ;; byte-optimize.el). 3640 ;; byte-optimize.el).
3559 (t form))))) 3641 (t form)))))
3560 3642
3561 ;;(define-compiler-macro equalp (&whole form x y)
3562 ;; "Expand calls to `equalp' where X or Y is a constant expression.
3563 ;;
3564 ;;Much of the processing that `equalp' does is dependent on the types of both
3565 ;;of its arguments, and with type information for one of them, we can
3566 ;;eliminate much of the body of the function at compile time.
3567 ;;
3568 ;;Where both X and Y are constant expressions, `equalp' is evaluated at
3569 ;;compile time by byte-optimize.el--this compiler macro passes FORM through to
3570 ;;the byte optimizer in those cases."
3571 ;; ;; Cases where both arguments are constant are handled in
3572 ;; ;; byte-optimize.el, we only need to handle those cases where one is
3573 ;; ;; constant here.
3574 ;; (let* ((equalp-sym (eval-when-compile (gensym)))
3575 ;; (let-form '(progn))
3576 ;; (check-bit-vector t)
3577 ;; (check-string t)
3578 ;; (original-y y)
3579 ;; equalp-temp checked)
3580 ;; (macrolet
3581 ;; ((unordered-check (check)
3582 ;; `(prog1
3583 ;; (setq checked
3584 ;; (or ,check
3585 ;; (prog1 ,(sublis '((x . y) (y . x)) check :test #'eq)
3586 ;; (setq equalp-temp x x y y equalp-temp))))
3587 ;; (when checked
3588 ;; (unless (symbolp y)
3589 ;; (setq let-form `(let ((,equalp-sym ,y))) y equalp-sym))))))
3590 ;; ;; In the bodies of the below clauses, x is always a constant expression
3591 ;; ;; of the type we're interested in, and y is always a symbol that refers
3592 ;; ;; to the result non-constant side of the comparison.
3593 ;; (cond ((unordered-check (and (arrayp x) (not (cl-const-expr-p y))))
3594 ;; ;; Strings and other arrays. A vector containing the same
3595 ;; ;; character elements as a given string is equalp to that string;
3596 ;; ;; a bit-vector can only be equalp to a string if both are
3597 ;; ;; zero-length.
3598 ;; (cond
3599 ;; ((member x '("" #* []))
3600 ;; ;; No need to protect against multiple evaluation here:
3601 ;; `(and (member ,original-y '("" #* [])) t))
3602 ;; ((stringp x)
3603 ;; `(,@let-form
3604 ;; (if (stringp ,y)
3605 ;; (eq t (compare-strings ,x nil nil
3606 ;; ,y nil nil t))
3607 ;; (if (vectorp ,y)
3608 ;; (cl-string-vector-equalp ,x ,y)))))
3609 ;; ((bit-vector-p x)
3610 ;; `(,@let-form
3611 ;; (if (bit-vector-p ,y)
3612 ;; ;; No need to call equalp on each element here:
3613 ;; (equal ,x ,y)
3614 ;; (if (vectorp ,y)
3615 ;; (cl-bit-vector-vector-equalp ,x ,y)))))
3616 ;; (t
3617 ;; (loop
3618 ;; for elt across x
3619 ;; ;; We may not need to check the other argument if it's a
3620 ;; ;; string or bit vector, depending on the contents of x:
3621 ;; always (progn
3622 ;; (unless (characterp elt) (setq check-string nil))
3623 ;; (unless (and (numberp elt) (or (= elt 0) (= elt 1)))
3624 ;; (setq check-bit-vector nil))
3625 ;; (or check-string check-bit-vector)))
3626 ;; `(,@let-form
3627 ;; (cond
3628 ;; ,@(if check-string
3629 ;; `(((stringp ,y)
3630 ;; (cl-string-vector-equalp ,y ,x))))
3631 ;; ,@(if check-bit-vector
3632 ;; `(((bit-vector-p ,y)
3633 ;; (cl-bit-vector-vector-equalp ,y ,x))))
3634 ;; ((vectorp ,y)
3635 ;; (cl-vector-array-equalp ,x ,y)))))))
3636 ;; ((unordered-check (and (characterp x) (not (cl-const-expr-p y))))
3637 ;; `(,@let-form
3638 ;; (or (eq ,x ,y)
3639 ;; ;; eq has a bytecode, char-equal doesn't.
3640 ;; (and (characterp ,y)
3641 ;; (eq (downcase ,x) (downcase ,y))))))
3642 ;; ((unordered-check (and (numberp x) (not (cl-const-expr-p y))))
3643 ;; `(,@let-form
3644 ;; (and (numberp ,y)
3645 ;; (= ,x ,y))))
3646 ;; ((unordered-check (and (hash-table-p x) (not (cl-const-expr-p y))))
3647 ;; ;; Hash tables; follow the CL spec.
3648 ;; `(,@let-form
3649 ;; (and (hash-table-p ,y)
3650 ;; (eq ',(hash-table-test x) (hash-table-test ,y))
3651 ;; (= ,(hash-table-count x) (hash-table-count ,y))
3652 ;; (cl-hash-table-contents-equalp ,x ,y))))
3653 ;; ((unordered-check
3654 ;; ;; Symbols; eq.
3655 ;; (and (not (cl-const-expr-p y))
3656 ;; (or (memq x '(nil t))
3657 ;; (and (eq (car-safe x) 'quote) (symbolp (second x))))))
3658 ;; (cons 'eq (cdr form)))
3659 ;; ((unordered-check
3660 ;; ;; Compare conses at runtime, there's no real upside to
3661 ;; ;; unrolling the function -> they fall through to the next
3662 ;; ;; clause in this function.
3663 ;; (and (cl-const-expr-p x) (not (consp x))
3664 ;; (not (cl-const-expr-p y))))
3665 ;; ;; All other types; use equal.
3666 ;; (cons 'equal (cdr form)))
3667 ;; ;; Neither side is a constant expression, do all our evaluation at
3668 ;; ;; runtime (or both are, and equalp will be called from
3669 ;; ;; byte-optimize.el).
3670 ;; (t form)))))
3671
3672 (define-compiler-macro notany (&whole form &rest cl-rest) 3643 (define-compiler-macro notany (&whole form &rest cl-rest)
3673 `(not (some ,@(cdr form)))) 3644 `(not (some ,@(cdr form))))
3674 3645
3675 (define-compiler-macro notevery (&whole form &rest cl-rest) 3646 (define-compiler-macro notevery (&whole form &rest cl-rest)
3676 `(not (every ,@(cdr form)))) 3647 `(not (every ,@(cdr form))))
3769 (vector (cons 'vconcat (cddr form))) 3740 (vector (cons 'vconcat (cddr form)))
3770 (bit-vector (cons 'bvconcat (cddr form))) 3741 (bit-vector (cons 'bvconcat (cddr form)))
3771 (string (cons 'concat (cddr form)))) 3742 (string (cons 'concat (cddr form))))
3772 form)) 3743 form))
3773 3744
3745 (define-compiler-macro subst-char-in-string (&whole form fromchar tochar
3746 string &optional inplace)
3747 (if (every #'cl-safe-expr-p (cdr form))
3748 `(funcall (if ,inplace #'nsubstitute #'substitute) ,tochar ,fromchar
3749 (the string ,string) :test #'eq)
3750 form))
3751
3774 (map nil 3752 (map nil
3775 #'(lambda (function) 3753 #'(lambda (function)
3776 ;; There are byte codes for the two-argument versions of these 3754 ;; There are byte codes for the two-argument versions of these
3777 ;; functions; if the form has more arguments and those arguments 3755 ;; functions; if the form has more arguments and those arguments
3778 ;; have no side effects, transform to a series of two-argument 3756 ;; have no side effects, transform to a series of two-argument
3801 (list 'list (list 'quote (caddr y)) 'x)) 3779 (list 'list (list 'quote (caddr y)) 'x))
3802 (cons 'list (cdr y)))))) 3780 (cons 'list (cdr y))))))
3803 '((first 'car x) (second 'cadr x) (third 'caddr x) (fourth 'cadddr x) 3781 '((first 'car x) (second 'cadr x) (third 'caddr x) (fourth 'cadddr x)
3804 (fifth 'nth 4 x) (sixth 'nth 5 x) (seventh 'nth 6 x) 3782 (fifth 'nth 4 x) (sixth 'nth 5 x) (seventh 'nth 6 x)
3805 (eighth 'nth 7 x) (ninth 'nth 8 x) (tenth 'nth 9 x) 3783 (eighth 'nth 7 x) (ninth 'nth 8 x) (tenth 'nth 9 x)
3806 (rest 'cdr x) (endp 'null x) (plusp '> x 0) (minusp '< x 0) 3784 (rest 'cdr x) (plusp '> x 0) (minusp '< x 0)
3807 (oddp 'eq (list 'logand x 1) 1) 3785 (oddp 'eq (list 'logand x 1) 1)
3808 (evenp 'eq (list 'logand x 1) 0) 3786 (evenp 'eq (list 'logand x 1) 0)
3809 (caar car car) (cadr car cdr) (cdar cdr car) (cddr cdr cdr) 3787 (caar car car) (cadr car cdr) (cdar cdr car) (cddr cdr cdr)
3810 (caaar car caar) (caadr car cadr) (cadar car cdar) 3788 (caaar car caar) (caadr car cadr) (cadar car cdar)
3811 (caddr car cddr) (cdaar cdr caar) (cdadr cdr cadr) 3789 (caddr car cddr) (cdaar cdr caar) (cdadr cdr cadr)