changeset 5523:810b77562486

Improve #'defsubst* a little, document a bug that remains. 2011-06-19 Aidan Kehoe <kehoea@parhasard.net> * cl-macs.el (defsubst*): * cl-macs.el (cl-defsubst-expand): If defaults refer to earlier args, or if there's a &rest arg, use #'proclaim-inline. Use #'symbol-macrolet instead of #'subst when replacing argument names with their values in the inline expansion; this avoids (most) instances where the symbol's function slot is used. Document a bug that occurs if the symbol is being shadowed in a lexically-contained scope.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 19 Jun 2011 19:03:39 +0100
parents 544e6336d37c
children e05d98bf9644
files lisp/ChangeLog lisp/cl-macs.el
diffstat 2 files changed, 37 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Sun Jun 19 17:43:03 2011 +0100
+++ b/lisp/ChangeLog	Sun Jun 19 19:03:39 2011 +0100
@@ -1,3 +1,15 @@
+2011-06-19  Aidan Kehoe  <kehoea@parhasard.net>
+
+	* cl-macs.el (defsubst*):
+	* cl-macs.el (cl-defsubst-expand):
+	If defaults refer to earlier args, or if there's a &rest arg, use
+	#'proclaim-inline.
+	Use #'symbol-macrolet instead of #'subst when replacing argument
+	names with their values in the inline expansion; this avoids
+	(most) instances where the symbol's function slot is used.
+	Document a bug that occurs if the symbol is being shadowed in a
+	lexically-contained scope.
+
 2011-06-19  Aidan Kehoe  <kehoea@parhasard.net>
 
 	* cl-macs.el:
--- a/lisp/cl-macs.el	Sun Jun 19 17:43:03 2011 +0100
+++ b/lisp/cl-macs.el	Sun Jun 19 19:03:39 2011 +0100
@@ -3201,7 +3201,10 @@
 	 (unsafe (not (cl-safe-expr-p pbody))))
     (while (and p (eq (cl-expr-contains arglist (car p)) 1)) (pop p))
     (list 'progn
-	  (if p nil   ; give up if defaults refer to earlier args
+	  (if (or p (memq '&rest arglist))
+              ; Defaults refer to earlier args, or we would have to cons up
+              ; something for &rest:
+              (list 'proclaim-inline name) 
 	    (list 'define-compiler-macro name
 		  (if (memq '&key arglist)
 		      (list* '&whole 'cl-whole '&cl-quote arglist)
@@ -3213,15 +3216,27 @@
 	  (list* 'defun* name arglist docstring body))))
 
 (defun cl-defsubst-expand (argns body simple whole unsafe &rest argvs)
-  (if (and whole (not (cl-safe-expr-p (cons 'progn argvs)))) whole
-    (if (cl-simple-exprs-p argvs) (setq simple t))
-    (let ((lets (mapcan #'(lambda (argn argv)
-			    (if (or simple (cl-const-expr-p argv))
-				(progn (setq body (subst argv argn body))
-				       (and unsafe (list (list argn argv))))
-			      (list (list argn argv))))
-			argns argvs)))
-      (if lets (list 'let lets body) body))))
+  (if (and whole (not (cl-safe-expr-p (cons 'progn argvs))))
+      whole
+    (if (cl-simple-exprs-p argvs)
+        (setq simple t))
+    (let* ((symbol-macros nil)
+           (lets (mapcan #'(lambda (argn argv)
+                             (if (or simple (cl-const-expr-p argv))
+                                 (progn (push (list argn argv) symbol-macros)
+                                        (and unsafe (list (list argn argv))))
+                               (list (list argn argv))))
+                         argns argvs)))
+      `(let ,lets
+         (symbol-macrolet
+             ;; #### Bug; this will happily substitute in places where the
+             ;; symbol is being shadowed in a different scope (e.g. inside
+             ;; let bindings or lambda expressions where it has been
+             ;; bound). We don't have GNU's issue where the replacement will
+             ;; be done when the symbol is used in a function context,
+             ;; because we're using #'symbol-macrolet instead of #'subst.
+             ,symbol-macros
+           ,body)))))
 
 ;; When a 64-bit build is byte-compiling code, some of its native fixnums
 ;; will not be represented as fixnums if the byte-compiled code is read by