diff options
| author | Stefan Monnier | 2015-10-28 13:59:42 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2015-10-28 13:59:42 -0400 |
| commit | d5ee655c1710a62e01513fd20256a7cf35d52167 (patch) | |
| tree | 9d53dd575f27624e44ec3851b3012f621e50f44b /lisp | |
| parent | 1f02cbea8b489ed7676110431aa36ad5abc47d9b (diff) | |
| download | emacs-d5ee655c1710a62e01513fd20256a7cf35d52167.tar.gz emacs-d5ee655c1710a62e01513fd20256a7cf35d52167.zip | |
* lisp/emacs-lisp/macroexp.el: Tweak macroexp-if optimizations
(macroexp-unprogn): Make sure we never return an empty list.
(macroexp-if): Remove unused (and unsafe) optimization.
Optimize (if A T (if B T E)) into (if (or A B) T E) instead, which does
occur occasionally.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/emacs-lisp/macroexp.el | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el index 8bf49b01689..8983454d318 100644 --- a/lisp/emacs-lisp/macroexp.el +++ b/lisp/emacs-lisp/macroexp.el | |||
| @@ -322,8 +322,9 @@ definitions to shadow the loaded ones for use in file byte-compilation." | |||
| 322 | (if (cdr exps) `(progn ,@exps) (car exps))) | 322 | (if (cdr exps) `(progn ,@exps) (car exps))) |
| 323 | 323 | ||
| 324 | (defun macroexp-unprogn (exp) | 324 | (defun macroexp-unprogn (exp) |
| 325 | "Turn EXP into a list of expressions to execute in sequence." | 325 | "Turn EXP into a list of expressions to execute in sequence. |
| 326 | (if (eq (car-safe exp) 'progn) (cdr exp) (list exp))) | 326 | Never returns an empty list." |
| 327 | (if (eq (car-safe exp) 'progn) (or (cdr exp) '(nil)) (list exp))) | ||
| 327 | 328 | ||
| 328 | (defun macroexp-let* (bindings exp) | 329 | (defun macroexp-let* (bindings exp) |
| 329 | "Return an expression equivalent to `(let* ,bindings ,exp)." | 330 | "Return an expression equivalent to `(let* ,bindings ,exp)." |
| @@ -333,22 +334,33 @@ definitions to shadow the loaded ones for use in file byte-compilation." | |||
| 333 | (t `(let* ,bindings ,exp)))) | 334 | (t `(let* ,bindings ,exp)))) |
| 334 | 335 | ||
| 335 | (defun macroexp-if (test then else) | 336 | (defun macroexp-if (test then else) |
| 336 | "Return an expression equivalent to `(if ,test ,then ,else)." | 337 | "Return an expression equivalent to `(if ,TEST ,THEN ,ELSE)." |
| 337 | (cond | 338 | (cond |
| 338 | ((eq (car-safe else) 'if) | 339 | ((eq (car-safe else) 'if) |
| 339 | (if (equal test (nth 1 else)) | 340 | (cond |
| 340 | ;; Doing a test a second time: get rid of the redundancy. | 341 | ;; Drop this optimization: It's unsafe (it assumes that `test' is |
| 341 | `(if ,test ,then ,@(nthcdr 3 else)) | 342 | ;; pure, or at least idempotent), and it's not used even a single |
| 342 | `(cond (,test ,then) | 343 | ;; time while compiling Emacs's sources. |
| 343 | (,(nth 1 else) ,(nth 2 else)) | 344 | ;;((equal test (nth 1 else)) |
| 344 | (t ,@(nthcdr 3 else))))) | 345 | ;; ;; Doing a test a second time: get rid of the redundancy. |
| 346 | ;; (message "macroexp-if: sharing 'test' %S" test) | ||
| 347 | ;; `(if ,test ,then ,@(nthcdr 3 else))) | ||
| 348 | ((equal then (nth 2 else)) | ||
| 349 | ;; (message "macroexp-if: sharing 'then' %S" then) | ||
| 350 | `(if (or ,test ,(nth 1 else)) ,then ,@(nthcdr 3 else))) | ||
| 351 | ((equal (macroexp-unprogn then) (nthcdr 3 else)) | ||
| 352 | ;; (message "macroexp-if: sharing 'then' with not %S" then) | ||
| 353 | `(if (or ,test (not ,(nth 1 else))) | ||
| 354 | ,then ,@(macroexp-unprogn (nth 2 else)))) | ||
| 355 | (t | ||
| 356 | `(cond (,test ,@(macroexp-unprogn then)) | ||
| 357 | (,(nth 1 else) ,@(macroexp-unprogn (nth 2 else))) | ||
| 358 | (t ,@(nthcdr 3 else)))))) | ||
| 345 | ((eq (car-safe else) 'cond) | 359 | ((eq (car-safe else) 'cond) |
| 346 | `(cond (,test ,then) | 360 | `(cond (,test ,@(macroexp-unprogn then)) ,@(cdr else))) |
| 347 | ;; Doing a test a second time: get rid of the redundancy, as above. | ||
| 348 | ,@(remove (assoc test else) (cdr else)))) | ||
| 349 | ;; Invert the test if that lets us reduce the depth of the tree. | 361 | ;; Invert the test if that lets us reduce the depth of the tree. |
| 350 | ((memq (car-safe then) '(if cond)) (macroexp-if `(not ,test) else then)) | 362 | ((memq (car-safe then) '(if cond)) (macroexp-if `(not ,test) else then)) |
| 351 | (t `(if ,test ,then ,else)))) | 363 | (t `(if ,test ,then ,@(macroexp-unprogn else))))) |
| 352 | 364 | ||
| 353 | (defmacro macroexp-let2 (test sym exp &rest body) | 365 | (defmacro macroexp-let2 (test sym exp &rest body) |
| 354 | "Evaluate BODY with SYM bound to an expression for EXP's value. | 366 | "Evaluate BODY with SYM bound to an expression for EXP's value. |