Skip to content

Commit 16cc951

Browse files
committed
keep loop sync
1 parent 04cebcf commit 16cc951

File tree

1 file changed

+18
-15
lines changed

1 file changed

+18
-15
lines changed

src/sci/impl/async_macro.cljc

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
(defn transform-loop*
139139
"Transform loop* with await into a recursive promise-returning function.
140140
Wraps init values in let* to preserve sequential scoping (each init sees previous bindings).
141+
Returns original loop unchanged if there are no promises.
141142
142143
(loop* [x 0] (if (< x 3) (do (await p) (recur (inc x))) x))
143144
=>
@@ -148,24 +149,26 @@
148149
pairs (partition 2 bindings)
149150
param-names (mapv first pairs)
150151
init-values (mapv second pairs)
151-
;; Add params to locals for body transformation
152152
body-locals (into locals param-names)
153-
;; Replace recur with loop function call
153+
;; Replace recur with loop function call and transform body
154154
body-with-replaced-recur (map #(replace-recur % loop-fn-name) body)
155-
;; Transform the body using transform-do to properly chain promises
156155
transformed-body (transform-do ctx body-locals body-with-replaced-recur)
157-
;; Ensure promise result
158-
promised-body (if (promise-form? transformed-body)
159-
transformed-body
160-
(wrap-promise transformed-body))
161-
;; Build the loop function
162-
loop-fn (list 'fn* loop-fn-name param-names promised-body)
163-
;; Build the loop call - uses param names since they'll be bound by let*
164-
loop-call (wrap-promise (apply list loop-fn param-names))
165-
;; Build let* bindings: [param1 init1 param2 init2 ...]
166-
let-bindings (vec (interleave param-names init-values))]
167-
;; Wrap in let* and transform - this handles sequential scoping and promise chaining
168-
(transform-let* ctx locals let-bindings (list loop-call))))
156+
;; Transform inits via let* to check for promises (also handles sequential scoping)
157+
let-bindings (vec (interleave param-names init-values))
158+
transformed-let-check (transform-let* ctx locals let-bindings (list transformed-body))
159+
;; Check if body or inits have any promises
160+
has-promise? (or (promise-form? transformed-body)
161+
(promise-form? transformed-let-check))]
162+
(if has-promise?
163+
;; Has promises - build async loop
164+
(let [promised-body (if (promise-form? transformed-body)
165+
transformed-body
166+
(wrap-promise transformed-body))
167+
loop-fn (list 'fn* loop-fn-name param-names promised-body)
168+
loop-call (wrap-promise (apply list loop-fn param-names))]
169+
(transform-let* ctx locals let-bindings (list loop-call)))
170+
;; No promises - return original loop unchanged
171+
(list* 'loop* bindings body))))
169172

170173
(defn transform-try
171174
"Transform try/catch/finally with await into Promise .catch/.finally chains.

0 commit comments

Comments
 (0)