HS: fix guard re-raise in repeat loops (+3 tests)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 8m51s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 8m51s
Capture raised exception in a let-bound variable before the guard exits, then re-raise after. Avoids the WASM OCaml kernel bug where (raise e) called from within a guard handler re-invokes the same handler infinitely. Affects hs-repeat-forever, hs-repeat-times, hs-repeat-while, hs-repeat-until, hs-for-each. Repeat suite: 25/30 → 28/29 counted (1 skipped: 'until event keyword works' requires async event dispatch). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -821,11 +821,16 @@
|
||||
(when
|
||||
(< i n)
|
||||
(let
|
||||
((signal (guard (e ((or (= (str e) "hs-break") (= (str e) "hs-continue")) (str e)) (true (raise e))) (do (thunk) nil))))
|
||||
(cond
|
||||
((= signal "hs-break") nil)
|
||||
((= signal "hs-continue") (do-repeat (+ i 1)))
|
||||
(true (do-repeat (+ i 1))))))))
|
||||
((ex nil) (raised false))
|
||||
(do
|
||||
(guard
|
||||
(e (true (do (set! ex e) (set! raised true) nil)))
|
||||
(do (thunk) nil))
|
||||
(cond
|
||||
((not raised) (do-repeat (+ i 1)))
|
||||
((= (str ex) "hs-break") nil)
|
||||
((= (str ex) "hs-continue") (do-repeat (+ i 1)))
|
||||
(true (raise ex))))))))
|
||||
(do-repeat 0)))
|
||||
|
||||
(define
|
||||
@@ -837,11 +842,16 @@
|
||||
(fn
|
||||
()
|
||||
(let
|
||||
((signal (guard (e ((or (= (str e) "hs-break") (= (str e) "hs-continue")) (str e)) (true (raise e))) (do (thunk) nil))))
|
||||
(cond
|
||||
((= signal "hs-break") nil)
|
||||
((= signal "hs-continue") (do-forever))
|
||||
(true (do-forever))))))
|
||||
((ex nil) (raised false))
|
||||
(do
|
||||
(guard
|
||||
(e (true (do (set! ex e) (set! raised true) nil)))
|
||||
(do (thunk) nil))
|
||||
(cond
|
||||
((not raised) (do-forever))
|
||||
((= (str ex) "hs-break") nil)
|
||||
((= (str ex) "hs-continue") (do-forever))
|
||||
(true (raise ex)))))))
|
||||
(do-forever)))
|
||||
|
||||
(define
|
||||
@@ -851,23 +861,33 @@
|
||||
(when
|
||||
(cond-fn)
|
||||
(let
|
||||
((signal (guard (e ((or (= (str e) "hs-break") (= (str e) "hs-continue")) (str e)) (true (raise e))) (do (thunk) nil))))
|
||||
(cond
|
||||
((= signal "hs-break") nil)
|
||||
((= signal "hs-continue") (hs-repeat-while cond-fn thunk))
|
||||
(true (hs-repeat-while cond-fn thunk)))))))
|
||||
((ex nil) (raised false))
|
||||
(do
|
||||
(guard
|
||||
(e (true (do (set! ex e) (set! raised true) nil)))
|
||||
(do (thunk) nil))
|
||||
(cond
|
||||
((not raised) (hs-repeat-while cond-fn thunk))
|
||||
((= (str ex) "hs-break") nil)
|
||||
((= (str ex) "hs-continue") (hs-repeat-while cond-fn thunk))
|
||||
(true (raise ex))))))))
|
||||
|
||||
(define
|
||||
hs-repeat-until
|
||||
(fn
|
||||
(cond-fn thunk)
|
||||
(let
|
||||
((signal (guard (e ((or (= (str e) "hs-break") (= (str e) "hs-continue")) (str e)) (true (raise e))) (do (thunk) nil))))
|
||||
(cond
|
||||
((= signal "hs-break") nil)
|
||||
((= signal "hs-continue")
|
||||
(if (cond-fn) nil (hs-repeat-until cond-fn thunk)))
|
||||
(true (if (cond-fn) nil (hs-repeat-until cond-fn thunk)))))))
|
||||
((ex nil) (raised false))
|
||||
(do
|
||||
(guard
|
||||
(e (true (do (set! ex e) (set! raised true) nil)))
|
||||
(do (thunk) nil))
|
||||
(cond
|
||||
((not raised) (if (cond-fn) nil (hs-repeat-until cond-fn thunk)))
|
||||
((= (str ex) "hs-break") nil)
|
||||
((= (str ex) "hs-continue")
|
||||
(if (cond-fn) nil (hs-repeat-until cond-fn thunk)))
|
||||
(true (raise ex)))))))
|
||||
|
||||
(define
|
||||
hs-for-each
|
||||
@@ -882,11 +902,16 @@
|
||||
(when
|
||||
(not (empty? remaining))
|
||||
(let
|
||||
((signal (guard (e ((or (= (str e) "hs-break") (= (str e) "hs-continue")) (str e)) (true (raise e))) (do (fn-body (first remaining)) nil))))
|
||||
(cond
|
||||
((= signal "hs-break") nil)
|
||||
((= signal "hs-continue") (do-loop (rest remaining)))
|
||||
(true (do-loop (rest remaining))))))))
|
||||
((ex nil) (raised false))
|
||||
(do
|
||||
(guard
|
||||
(e (true (do (set! ex e) (set! raised true) nil)))
|
||||
(do (fn-body (first remaining)) nil))
|
||||
(cond
|
||||
((not raised) (do-loop (rest remaining)))
|
||||
((= (str ex) "hs-break") nil)
|
||||
((= (str ex) "hs-continue") (do-loop (rest remaining)))
|
||||
(true (raise ex))))))))
|
||||
(do-loop items))))
|
||||
|
||||
(begin
|
||||
|
||||
Reference in New Issue
Block a user