branch: elpa/loopy
commit 07a9952cd6c03e9573afecf95ffb4eed7521d559
Author: okamsn <[email protected]>
Commit: GitHub <[email protected]>

    For destructuring accumulation, maintain order of expressions used by 
`pcase`. (#251)
    
    When destructuring for accumulation commands, don't assume that `pcase` 
binds
    the final variable to a value already stored in a temporary variable.  More
    specifically, in `loopy--pcase-parse-for-destructuring-accumulation-command`
    keep the same order returned by `pcase` for the binding of those final
    variables.
    
    This is not known to be an error, but could possibly produce one for some
    unknown `pcase` pattern.
---
 CHANGELOG.md              | 11 +++++++++++
 lisp/loopy-destructure.el | 26 ++++++++++++++++++++++----
 2 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a792a2d092b..67e98beea96 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,17 @@ This document describes the user-facing changes to Loopy.
 
 For Loopy Dash, see <https://github.com/okamsn/loopy-dash>.
 
+## Unreleased
+
+### Bug Fixes
+
+- When destructuring for accumulation commands, don't assume that `pcase` binds
+  the final variable to a value already stored in a temporary variable 
([#251]).
+  More specifically, keep the same order returned by `pcase` for the binding of
+  those final variables.
+
+[#251]: https://github.com/okamsn/loopy/PR/251
+
 ## 0.15.0
 
 ### New Features
diff --git a/lisp/loopy-destructure.el b/lisp/loopy-destructure.el
index a14e1751435..10efeae2249 100644
--- a/lisp/loopy-destructure.el
+++ b/lisp/loopy-destructure.el
@@ -995,7 +995,7 @@ an error should be signaled if the pattern doesn't match."
                  (remq nil
                        (list (cons var
                                    (lambda (varvals &rest _)
-                                     (let ((destr-main-body))
+                                     (let ((destr-main-body nil))
                                        (dolist (varval varvals)
                                          (let ((destr-var (cl-first varval))
                                                (destr-val (cl-second varval)))
@@ -1010,7 +1010,16 @@ an error should be signaled if the pattern doesn't 
match."
                                        ;; The lambda returns the destructured 
main body,
                                        ;; which needs to be wrapped by Pcase's
                                        ;; destructured bindings.
-                                       (macroexp-progn (apply #'append 
destr-main-body)))))
+                                       ;;
+                                       ;; We keep these in the order returned 
by
+                                       ;; Pcase just in case Pcase uses state
+                                       ;; (such as push and pop).  It does not
+                                       ;; appear to use state, but we do it
+                                       ;; anyway.
+                                       (thread-last destr-main-body
+                                                    nreverse
+                                                    (apply #'append)
+                                                    macroexp-progn))))
                              (when error
                                (cons '_ #'signaler))))))
         ;; NOTE: In Emacs versions less than 28, this functionality technically
@@ -1023,7 +1032,7 @@ an error should be signaled if the pattern doesn't match."
                                                 var
                                               `(or ,var pcase--dontcare))))
                             ,(lambda (vars)
-                               (let ((destr-main-body))
+                               (let ((destr-main-body nil))
                                  (dolist (v vars)
                                    (let ((destr-var (car v))
                                          ;; Use `cadr' for Emacs 28+, `cdr' 
for less.
@@ -1043,7 +1052,16 @@ an error should be signaled if the pattern doesn't 
match."
                                  ;; The lambda returns the destructured main 
body,
                                  ;; which needs to be wrapped by Pcase's
                                  ;; destructured bindings.
-                                 (macroexp-progn (apply #'append 
destr-main-body)))))
+                                 ;;
+                                 ;; We keep these in the order returned by
+                                 ;; Pcase just in case Pcase uses state
+                                 ;; (such as push and pop).  It does not
+                                 ;; appear to use state, but we do it
+                                 ;; anyway.
+                                 (thread-last destr-main-body
+                                              nreverse
+                                              (apply #'append)
+                                              macroexp-progn))))
                            ,(when error
                               (list (pcase--match value-holder 
(pcase--macroexpand '_))
                                     #'signaler))))))))

Reply via email to