Mercurial > hg > xemacs-beta
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) |