diff options
| author | Tino Calancha | 2018-01-08 19:11:20 +0900 |
|---|---|---|
| committer | Tino Calancha | 2018-01-08 19:15:28 +0900 |
| commit | a0365437c9ee308ad7978e436631020f513b25e7 (patch) | |
| tree | c6164968de607fd2bfd37c32983fe9a4be0eceba /test | |
| parent | 1daac66a6eedbcbfa32ab920b5c579872d989517 (diff) | |
| download | emacs-a0365437c9ee308ad7978e436631020f513b25e7.tar.gz emacs-a0365437c9ee308ad7978e436631020f513b25e7.zip | |
cl-loop: Add missing guard condition
Consider the expansion of `cl-loop' with a `for' clause and more
than one internal variables, X, Y, processed in parallel.
Each step updates X and Y right after update the loop variable, K; if
either X or Y depend on K, then some forms of the body are
evaluated with the wrong K (Bug#29799).
For instance, consider the following code:
(cl-loop for k below 2
for x = (progn (message "k = %d" k) 1)
and y = 1)
This code should show in *Messages*:
k = 0
k = 1
Instead, the code shows:
k = 0
k = 1
k = 2
To prevent this we must ensure that the loop condition is still
satisfied right after update the loop variable.
In the macro expansion of the example above, right after:
(setq k (+ k 1))
evaluate the rest of the body forms iif the condition
(< k 2)
is still valid.
* lisp/emacs-lisp/cl-macs.el (cl--loop-guard-cond): New variable.
(cl--parse-loop-clause): Set it non-nil if the loop contains
a for/as clause.
(cl-loop): After update the loop variable, evaluate the remaining of
the body forms just if the loop condition is still valid (Bug#29799).
* test/lisp/emacs-lisp/cl-macs-tests.el (cl-macs-loop-for-as-equals-and):
New test.
Diffstat (limited to 'test')
| -rw-r--r-- | test/lisp/emacs-lisp/cl-macs-tests.el | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/test/lisp/emacs-lisp/cl-macs-tests.el b/test/lisp/emacs-lisp/cl-macs-tests.el index f0bde7af397..edb1530cad5 100644 --- a/test/lisp/emacs-lisp/cl-macs-tests.el +++ b/test/lisp/emacs-lisp/cl-macs-tests.el | |||
| @@ -497,4 +497,12 @@ collection clause." | |||
| 497 | vconcat (vector (1+ x))) | 497 | vconcat (vector (1+ x))) |
| 498 | [2 3 4 5 6]))) | 498 | [2 3 4 5 6]))) |
| 499 | 499 | ||
| 500 | |||
| 501 | (ert-deftest cl-macs-loop-for-as-equals-and () | ||
| 502 | "Test for https://debbugs.gnu.org/29799 ." | ||
| 503 | (let ((arr (make-vector 3 0))) | ||
| 504 | (should (equal '((0 0) (1 1) (2 2)) | ||
| 505 | (cl-loop for k below 3 for x = k and z = (elt arr k) | ||
| 506 | collect (list k x)))))) | ||
| 507 | |||
| 500 | ;;; cl-macs-tests.el ends here | 508 | ;;; cl-macs-tests.el ends here |