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))))))))