@@ -889,15 +889,15 @@ This is compatible with Common Lisp, but note that `defun' and
889
889
; ;; The "cl-loop" macro.
890
890
891
891
(defvar cl--loop-args ) (defvar cl--loop-accum-var ) (defvar cl--loop-accum-vars )
892
- (defvar cl--loop-bindings ) (defvar cl--loop-body )
892
+ (defvar cl--loop-bindings ) (defvar cl--loop-body ) ( defvar cl--loop-conditions )
893
893
(defvar cl--loop-finally )
894
894
(defvar cl--loop-finish-flag ) ; Symbol set to nil to exit the loop?
895
895
(defvar cl--loop-first-flag )
896
896
(defvar cl--loop-initially ) (defvar cl--loop-iterator-function )
897
897
(defvar cl--loop-name )
898
898
(defvar cl--loop-result ) (defvar cl--loop-result-explicit )
899
899
(defvar cl--loop-result-var ) (defvar cl--loop-steps )
900
- (defvar cl--loop-symbol-macs ) ( defvar cl--loop-guard-cond )
900
+ (defvar cl--loop-symbol-macs )
901
901
902
902
(defun cl--loop-set-iterator-function (kind iterator )
903
903
(if cl--loop-iterator-function
@@ -966,7 +966,8 @@ For more details, see Info node `(cl)Loop Facility'.
966
966
(cl--loop-accum-var nil ) (cl--loop-accum-vars nil )
967
967
(cl--loop-initially nil ) (cl--loop-finally nil )
968
968
(cl--loop-iterator-function nil ) (cl--loop-first-flag nil )
969
- (cl--loop-symbol-macs nil ) (cl--loop-guard-cond nil ))
969
+ (cl--loop-symbol-macs nil )
970
+ (cl--loop-conditions nil ))
970
971
; ; Here is more or less how those dynbind vars are used after looping
971
972
; ; over cl--parse-loop-clause:
972
973
; ;
@@ -1001,24 +1002,7 @@ For more details, see Info node `(cl)Loop Facility'.
1001
1002
(list (or cl--loop-result-explicit
1002
1003
cl--loop-result))))
1003
1004
(ands (cl--loop-build-ands (nreverse cl--loop-body)))
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)))))))
1005
+ (while-body (nconc (cadr ands) (nreverse cl--loop-steps)))
1022
1006
(body (append
1023
1007
(nreverse cl--loop-initially)
1024
1008
(list (if cl--loop-iterator-function
@@ -1051,6 +1035,12 @@ For more details, see Info node `(cl)Loop Facility'.
1051
1035
(list `(cl-symbol-macrolet , cl--loop-symbol-macs ,@body ))))
1052
1036
`(cl-block , cl--loop-name ,@body )))))
1053
1037
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
+
1054
1044
; ; Below is a complete spec for cl-loop, in several parts that correspond
1055
1045
; ; to the syntax given in CLtL2. The specs do more than specify where
1056
1046
; ; the forms are; it also specifies, as much as Edebug allows, all the
@@ -1201,8 +1191,6 @@ For more details, see Info node `(cl)Loop Facility'.
1201
1191
; ; (def-edebug-spec loop-d-type-spec
1202
1192
; ; (&or (loop-d-type-spec . [&or nil loop-d-type-spec]) cl-type-spec))
1203
1193
1204
-
1205
-
1206
1194
(defun cl--parse-loop-clause () ; uses loop-*
1207
1195
(let ((word (pop cl--loop-args))
1208
1196
(hash-types '(hash-key hash-keys hash-value hash-values))
@@ -1281,11 +1269,11 @@ For more details, see Info node `(cl)Loop Facility'.
1281
1269
(if end-var (push (list end-var end) loop-for-bindings))
1282
1270
(if step-var (push (list step-var step)
1283
1271
loop-for-bindings))
1284
- (if end
1285
- ( push ( list
1286
- ( if down ( if excl ' > '> = ) ( if excl ' < '< = ))
1287
- var ( or end-var end ))
1288
- cl--loop-body ))
1272
+ (when end
1273
+ (cl--push-clause-loop-body
1274
+ ( list
1275
+ ( if down ( if excl ' > '> = ) ( if excl ' < '< = ))
1276
+ var ( or end-var end)) ))
1289
1277
(push (list var (list (if down '- '+ ) var
1290
1278
(or step-var step 1 )))
1291
1279
loop-for-steps)))
@@ -1295,7 +1283,7 @@ For more details, see Info node `(cl)Loop Facility'.
1295
1283
(temp (if (and on (symbolp var))
1296
1284
var (make-symbol " --cl-var--" ))))
1297
1285
(push (list temp (pop cl--loop-args)) loop-for-bindings)
1298
- ( push `(consp , temp ) cl--loop-body )
1286
+ (cl-- push-clause-loop-body `(consp , temp ))
1299
1287
(if (eq word 'in-ref )
1300
1288
(push (list var `(car , temp )) cl--loop-symbol-macs)
1301
1289
(or (eq temp var)
@@ -1318,24 +1306,19 @@ For more details, see Info node `(cl)Loop Facility'.
1318
1306
((eq word '= )
1319
1307
(let* ((start (pop cl--loop-args))
1320
1308
(then (if (eq (car cl--loop-args) 'then )
1321
- (cl--pop2 cl--loop-args) start)))
1309
+ (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--" )))))
1322
1313
(push (list var nil ) loop-for-bindings)
1323
1314
(if (or ands (eq (car cl--loop-args) 'and ))
1324
1315
(progn
1325
- (push `(, var
1326
- (if ,(or cl--loop-first-flag
1327
- (setq cl--loop-first-flag
1328
- (make-symbol " --cl-var--" )))
1329
- , start , var ))
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))))
1316
+ (push `(, var (if , first-assign , start , var )) loop-for-sets)
1317
+ (push `(, var (if ,(car (cl--loop-build-ands
1318
+ (nreverse cl--loop-conditions)))
1319
+ , then , var ))
1320
+ loop-for-steps))
1321
+ (push `(, var (if , first-assign , start , then )) loop-for-sets))))
1339
1322
1340
1323
((memq word '(across across-ref))
1341
1324
(let ((temp-vec (make-symbol " --cl-vec--" ))
@@ -1344,9 +1327,8 @@ For more details, see Info node `(cl)Loop Facility'.
1344
1327
(push (list temp-vec (pop cl--loop-args)) loop-for-bindings)
1345
1328
(push (list temp-len `(length , temp-vec )) loop-for-bindings)
1346
1329
(push (list temp-idx -1 ) loop-for-bindings)
1347
- (push `(< (setq , temp-idx (1+ , temp-idx ))
1348
- , temp-len )
1349
- cl--loop-body)
1330
+ (cl--push-clause-loop-body
1331
+ `(< (setq , temp-idx (1+ , temp-idx )) , temp-len ))
1350
1332
(if (eq word 'across-ref )
1351
1333
(push (list var `(aref , temp-vec , temp-idx ))
1352
1334
cl--loop-symbol-macs)
@@ -1376,15 +1358,14 @@ For more details, see Info node `(cl)Loop Facility'.
1376
1358
loop-for-bindings)
1377
1359
(push (list var `(elt , temp-seq , temp-idx ))
1378
1360
cl--loop-symbol-macs)
1379
- (push `(< , temp-idx , temp-len ) cl--loop-body ))
1361
+ (cl-- push-clause-loop-body `(< , temp-idx , temp-len )))
1380
1362
; ; Evaluate seq length just if needed, that is, when seq is not a cons.
1381
1363
(push (list temp-len (or (consp seq) `(length , temp-seq )))
1382
1364
loop-for-bindings)
1383
1365
(push (list var nil ) loop-for-bindings)
1384
- (push `(and , temp-seq
1385
- (or (consp , temp-seq )
1386
- (< , temp-idx , temp-len )))
1387
- cl--loop-body)
1366
+ (cl--push-clause-loop-body `(and , temp-seq
1367
+ (or (consp , temp-seq )
1368
+ (< , temp-idx , temp-len ))))
1388
1369
(push (list var `(if (consp , temp-seq )
1389
1370
(pop , temp-seq )
1390
1371
(aref , temp-seq , temp-idx )))
@@ -1480,9 +1461,8 @@ For more details, see Info node `(cl)Loop Facility'.
1480
1461
(push (list var '(selected-frame ))
1481
1462
loop-for-bindings)
1482
1463
(push (list temp nil ) loop-for-bindings)
1483
- (push `(prog1 (not (eq , var , temp ))
1484
- (or , temp (setq , temp , var )))
1485
- cl--loop-body)
1464
+ (cl--push-clause-loop-body `(prog1 (not (eq , var , temp ))
1465
+ (or , temp (setq , temp , var ))))
1486
1466
(push (list var `(next-frame , var ))
1487
1467
loop-for-steps)))
1488
1468
@@ -1503,9 +1483,8 @@ For more details, see Info node `(cl)Loop Facility'.
1503
1483
(push (list minip `(minibufferp (window-buffer , var )))
1504
1484
loop-for-bindings)
1505
1485
(push (list temp nil ) loop-for-bindings)
1506
- (push `(prog1 (not (eq , var , temp ))
1507
- (or , temp (setq , temp , var )))
1508
- cl--loop-body)
1486
+ (cl--push-clause-loop-body `(prog1 (not (eq , var , temp ))
1487
+ (or , temp (setq , temp , var ))))
1509
1488
(push (list var `(next-window , var , minip ))
1510
1489
loop-for-steps)))
1511
1490
@@ -1529,7 +1508,6 @@ For more details, see Info node `(cl)Loop Facility'.
1529
1508
t )
1530
1509
cl--loop-body))
1531
1510
(when loop-for-steps
1532
- (setq cl--loop-guard-cond t )
1533
1511
(push (cons (if ands 'cl-psetq 'setq )
1534
1512
(apply 'append (nreverse loop-for-steps)))
1535
1513
cl--loop-steps))))
0 commit comments