From 1b844f6a1966e9aa29d7d0b34d001f092dc0c7e3 Mon Sep 17 00:00:00 2001 From: giles Date: Thu, 7 May 2026 04:14:48 +0000 Subject: [PATCH] =?UTF-8?q?haskell:=20Phase=209=20=E2=80=94=20hk-run-io=20?= =?UTF-8?q?catches=20errors=20and=20appends=20to=20io-lines?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- lib/haskell/eval.sx | 13 +++++++++++-- lib/haskell/tests/io-input.sx | 11 +++++------ plans/haskell-completeness.md | 15 ++++++++++++++- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/lib/haskell/eval.sx b/lib/haskell/eval.sx index a7fa0eff..b3400855 100644 --- a/lib/haskell/eval.sx +++ b/lib/haskell/eval.sx @@ -1163,7 +1163,14 @@ (define hk-run-io - (fn (src) (do (set! hk-io-lines (list)) (hk-run src) hk-io-lines))) + (fn + (src) + (do + (set! hk-io-lines (list)) + (guard + (e (true (append! hk-io-lines (if (string? e) e (str e))))) + (hk-deep-force (hk-run src))) + hk-io-lines))) (define hk-stdin-lines (list)) @@ -1176,7 +1183,9 @@ (begin (set! hk-io-lines (list)) (set! hk-stdin-lines stdin-lines) - (hk-run src) + (guard + (e (true (append! hk-io-lines (if (string? e) e (str e))))) + (hk-deep-force (hk-run src))) hk-io-lines))) (define hk-env0 (hk-init-env)) diff --git a/lib/haskell/tests/io-input.sx b/lib/haskell/tests/io-input.sx index 71bf4620..937781e1 100644 --- a/lib/haskell/tests/io-input.sx +++ b/lib/haskell/tests/io-input.sx @@ -64,12 +64,11 @@ (hk-test "readFile error on missing file" - (guard - (e (true (>= (index-of e "file not found") 0))) - (begin - (set! hk-vfs (dict)) - (hk-run-io "main = readFile \"no.txt\" >>= putStrLn") - false)) + (begin + (set! hk-vfs (dict)) + (let + ((lines (hk-run-io "main = readFile \"no.txt\" >>= putStrLn"))) + (>= (index-of (str lines) "file not found") 0))) true) (hk-test diff --git a/plans/haskell-completeness.md b/plans/haskell-completeness.md index 789fb9d7..ae5be084 100644 --- a/plans/haskell-completeness.md +++ b/plans/haskell-completeness.md @@ -131,7 +131,7 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. - [x] Partial functions emit proper error messages: `head []` → `"Prelude.head: empty list"`, `tail []` → `"Prelude.tail: empty list"`, `fromJust Nothing` → `"Maybe.fromJust: Nothing"`. -- [ ] Top-level `hk-run-io` catches `hk-error` tag and returns it as a tagged +- [x] Top-level `hk-run-io` catches `hk-error` tag and returns it as a tagged error result so test suites can inspect it without crashing. - [ ] `hk-test-error` helper in `testlib.sx`: `(hk-test-error "desc" thunk expected-substring)` — asserts the thunk raises @@ -293,6 +293,19 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. _Newest first._ +**2026-05-07** — Phase 9 `hk-run-io` catches errors, appends to io-lines: +- Wrapped both `hk-run-io` and `hk-run-io-with-input` in `(guard (e (true …)))` + that appends the caught exception to `hk-io-lines`. Also added `hk-deep-force` + inside the guard so `main`'s thunk actually evaluates (post-lazy-CAFs change + it was a thunk, was previously not forced — IO actions never fired in + programs that returned the thunk to `hk-run-io`). Test suites now see error + output as the last line of `hk-io-lines` instead of crashing. +- Updated one io-input test that used an outer `guard` to look for + `"file not found"` in the io-lines string instead. +- Verified across program-io (10/10), io-input (11/11), program-fizzbuzz + (12/12), program-calculator (5/5), program-roman (14/14), program-wordcount + (10/10), program-showadt (5/5), program-showio (5/5), eval.sx (64/64). + **2026-05-07** — Phase 9 partial functions emit proper error messages: - Added empty-list catch clauses to `head`, `tail` in the prelude. Added `fromJust`, `fromMaybe`, `isJust`, `isNothing` (the last three were missing).