diff options
| -rw-r--r-- | lisp/emacs-lisp/cl-macs.el | 32 | ||||
| -rw-r--r-- | test/lisp/emacs-lisp/cl-macs-tests.el | 8 |
2 files changed, 33 insertions, 7 deletions
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index 9af014cf8e9..43eb4261162 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el | |||
| @@ -892,7 +892,7 @@ This is compatible with Common Lisp, but note that `defun' and | |||
| 892 | (defvar cl--loop-name) | 892 | (defvar cl--loop-name) |
| 893 | (defvar cl--loop-result) (defvar cl--loop-result-explicit) | 893 | (defvar cl--loop-result) (defvar cl--loop-result-explicit) |
| 894 | (defvar cl--loop-result-var) (defvar cl--loop-steps) | 894 | (defvar cl--loop-result-var) (defvar cl--loop-steps) |
| 895 | (defvar cl--loop-symbol-macs) | 895 | (defvar cl--loop-symbol-macs) (defvar cl--loop-guard-cond) |
| 896 | 896 | ||
| 897 | (defun cl--loop-set-iterator-function (kind iterator) | 897 | (defun cl--loop-set-iterator-function (kind iterator) |
| 898 | (if cl--loop-iterator-function | 898 | (if cl--loop-iterator-function |
| @@ -961,7 +961,7 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 961 | (cl--loop-accum-var nil) (cl--loop-accum-vars nil) | 961 | (cl--loop-accum-var nil) (cl--loop-accum-vars nil) |
| 962 | (cl--loop-initially nil) (cl--loop-finally nil) | 962 | (cl--loop-initially nil) (cl--loop-finally nil) |
| 963 | (cl--loop-iterator-function nil) (cl--loop-first-flag nil) | 963 | (cl--loop-iterator-function nil) (cl--loop-first-flag nil) |
| 964 | (cl--loop-symbol-macs nil)) | 964 | (cl--loop-symbol-macs nil) (cl--loop-guard-cond nil)) |
| 965 | ;; Here is more or less how those dynbind vars are used after looping | 965 | ;; Here is more or less how those dynbind vars are used after looping |
| 966 | ;; over cl--parse-loop-clause: | 966 | ;; over cl--parse-loop-clause: |
| 967 | ;; | 967 | ;; |
| @@ -996,7 +996,24 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 996 | (list (or cl--loop-result-explicit | 996 | (list (or cl--loop-result-explicit |
| 997 | cl--loop-result)))) | 997 | cl--loop-result)))) |
| 998 | (ands (cl--loop-build-ands (nreverse cl--loop-body))) | 998 | (ands (cl--loop-build-ands (nreverse cl--loop-body))) |
| 999 | (while-body (nconc (cadr ands) (nreverse cl--loop-steps))) | 999 | (while-body |
| 1000 | (nconc | ||
| 1001 | (cadr ands) | ||
| 1002 | (if (or (not cl--loop-guard-cond) (not cl--loop-first-flag)) | ||
| 1003 | (nreverse cl--loop-steps) | ||
| 1004 | ;; Right after update the loop variable ensure that the loop | ||
| 1005 | ;; condition, i.e. (car ands), is still satisfied; otherwise, | ||
| 1006 | ;; set `cl--loop-first-flag' nil and skip the remaining | ||
| 1007 | ;; body forms (#Bug#29799). | ||
| 1008 | ;; | ||
| 1009 | ;; (last cl--loop-steps) updates the loop var | ||
| 1010 | ;; (car (butlast cl--loop-steps)) sets `cl--loop-first-flag' nil | ||
| 1011 | ;; (nreverse (cdr (butlast cl--loop-steps))) are the | ||
| 1012 | ;; remaining body forms. | ||
| 1013 | (append (last cl--loop-steps) | ||
| 1014 | `((and ,(car ands) | ||
| 1015 | ,@(nreverse (cdr (butlast cl--loop-steps))))) | ||
| 1016 | `(,(car (butlast cl--loop-steps))))))) | ||
| 1000 | (body (append | 1017 | (body (append |
| 1001 | (nreverse cl--loop-initially) | 1018 | (nreverse cl--loop-initially) |
| 1002 | (list (if cl--loop-iterator-function | 1019 | (list (if cl--loop-iterator-function |
| @@ -1506,10 +1523,11 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1506 | ,(cl--loop-let (nreverse loop-for-sets) 'setq ands) | 1523 | ,(cl--loop-let (nreverse loop-for-sets) 'setq ands) |
| 1507 | t) | 1524 | t) |
| 1508 | cl--loop-body)) | 1525 | cl--loop-body)) |
| 1509 | (if loop-for-steps | 1526 | (when loop-for-steps |
| 1510 | (push (cons (if ands 'cl-psetq 'setq) | 1527 | (setq cl--loop-guard-cond t) |
| 1511 | (apply 'append (nreverse loop-for-steps))) | 1528 | (push (cons (if ands 'cl-psetq 'setq) |
| 1512 | cl--loop-steps)))) | 1529 | (apply 'append (nreverse loop-for-steps))) |
| 1530 | cl--loop-steps)))) | ||
| 1513 | 1531 | ||
| 1514 | ((eq word 'repeat) | 1532 | ((eq word 'repeat) |
| 1515 | (let ((temp (make-symbol "--cl-var--"))) | 1533 | (let ((temp (make-symbol "--cl-var--"))) |
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 |