# HG changeset patch # User Aidan Kehoe # Date 1308506619 -3600 # Node ID 810b775624861e2fe6ea3b238370c6a3b840a4de # Parent 544e6336d37cbafad876c7a838a072bf1af6dce4 Improve #'defsubst* a little, document a bug that remains. 2011-06-19 Aidan Kehoe * 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. diff -r 544e6336d37c -r 810b77562486 lisp/ChangeLog --- 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 + + * 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 * cl-macs.el: diff -r 544e6336d37c -r 810b77562486 lisp/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