diff lisp/cl-macs.el @ 5659:e63bb7b22c8f

Add compiler macros for #'equal, #'member, ... where #'eq, #'memq appropriate. lisp/ChangeLog addition: 2012-05-07 Aidan Kehoe <kehoea@parhasard.net> * cl-macs.el: * cl-macs.el (cl-non-fixnum-number-p): Rename, to cl-non-immediate-number-p. This is a little more informative as a name, though still not ideal, in that it will give t for some immediate fixnums on 64-bit builds. * cl-macs.el (eql): * cl-macs.el (define-star-compiler-macros): * cl-macs.el (delq): * cl-macs.el (remq): Use the new name. * cl-macs.el (cl-equal-equivalent-to-eq-p): New. * cl-macs.el (cl-car-or-pi): New. * cl-macs.el (cl-cdr-or-pi): New. * cl-macs.el (equal): New compiler macro. * cl-macs.el (member): New compiler macro. * cl-macs.el (assoc): New compiler macro. * cl-macs.el (rassoc): New compiler macro. If any of #'equal, #'member, #'assoc or #'rassoc has a constant argument such that #'eq, #'memq, #'assq or #'rassq, respectively, are equivalent, make the substitution. Relevant in files like ispell.el, there's a reasonable amount of code out there that doesn't quite get the distinction.
author Aidan Kehoe <kehoea@parhasard.net>
date Mon, 07 May 2012 17:56:24 +0100
parents 289cf21be887
children 796f2a8fdced
line wrap: on
line diff
--- a/lisp/cl-macs.el	Sun May 06 15:29:59 2012 +0100
+++ b/lisp/cl-macs.el	Mon May 07 17:56:24 2012 +0100
@@ -3203,7 +3203,7 @@
     ((most-positive-fixnum-on-32-bit-machines () (1- (lsh 1 30)))
      (most-negative-fixnum-on-32-bit-machines ()
        (lognot (most-positive-fixnum-on-32-bit-machines))))
-  (defun cl-non-fixnum-number-p (object)
+  (defun cl-non-immediate-number-p (object)
     "Return t if OBJECT is a number not guaranteed to be immediate."
     (and (numberp object)
 	 (or (not (fixnump object))
@@ -3218,16 +3218,55 @@
 (define-compiler-macro eql (&whole form a b)
   (cond ((eq (cl-const-expr-p a) t)
 	 (let ((val (cl-const-expr-val a)))
-	   (if (cl-non-fixnum-number-p val)
+	   (if (cl-non-immediate-number-p val)
 	       (list 'equal a b)
 	     (list 'eq a b))))
 	((eq (cl-const-expr-p b) t)
 	 (let ((val (cl-const-expr-val b)))
-	   (if (cl-non-fixnum-number-p val)
+	   (if (cl-non-immediate-number-p val)
 	       (list 'equal a b)
 	     (list 'eq a b))))
 	(t form)))
 
+(defun cl-equal-equivalent-to-eq-p (object)
+  (or (symbolp object) (characterp object)
+      (and (fixnump object) (not (cl-non-immediate-number-p object)))))
+
+(defun cl-car-or-pi (object)
+  (if (consp object) (car object) pi))
+
+(defun cl-cdr-or-pi (object)
+  (if (consp object) (cdr object) pi))
+
+(define-compiler-macro equal (&whole form a b)
+  (if (or (cl-equal-equivalent-to-eq-p (cl-const-expr-val a pi))
+          (cl-equal-equivalent-to-eq-p (cl-const-expr-val b pi)))
+      (cons 'eq (cdr form))
+    form))
+
+(define-compiler-macro member (&whole form elt list)
+  (if (or (cl-equal-equivalent-to-eq-p (cl-const-expr-val elt pi))
+          (every #'cl-equal-equivalent-to-eq-p
+                 (cl-const-expr-val list '(1.0))))
+      (cons 'memq (cdr form))
+    form))
+
+(define-compiler-macro assoc (&whole form elt list)
+  (if (or (cl-equal-equivalent-to-eq-p (cl-const-expr-val elt pi))
+          (not (find-if-not #'cl-equal-equivalent-to-eq-p
+                            (cl-const-expr-val list '((1.0 . nil)))
+                            :key #'cl-car-or-pi)))
+      (cons 'assq (cdr form))
+    form))
+
+(define-compiler-macro rassoc (&whole form elt list)
+  (if (or (cl-equal-equivalent-to-eq-p (cl-const-expr-val elt pi))
+          (not (find-if-not #'cl-equal-equivalent-to-eq-p
+                            (cl-const-expr-val list '((nil . 1.0)))
+                            :key #'cl-cdr-or-pi)))
+      (cons 'rassq (cdr form))
+    form)))
+
 (macrolet
     ((define-star-compiler-macros (&rest macros)
        "For `member*', `assoc*' and `rassoc*' with constant ITEM or
@@ -3256,12 +3295,12 @@
                                  `(,',equal-function ,item ,list))
                                 ((and (eq test 'eql)
                                       (not (eq not-constant item-val)))
-                                 (if (cl-non-fixnum-number-p item-val)
+                                 (if (cl-non-immediate-number-p item-val)
                                      `(,',equal-function ,item ,list)
                                    `(,',eq-function ,item ,list)))
                                 ((and (eq test 'eql) (not (eq not-constant
                                                               list-val)))
-                                 (if (some 'cl-non-fixnum-number-p list-val)
+                                 (if (some 'cl-non-immediate-number-p list-val)
                                      `(,',equal-function ,item ,list)
                                    ;; This compiler macro used to limit
                                    ;; calls to ,,eq-function to lists where
@@ -3313,7 +3352,7 @@
           ((not-constant '#:not-constant))
         (let ((cl-const-expr-val (cl-const-expr-val (nth 1 form) not-constant)))
           (if (and (cdr form) (not (eq not-constant cl-const-expr-val))
-                   (not (cl-non-fixnum-number-p cl-const-expr-val)))
+                   (not (cl-non-immediate-number-p cl-const-expr-val)))
               (cons 'delete* (cdr form))
             `(delete* ,@(cdr form) :test #'eq))))
     form))
@@ -3336,7 +3375,7 @@
           ((not-constant '#:not-constant))
         (let ((cl-const-expr-val (cl-const-expr-val (nth 1 form) not-constant)))
           (if (and (cdr form) (not (eq not-constant cl-const-expr-val))
-                   (not (cl-non-fixnum-number-p cl-const-expr-val)))
+                   (not (cl-non-immediate-number-p cl-const-expr-val)))
               (cons 'remove* (cdr form))
             `(remove* ,@(cdr form) :test #'eq))))
     form))