comparison lisp/cl-macs.el @ 5294:bbff29a01820

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