@@ -190,52 +190,75 @@ handled by `loopy-iter'."
190
190
; ; being known at compile time (but still only being evaluated once.)
191
191
; ; (#194)
192
192
(cl-defun loopy--parse-set-prev-command
193
- ((_ var val &key back))
193
+ ((_ var val &key ( back 1 ) ))
194
194
" Parse the `set-prev' command as (set-prev VAR VAL &key back).
195
195
196
196
VAR is set to a version of VAL in a past loop cycle. With BACK,
197
197
wait that many cycle before beginning to update VAR.
198
198
199
+ This command records the value of VAL at the end of the cycle,
200
+ not when the command is run.
201
+
199
202
This command does not wait for VAL to change before updating VAR."
200
- (let* ((holding-vars (cl-loop for i from 1 to (or back 1 )
201
- collect (gensym " set-prev-hold" )))
202
- (using-destructuring (seqp var))
203
- (with-bound (if using-destructuring
204
- (cl-some #'loopy--with-bound-p
205
- (cl-second (loopy--destructure-for-iteration var val)))
206
- (loopy--with-bound-p var)))
207
- ; ; We don't use `cl-shiftf' in the main body because we want the
208
- ; ; holding variables to update regardless of whether we update
209
- ; ; VAR.
210
- (holding-vars-setq `(loopy--latter-body
211
- (cl-shiftf ,@holding-vars , val ))))
212
- (if with-bound
213
- (if using-destructuring
214
- (let ((cnt-holder (gensym " count" ))
215
- (back-holder (gensym " back" )))
216
- `((loopy--other-vars (, cnt-holder 0 ))
217
- (loopy--latter-body (setq , cnt-holder (1+ , cnt-holder )))
218
- (loopy--other-vars (, back-holder , back ))
219
- ,@(mapcar (lambda (x ) `(loopy--other-vars (, x nil )))
220
- holding-vars)
221
- ,@(loopy--bind-main-body (main-exprs rest-instr)
222
- (loopy--destructure-for-other-command
223
- var (car holding-vars))
224
- `((loopy--main-body (when (>= , cnt-holder , back-holder )
225
- ,@main-exprs ))
226
- ,@rest-instr ))
227
- , holding-vars-setq ))
228
- (let ((val-holder (gensym " set-prev-val" )))
229
- `((loopy--other-vars (, val-holder , var ))
230
- ,@(mapcar (lambda (x ) `(loopy--other-vars (, x , val-holder )))
231
- holding-vars)
232
- (loopy--main-body (setq , var ,(car holding-vars)))
233
- , holding-vars-setq )))
234
- `(,@(mapcar (lambda (x ) `(loopy--other-vars (, x nil )))
235
- holding-vars)
236
- ,@(loopy--destructure-for-other-command
237
- var (car holding-vars))
238
- , holding-vars-setq ))))
203
+ (if (not (numberp back))
204
+ ; ; When we don't know ahead of time how far back we need to go, we have to
205
+ ; ; use a queue. This code is adapted from Irreal's blog
206
+ ; ; (https://irreal.org/blog/?p=40) where they give an example of a simple
207
+ ; ; FIFO queue in Scheme. It uses two lists. The "front" lists contains
208
+ ; ; values for popping off. The "back" list contains values for pushing
209
+ ; ; on. When the "front" list is exhausted, values are moved from the
210
+ ; ; "back" list in reverse.
211
+ (loopy--instr-let-const* ((prev back))
212
+ loopy--other-vars
213
+ (loopy--instr-let-var* ((cnt 0 )
214
+ (queue-front nil )
215
+ (queue-end nil ))
216
+ loopy--other-vars
217
+ ; ; We generate a main-body expression for binding the variables to the
218
+ ; ; desired values and for setting them to nil. There is overlap in the
219
+ ; ; remaining expressions, which initialize the variables.
220
+ (loopy--bind-main-body (main-exprs init-instr)
221
+ (loopy--destructure-for-other-command
222
+ var `(or (pop , queue-front )
223
+ (progn
224
+ (setq , queue-front (reverse , queue-end )
225
+ , queue-end nil )
226
+ (pop , queue-front ))))
227
+ `((loopy--main-body (when (>= , cnt , prev )
228
+ ,(macroexp-progn main-exprs)))
229
+ ,@init-instr
230
+ (loopy--latter-body (push , val , queue-end ))
231
+ (loopy--latter-body (setq , cnt (1+ , cnt )))))))
232
+
233
+ ; ; When we know ahead of time how far we need to go back, we can use a chain
234
+ ; ; of `setq' s for storing values instead of queue. However, except when
235
+ ; ; BACK is 1, we still need to use a count, in case one of the variables is
236
+ ; ; initialized in `with' .
237
+
238
+ (if (= back 1 )
239
+ (loopy--instr-let-var* ((hold-var nil )
240
+ (run nil ))
241
+ loopy--other-vars
242
+ `(,@(loopy--bind-main-body (main-exprs init-instrs)
243
+ (loopy--destructure-for-other-command var hold-var)
244
+ `((loopy--main-body (when , run
245
+ ,@main-exprs ))
246
+ ,@init-instrs ))
247
+ (loopy--latter-body (setq , hold-var , val ))
248
+ (loopy--latter-body (setq , run t ))))
249
+ (let ((hold-vars (cl-loop for i from 1 to back
250
+ collect (gensym " hold-var" ))))
251
+ (loopy--instr-let-var* ((cnt 0 ))
252
+ loopy--other-vars
253
+ `(,@(mapcar (lambda (x ) `(loopy--other-vars (, x nil )))
254
+ hold-vars)
255
+ ,@(loopy--bind-main-body (main-exprs init-instrs)
256
+ (loopy--destructure-for-other-command var (car hold-vars))
257
+ `((loopy--main-body (when (>= , cnt , back )
258
+ ,@main-exprs ))
259
+ ,@init-instrs ))
260
+ (loopy--latter-body (cl-shiftf ,@hold-vars , val ))
261
+ (loopy--latter-body (setq , cnt (1+ , cnt )))))))))
239
262
240
263
; ;;;;; Group
241
264
(cl-defun loopy--parse-group-command ((_ &rest body))
0 commit comments