comparison lisp/cl-macs.el @ 5085:1ee30d3f9dd0

Handle the :from-end argument correctly, #'delete-duplicates compiler macro. 2010-03-02 Aidan Kehoe <kehoea@parhasard.net> * cl-macs.el (delete-dups): New compiler macro for this function, expanding to inline byte codes. (delete-duplicates): Handle the :from-end argument correctly in this compiler macro.
author Aidan Kehoe <kehoea@parhasard.net>
date Tue, 02 Mar 2010 13:02:36 +0000
parents 6afe991b8135
children a24f2ab0093b
comparison
equal deleted inserted replaced
5084:6afe991b8135 5085:1ee30d3f9dd0
3290 (cl-simple-expr-p val)) res 3290 (cl-simple-expr-p val)) res
3291 (let ((temp (gensym))) 3291 (let ((temp (gensym)))
3292 (list 'let (list (list temp val)) (subst temp val res))))) 3292 (list 'let (list (list temp val)) (subst temp val res)))))
3293 form)) 3293 form))
3294 3294
3295 ;; XEmacs; inline delete-duplicates if it's called with a literal 3295 (define-compiler-macro delete-dups (list)
3296 ;; #'equal or #'eq and no other keywords, we want the speed in 3296 `(delete-duplicates (the list ,list) :test #'equal :from-end t))
3297 ;; font-lock.el. 3297
3298 ;; XEmacs; inline delete-duplicates if it's called with one of the
3299 ;; common compile-time constant tests and an optional :from-end
3300 ;; argument, we want the speed in font-lock.el.
3298 (define-compiler-macro delete-duplicates (&whole form cl-seq &rest cl-keys) 3301 (define-compiler-macro delete-duplicates (&whole form cl-seq &rest cl-keys)
3299 (let ((listp-check 3302 (let ((listp-check
3300 (if (memq (car-safe cl-seq) 3303 (cond
3301 ;; No need to check for a list at runtime with these. We 3304 ((memq (car-safe cl-seq)
3302 ;; could expand the list, but these are all the functions 3305 ;; No need to check for a list at runtime with these. We
3303 ;; in the relevant context at the moment. 3306 ;; could expand the list, but these are all the functions
3304 '(nreverse append nconc mapcan mapcar)) 3307 ;; in the relevant context at the moment.
3305 t 3308 '(nreverse append nconc mapcan mapcar string-to-list))
3306 '(listp begin)))) 3309 t)
3307 (cond ((and (= 4 (length form)) 3310 ((and (listp cl-seq) (eq (first cl-seq) 'the)
3308 (eq :test (third form)) 3311 (eq (second cl-seq) 'list))
3309 (or (equal '(quote eq) (fourth form)) 3312 ;; Allow users to force this, if they really want to.
3310 (equal '(function eq) (fourth form)))) 3313 t)
3314 (t
3315 '(listp begin)))))
3316 (cond ((loop
3317 for relevant-key-values
3318 in '((:test 'eq)
3319 (:test #'eq)
3320 (:test 'eq :from-end nil)
3321 (:test #'eq :from-end nil))
3322 ;; One of the above corresponds exactly to CL-KEYS:
3323 thereis (not (set-difference cl-keys relevant-key-values
3324 :test #'equal)))
3325 `(let* ((begin ,cl-seq)
3326 cl-seq)
3327 (if ,listp-check
3328 (progn
3329 (while (memq (car begin) (cdr begin))
3330 (setq begin (cdr begin)))
3331 (setq cl-seq begin)
3332 (while (cddr cl-seq)
3333 (if (memq (cadr cl-seq) (cddr cl-seq))
3334 (setcdr (cdr cl-seq) (cddr cl-seq))
3335 (setq cl-seq (cdr cl-seq))))
3336 begin)
3337 ;; Call cl-delete-duplicates explicitly, to avoid the form
3338 ;; getting compiler-macroexpanded again:
3339 (cl-delete-duplicates begin ',cl-keys nil))))
3340 ((loop
3341 for relevant-key-values
3342 in '((:test 'eq :from-end t)
3343 (:test #'eq :from-end t))
3344 ;; One of the above corresponds exactly to CL-KEYS:
3345 thereis (not (set-difference cl-keys relevant-key-values
3346 :test #'equal)))
3347 `(let* ((begin ,cl-seq)
3348 (cl-seq begin))
3349 (if ,listp-check
3350 (progn
3351 (while cl-seq
3352 (setq cl-seq (setcdr cl-seq
3353 (delq (car cl-seq) (cdr cl-seq)))))
3354 begin)
3355 ;; Call cl-delete-duplicates explicitly, to avoid the form
3356 ;; getting compiler-macroexpanded again:
3357 (cl-delete-duplicates begin ',cl-keys nil))))
3358
3359 ((loop
3360 for relevant-key-values
3361 in '((:test 'equal)
3362 (:test #'equal)
3363 (:test 'equal :from-end nil)
3364 (:test #'equal :from-end nil))
3365 ;; One of the above corresponds exactly to CL-KEYS:
3366 thereis (not (set-difference cl-keys relevant-key-values
3367 :test #'equal)))
3368 `(let* ((begin ,cl-seq)
3369 cl-seq)
3370 (if ,listp-check
3371 (progn
3372 (while (member (car begin) (cdr begin))
3373 (setq begin (cdr begin)))
3374 (setq cl-seq begin)
3375 (while (cddr cl-seq)
3376 (if (member (cadr cl-seq) (cddr cl-seq))
3377 (setcdr (cdr cl-seq) (cddr cl-seq)))
3378 (setq cl-seq (cdr cl-seq)))
3379 begin)
3380 ;; Call cl-delete-duplicates explicitly, to avoid the form
3381 ;; getting compiler-macroexpanded again:
3382 (cl-delete-duplicates begin ',cl-keys nil))))
3383 ((loop
3384 for relevant-key-values
3385 in '((:test 'equal :from-end t)
3386 (:test #'equal :from-end t))
3387 ;; One of the above corresponds exactly to CL-KEYS:
3388 thereis (not (set-difference cl-keys relevant-key-values
3389 :test #'equal)))
3311 `(let* ((begin ,cl-seq) 3390 `(let* ((begin ,cl-seq)
3312 (cl-seq begin)) 3391 (cl-seq begin))
3313 (if ,listp-check 3392 (if ,listp-check
3314 (progn 3393 (progn
3315 (while cl-seq 3394 (while cl-seq
3316 (setq cl-seq (setcdr cl-seq (delq (car cl-seq) 3395 (setq cl-seq
3317 (cdr cl-seq))))) 3396 (setcdr cl-seq (delete (car cl-seq) (cdr cl-seq)))))
3318 begin) 3397 begin)
3319 ;; Call cl-delete-duplicates explicitly, to avoid the form 3398 ;; Call cl-delete-duplicates explicitly, to avoid the form
3320 ;; getting compiler-macroexpanded again: 3399 ;; getting compiler-macroexpanded again:
3321 (cl-delete-duplicates begin ',cl-keys nil)))) 3400 (cl-delete-duplicates begin ',cl-keys nil))))
3322 ((and (= 4 (length form)) 3401 (t form))))
3323 (eq :test (third form))
3324 (or (equal '(quote equal) (fourth form))
3325 (equal '(function equal) (fourth form))))
3326 `(let* ((begin ,cl-seq)
3327 (cl-seq begin))
3328 (if ,listp-check
3329 (progn
3330 (while cl-seq
3331 (setq cl-seq (setcdr cl-seq (delete (car cl-seq)
3332 (cdr cl-seq)))))
3333 begin)
3334 ;; Call cl-delete-duplicates explicitly, to avoid the form
3335 ;; getting compiler-macroexpanded again:
3336 (cl-delete-duplicates begin ',cl-keys nil))))
3337 (t
3338 form))))
3339 3402
3340 ;; XEmacs; it's perfectly reasonable, and often much clearer to those 3403 ;; XEmacs; it's perfectly reasonable, and often much clearer to those
3341 ;; reading the code, to call regexp-quote on a constant string, which is 3404 ;; reading the code, to call regexp-quote on a constant string, which is
3342 ;; something we can optimise here easily. 3405 ;; something we can optimise here easily.
3343 (define-compiler-macro regexp-quote (&whole form string) 3406 (define-compiler-macro regexp-quote (&whole form string)