|
138 | 138 | (defn transform-loop* |
139 | 139 | "Transform loop* with await into a recursive promise-returning function. |
140 | 140 | Wraps init values in let* to preserve sequential scoping (each init sees previous bindings). |
| 141 | + Returns original loop unchanged if there are no promises. |
141 | 142 |
|
142 | 143 | (loop* [x 0] (if (< x 3) (do (await p) (recur (inc x))) x)) |
143 | 144 | => |
|
148 | 149 | pairs (partition 2 bindings) |
149 | 150 | param-names (mapv first pairs) |
150 | 151 | init-values (mapv second pairs) |
151 | | - ;; Add params to locals for body transformation |
152 | 152 | body-locals (into locals param-names) |
153 | | - ;; Replace recur with loop function call |
| 153 | + ;; Replace recur with loop function call and transform body |
154 | 154 | body-with-replaced-recur (map #(replace-recur % loop-fn-name) body) |
155 | | - ;; Transform the body using transform-do to properly chain promises |
156 | 155 | 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)))) |
169 | 172 |
|
170 | 173 | (defn transform-try |
171 | 174 | "Transform try/catch/finally with await into Promise .catch/.finally chains. |
|
0 commit comments