diff options
| author | Noam Postavsky | 2020-04-30 19:33:34 -0400 |
|---|---|---|
| committer | Noam Postavsky | 2020-05-05 21:07:58 -0400 |
| commit | 79e133da034cd2d7cccfc5a6eb7db340f2dc45a8 (patch) | |
| tree | bd6713c2afedb6ec8c8ab04d136382ed215f4ac3 | |
| parent | 7be160d80002cd000f33da38d3a2f7a2920c1bf5 (diff) | |
| download | emacs-79e133da034cd2d7cccfc5a6eb7db340f2dc45a8.tar.gz emacs-79e133da034cd2d7cccfc5a6eb7db340f2dc45a8.zip | |
Revert "Refix conditional step clauses in cl-loop"
Don't merge to master. This is a safe-for-release fix for Bug#40727.
| -rw-r--r-- | lisp/emacs-lisp/cl-macs.el | 96 |
1 files changed, 59 insertions, 37 deletions
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index d56f4151df7..cda25d186fd 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el | |||
| @@ -889,7 +889,7 @@ This is compatible with Common Lisp, but note that `defun' and | |||
| 889 | ;;; The "cl-loop" macro. | 889 | ;;; The "cl-loop" macro. |
| 890 | 890 | ||
| 891 | (defvar cl--loop-args) (defvar cl--loop-accum-var) (defvar cl--loop-accum-vars) | 891 | (defvar cl--loop-args) (defvar cl--loop-accum-var) (defvar cl--loop-accum-vars) |
| 892 | (defvar cl--loop-bindings) (defvar cl--loop-body) (defvar cl--loop-conditions) | 892 | (defvar cl--loop-bindings) (defvar cl--loop-body) |
| 893 | (defvar cl--loop-finally) | 893 | (defvar cl--loop-finally) |
| 894 | (defvar cl--loop-finish-flag) ;Symbol set to nil to exit the loop? | 894 | (defvar cl--loop-finish-flag) ;Symbol set to nil to exit the loop? |
| 895 | (defvar cl--loop-first-flag) | 895 | (defvar cl--loop-first-flag) |
| @@ -897,7 +897,7 @@ This is compatible with Common Lisp, but note that `defun' and | |||
| 897 | (defvar cl--loop-name) | 897 | (defvar cl--loop-name) |
| 898 | (defvar cl--loop-result) (defvar cl--loop-result-explicit) | 898 | (defvar cl--loop-result) (defvar cl--loop-result-explicit) |
| 899 | (defvar cl--loop-result-var) (defvar cl--loop-steps) | 899 | (defvar cl--loop-result-var) (defvar cl--loop-steps) |
| 900 | (defvar cl--loop-symbol-macs) | 900 | (defvar cl--loop-symbol-macs) (defvar cl--loop-guard-cond) |
| 901 | 901 | ||
| 902 | (defun cl--loop-set-iterator-function (kind iterator) | 902 | (defun cl--loop-set-iterator-function (kind iterator) |
| 903 | (if cl--loop-iterator-function | 903 | (if cl--loop-iterator-function |
| @@ -966,8 +966,7 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 966 | (cl--loop-accum-var nil) (cl--loop-accum-vars nil) | 966 | (cl--loop-accum-var nil) (cl--loop-accum-vars nil) |
| 967 | (cl--loop-initially nil) (cl--loop-finally nil) | 967 | (cl--loop-initially nil) (cl--loop-finally nil) |
| 968 | (cl--loop-iterator-function nil) (cl--loop-first-flag nil) | 968 | (cl--loop-iterator-function nil) (cl--loop-first-flag nil) |
| 969 | (cl--loop-symbol-macs nil) | 969 | (cl--loop-symbol-macs nil) (cl--loop-guard-cond nil)) |
| 970 | (cl--loop-conditions nil)) | ||
| 971 | ;; Here is more or less how those dynbind vars are used after looping | 970 | ;; Here is more or less how those dynbind vars are used after looping |
| 972 | ;; over cl--parse-loop-clause: | 971 | ;; over cl--parse-loop-clause: |
| 973 | ;; | 972 | ;; |
| @@ -1002,7 +1001,24 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1002 | (list (or cl--loop-result-explicit | 1001 | (list (or cl--loop-result-explicit |
| 1003 | cl--loop-result)))) | 1002 | cl--loop-result)))) |
| 1004 | (ands (cl--loop-build-ands (nreverse cl--loop-body))) | 1003 | (ands (cl--loop-build-ands (nreverse cl--loop-body))) |
| 1005 | (while-body (nconc (cadr ands) (nreverse cl--loop-steps))) | 1004 | (while-body |
| 1005 | (nconc | ||
| 1006 | (cadr ands) | ||
| 1007 | (if (or (not cl--loop-guard-cond) (not cl--loop-first-flag)) | ||
| 1008 | (nreverse cl--loop-steps) | ||
| 1009 | ;; Right after update the loop variable ensure that the loop | ||
| 1010 | ;; condition, i.e. (car ands), is still satisfied; otherwise, | ||
| 1011 | ;; set `cl--loop-first-flag' nil and skip the remaining | ||
| 1012 | ;; body forms (#Bug#29799). | ||
| 1013 | ;; | ||
| 1014 | ;; (last cl--loop-steps) updates the loop var | ||
| 1015 | ;; (car (butlast cl--loop-steps)) sets `cl--loop-first-flag' nil | ||
| 1016 | ;; (nreverse (cdr (butlast cl--loop-steps))) are the | ||
| 1017 | ;; remaining body forms. | ||
| 1018 | (append (last cl--loop-steps) | ||
| 1019 | `((and ,(car ands) | ||
| 1020 | ,@(nreverse (cdr (butlast cl--loop-steps))))) | ||
| 1021 | `(,(car (butlast cl--loop-steps))))))) | ||
| 1006 | (body (append | 1022 | (body (append |
| 1007 | (nreverse cl--loop-initially) | 1023 | (nreverse cl--loop-initially) |
| 1008 | (list (if cl--loop-iterator-function | 1024 | (list (if cl--loop-iterator-function |
| @@ -1035,12 +1051,6 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1035 | (list `(cl-symbol-macrolet ,cl--loop-symbol-macs ,@body)))) | 1051 | (list `(cl-symbol-macrolet ,cl--loop-symbol-macs ,@body)))) |
| 1036 | `(cl-block ,cl--loop-name ,@body))))) | 1052 | `(cl-block ,cl--loop-name ,@body))))) |
| 1037 | 1053 | ||
| 1038 | (defmacro cl--push-clause-loop-body (clause) | ||
| 1039 | "Apply CLAUSE to both `cl--loop-conditions' and `cl--loop-body'." | ||
| 1040 | `(progn | ||
| 1041 | (push ,clause cl--loop-conditions) | ||
| 1042 | (push ,clause cl--loop-body))) | ||
| 1043 | |||
| 1044 | ;; Below is a complete spec for cl-loop, in several parts that correspond | 1054 | ;; Below is a complete spec for cl-loop, in several parts that correspond |
| 1045 | ;; to the syntax given in CLtL2. The specs do more than specify where | 1055 | ;; to the syntax given in CLtL2. The specs do more than specify where |
| 1046 | ;; the forms are; it also specifies, as much as Edebug allows, all the | 1056 | ;; the forms are; it also specifies, as much as Edebug allows, all the |
| @@ -1191,6 +1201,8 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1191 | ;; (def-edebug-spec loop-d-type-spec | 1201 | ;; (def-edebug-spec loop-d-type-spec |
| 1192 | ;; (&or (loop-d-type-spec . [&or nil loop-d-type-spec]) cl-type-spec)) | 1202 | ;; (&or (loop-d-type-spec . [&or nil loop-d-type-spec]) cl-type-spec)) |
| 1193 | 1203 | ||
| 1204 | |||
| 1205 | |||
| 1194 | (defun cl--parse-loop-clause () ; uses loop-* | 1206 | (defun cl--parse-loop-clause () ; uses loop-* |
| 1195 | (let ((word (pop cl--loop-args)) | 1207 | (let ((word (pop cl--loop-args)) |
| 1196 | (hash-types '(hash-key hash-keys hash-value hash-values)) | 1208 | (hash-types '(hash-key hash-keys hash-value hash-values)) |
| @@ -1269,11 +1281,11 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1269 | (if end-var (push (list end-var end) loop-for-bindings)) | 1281 | (if end-var (push (list end-var end) loop-for-bindings)) |
| 1270 | (if step-var (push (list step-var step) | 1282 | (if step-var (push (list step-var step) |
| 1271 | loop-for-bindings)) | 1283 | loop-for-bindings)) |
| 1272 | (when end | 1284 | (if end |
| 1273 | (cl--push-clause-loop-body | 1285 | (push (list |
| 1274 | (list | 1286 | (if down (if excl '> '>=) (if excl '< '<=)) |
| 1275 | (if down (if excl '> '>=) (if excl '< '<=)) | 1287 | var (or end-var end)) |
| 1276 | var (or end-var end)))) | 1288 | cl--loop-body)) |
| 1277 | (push (list var (list (if down '- '+) var | 1289 | (push (list var (list (if down '- '+) var |
| 1278 | (or step-var step 1))) | 1290 | (or step-var step 1))) |
| 1279 | loop-for-steps))) | 1291 | loop-for-steps))) |
| @@ -1283,7 +1295,7 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1283 | (temp (if (and on (symbolp var)) | 1295 | (temp (if (and on (symbolp var)) |
| 1284 | var (make-symbol "--cl-var--")))) | 1296 | var (make-symbol "--cl-var--")))) |
| 1285 | (push (list temp (pop cl--loop-args)) loop-for-bindings) | 1297 | (push (list temp (pop cl--loop-args)) loop-for-bindings) |
| 1286 | (cl--push-clause-loop-body `(consp ,temp)) | 1298 | (push `(consp ,temp) cl--loop-body) |
| 1287 | (if (eq word 'in-ref) | 1299 | (if (eq word 'in-ref) |
| 1288 | (push (list var `(car ,temp)) cl--loop-symbol-macs) | 1300 | (push (list var `(car ,temp)) cl--loop-symbol-macs) |
| 1289 | (or (eq temp var) | 1301 | (or (eq temp var) |
| @@ -1306,19 +1318,24 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1306 | ((eq word '=) | 1318 | ((eq word '=) |
| 1307 | (let* ((start (pop cl--loop-args)) | 1319 | (let* ((start (pop cl--loop-args)) |
| 1308 | (then (if (eq (car cl--loop-args) 'then) | 1320 | (then (if (eq (car cl--loop-args) 'then) |
| 1309 | (cl--pop2 cl--loop-args) start)) | 1321 | (cl--pop2 cl--loop-args) start))) |
| 1310 | (first-assign (or cl--loop-first-flag | ||
| 1311 | (setq cl--loop-first-flag | ||
| 1312 | (make-symbol "--cl-var--"))))) | ||
| 1313 | (push (list var nil) loop-for-bindings) | 1322 | (push (list var nil) loop-for-bindings) |
| 1314 | (if (or ands (eq (car cl--loop-args) 'and)) | 1323 | (if (or ands (eq (car cl--loop-args) 'and)) |
| 1315 | (progn | 1324 | (progn |
| 1316 | (push `(,var (if ,first-assign ,start ,var)) loop-for-sets) | 1325 | (push `(,var |
| 1317 | (push `(,var (if ,(car (cl--loop-build-ands | 1326 | (if ,(or cl--loop-first-flag |
| 1318 | (nreverse cl--loop-conditions))) | 1327 | (setq cl--loop-first-flag |
| 1319 | ,then ,var)) | 1328 | (make-symbol "--cl-var--"))) |
| 1320 | loop-for-steps)) | 1329 | ,start ,var)) |
| 1321 | (push `(,var (if ,first-assign ,start ,then)) loop-for-sets)))) | 1330 | loop-for-sets) |
| 1331 | (push (list var then) loop-for-steps)) | ||
| 1332 | (push (list var | ||
| 1333 | (if (eq start then) start | ||
| 1334 | `(if ,(or cl--loop-first-flag | ||
| 1335 | (setq cl--loop-first-flag | ||
| 1336 | (make-symbol "--cl-var--"))) | ||
| 1337 | ,start ,then))) | ||
| 1338 | loop-for-sets)))) | ||
| 1322 | 1339 | ||
| 1323 | ((memq word '(across across-ref)) | 1340 | ((memq word '(across across-ref)) |
| 1324 | (let ((temp-vec (make-symbol "--cl-vec--")) | 1341 | (let ((temp-vec (make-symbol "--cl-vec--")) |
| @@ -1327,8 +1344,9 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1327 | (push (list temp-vec (pop cl--loop-args)) loop-for-bindings) | 1344 | (push (list temp-vec (pop cl--loop-args)) loop-for-bindings) |
| 1328 | (push (list temp-len `(length ,temp-vec)) loop-for-bindings) | 1345 | (push (list temp-len `(length ,temp-vec)) loop-for-bindings) |
| 1329 | (push (list temp-idx -1) loop-for-bindings) | 1346 | (push (list temp-idx -1) loop-for-bindings) |
| 1330 | (cl--push-clause-loop-body | 1347 | (push `(< (setq ,temp-idx (1+ ,temp-idx)) |
| 1331 | `(< (setq ,temp-idx (1+ ,temp-idx)) ,temp-len)) | 1348 | ,temp-len) |
| 1349 | cl--loop-body) | ||
| 1332 | (if (eq word 'across-ref) | 1350 | (if (eq word 'across-ref) |
| 1333 | (push (list var `(aref ,temp-vec ,temp-idx)) | 1351 | (push (list var `(aref ,temp-vec ,temp-idx)) |
| 1334 | cl--loop-symbol-macs) | 1352 | cl--loop-symbol-macs) |
| @@ -1358,14 +1376,15 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1358 | loop-for-bindings) | 1376 | loop-for-bindings) |
| 1359 | (push (list var `(elt ,temp-seq ,temp-idx)) | 1377 | (push (list var `(elt ,temp-seq ,temp-idx)) |
| 1360 | cl--loop-symbol-macs) | 1378 | cl--loop-symbol-macs) |
| 1361 | (cl--push-clause-loop-body `(< ,temp-idx ,temp-len))) | 1379 | (push `(< ,temp-idx ,temp-len) cl--loop-body)) |
| 1362 | ;; Evaluate seq length just if needed, that is, when seq is not a cons. | 1380 | ;; Evaluate seq length just if needed, that is, when seq is not a cons. |
| 1363 | (push (list temp-len (or (consp seq) `(length ,temp-seq))) | 1381 | (push (list temp-len (or (consp seq) `(length ,temp-seq))) |
| 1364 | loop-for-bindings) | 1382 | loop-for-bindings) |
| 1365 | (push (list var nil) loop-for-bindings) | 1383 | (push (list var nil) loop-for-bindings) |
| 1366 | (cl--push-clause-loop-body `(and ,temp-seq | 1384 | (push `(and ,temp-seq |
| 1367 | (or (consp ,temp-seq) | 1385 | (or (consp ,temp-seq) |
| 1368 | (< ,temp-idx ,temp-len)))) | 1386 | (< ,temp-idx ,temp-len))) |
| 1387 | cl--loop-body) | ||
| 1369 | (push (list var `(if (consp ,temp-seq) | 1388 | (push (list var `(if (consp ,temp-seq) |
| 1370 | (pop ,temp-seq) | 1389 | (pop ,temp-seq) |
| 1371 | (aref ,temp-seq ,temp-idx))) | 1390 | (aref ,temp-seq ,temp-idx))) |
| @@ -1461,8 +1480,9 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1461 | (push (list var '(selected-frame)) | 1480 | (push (list var '(selected-frame)) |
| 1462 | loop-for-bindings) | 1481 | loop-for-bindings) |
| 1463 | (push (list temp nil) loop-for-bindings) | 1482 | (push (list temp nil) loop-for-bindings) |
| 1464 | (cl--push-clause-loop-body `(prog1 (not (eq ,var ,temp)) | 1483 | (push `(prog1 (not (eq ,var ,temp)) |
| 1465 | (or ,temp (setq ,temp ,var)))) | 1484 | (or ,temp (setq ,temp ,var))) |
| 1485 | cl--loop-body) | ||
| 1466 | (push (list var `(next-frame ,var)) | 1486 | (push (list var `(next-frame ,var)) |
| 1467 | loop-for-steps))) | 1487 | loop-for-steps))) |
| 1468 | 1488 | ||
| @@ -1483,8 +1503,9 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1483 | (push (list minip `(minibufferp (window-buffer ,var))) | 1503 | (push (list minip `(minibufferp (window-buffer ,var))) |
| 1484 | loop-for-bindings) | 1504 | loop-for-bindings) |
| 1485 | (push (list temp nil) loop-for-bindings) | 1505 | (push (list temp nil) loop-for-bindings) |
| 1486 | (cl--push-clause-loop-body `(prog1 (not (eq ,var ,temp)) | 1506 | (push `(prog1 (not (eq ,var ,temp)) |
| 1487 | (or ,temp (setq ,temp ,var)))) | 1507 | (or ,temp (setq ,temp ,var))) |
| 1508 | cl--loop-body) | ||
| 1488 | (push (list var `(next-window ,var ,minip)) | 1509 | (push (list var `(next-window ,var ,minip)) |
| 1489 | loop-for-steps))) | 1510 | loop-for-steps))) |
| 1490 | 1511 | ||
| @@ -1508,6 +1529,7 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1508 | t) | 1529 | t) |
| 1509 | cl--loop-body)) | 1530 | cl--loop-body)) |
| 1510 | (when loop-for-steps | 1531 | (when loop-for-steps |
| 1532 | (setq cl--loop-guard-cond t) | ||
| 1511 | (push (cons (if ands 'cl-psetq 'setq) | 1533 | (push (cons (if ands 'cl-psetq 'setq) |
| 1512 | (apply 'append (nreverse loop-for-steps))) | 1534 | (apply 'append (nreverse loop-for-steps))) |
| 1513 | cl--loop-steps)))) | 1535 | cl--loop-steps)))) |