Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 44s
hk-bind-exceptions! in eval.sx registers throwIO, throw, evaluate, catch, try, handle, displayException. SomeException constructor pre-registered in runtime.sx (arity 1, type SomeException). throwIO and the existing error primitive both raise via SX `raise` with a uniform "hk-error: msg" string. catch/try/handle parse it back into a SomeException via hk-exception-of, which strips nested 'Unhandled exception: "..."' host wraps (CEK's host_error formatter) and the "hk-error: " prefix. catch and handle evaluate the handler outside the guard scope (build an "ok"/"exn" outcome tag inside guard, then dispatch outside) so that a re-throw from the handler propagates past this catch — matching Haskell semantics rather than infinite-looping in the same guard. 14 unit tests in tests/exceptions.sx (catch success, catch error, try Right/Left, handle, throwIO + catch/try, evaluate, nested catch, do-bind through catch, branch on try result, IORef-mutating handler). Conformance: safediv.hs (8/8) and trycatch.hs (8/8). Scoreboard now 285/285 tests, 36/36 programs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
81 lines
2.1 KiB
Plaintext
81 lines
2.1 KiB
Plaintext
;; safediv.hs — safe division using catch (Phase 16 conformance).
|
|
|
|
(define
|
|
hk-safediv-source
|
|
"safeDiv :: Int -> Int -> IO Int
|
|
safeDiv _ 0 = throwIO (SomeException \"division by zero\")
|
|
safeDiv x y = return (x `div` y)
|
|
|
|
guarded :: Int -> Int -> IO Int
|
|
guarded x y = catch (safeDiv x y) (\\(SomeException _) -> return 0)
|
|
|
|
reason :: Int -> Int -> IO String
|
|
reason x y = catch (safeDiv x y `seq` return \"ok\")
|
|
(\\(SomeException m) -> return m)
|
|
|
|
bothBranches :: Int -> Int -> IO Int
|
|
bothBranches x y = do
|
|
v <- catch (safeDiv x y) (\\(SomeException _) -> return (-1))
|
|
return (v + 100)
|
|
|
|
")
|
|
|
|
(hk-test
|
|
"safediv.hs — divide by non-zero"
|
|
(hk-deep-force
|
|
(hk-run
|
|
(str hk-safediv-source "main = guarded 10 2")))
|
|
(list "IO" 5))
|
|
|
|
(hk-test
|
|
"safediv.hs — divide by zero returns 0"
|
|
(hk-deep-force
|
|
(hk-run
|
|
(str hk-safediv-source "main = guarded 10 0")))
|
|
(list "IO" 0))
|
|
|
|
(hk-test
|
|
"safediv.hs — divide by zero — reason captured"
|
|
(hk-deep-force
|
|
(hk-run
|
|
(str hk-safediv-source "main = catch (safeDiv 1 0) (\\(SomeException m) -> return 0) >> reason 1 0")))
|
|
(list "IO" "division by zero"))
|
|
|
|
(hk-test
|
|
"safediv.hs — bothBranches success path"
|
|
(hk-deep-force
|
|
(hk-run
|
|
(str hk-safediv-source "main = bothBranches 8 2")))
|
|
(list "IO" 104))
|
|
|
|
(hk-test
|
|
"safediv.hs — bothBranches failure path"
|
|
(hk-deep-force
|
|
(hk-run
|
|
(str hk-safediv-source "main = bothBranches 8 0")))
|
|
(list "IO" 99))
|
|
|
|
(hk-test
|
|
"safediv.hs — chained safeDiv with catch"
|
|
(hk-deep-force
|
|
(hk-run
|
|
(str hk-safediv-source
|
|
"main = do { a <- guarded 20 4; b <- guarded 7 0; return (a + b) }")))
|
|
(list "IO" 5))
|
|
|
|
(hk-test
|
|
"safediv.hs — try then bind through Either"
|
|
(hk-deep-force
|
|
(hk-run
|
|
(str hk-safediv-source
|
|
"main = do { r <- try (safeDiv 1 0); case r of { Right v -> return v; Left (SomeException m) -> return 999 } }")))
|
|
(list "IO" 999))
|
|
|
|
(hk-test
|
|
"safediv.hs — handle (flip catch)"
|
|
(hk-deep-force
|
|
(hk-run
|
|
(str hk-safediv-source
|
|
"main = handle (\\(SomeException _) -> return 0) (safeDiv 5 0)")))
|
|
(list "IO" 0))
|