go: goroutine-panic propagation + 8 corner tests → eval 100/100, Phase 6 acceptance cleared [shapes-scheduler]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 20s

Wired panic through :go stmt (v0 sync surfaces back to spawner —
matches real Go's "crash whole program" end-effect) and through
go-eval-for (was swallowing panic at the loop boundary).

8 tests added: goroutine-panic-surfaces, goroutine-recover-via-
spawner-defer, multi-defer-LIFO-with-recover, defer-fires-on-panic-
path, panic(nil), panic-in-loop, defer-still-runs-in-panicking-fn,
args-eager-on-panic-path. 20 Phase-6 tests total; +20 acceptance
bar cleared (eval/ 80 → 100).

Shape: 4 control-flow sites now repeat the same sentinel dispatch
arm (return-value, break, continue, eval-error, go-panic). The
scheduler kit should bake in a single propagates? helper rather
than have each guest evaluator list every sentinel inline — diary
documents the cross-cutting abstraction.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 23:54:56 +00:00
parent f52ad1fac6
commit c50f5d5155
6 changed files with 137 additions and 13 deletions

View File

@@ -914,6 +914,8 @@
:else (go-for-loop env1 cnd post body)))
(go-eval-error? r)
r
(go-panic? r)
r
:else (let
((env1 (cond (= post nil) r :else (go-eval-stmt r post))))
(cond
@@ -972,9 +974,16 @@
(and (list? stmt) (= (first stmt) :defer))
(go-eval-defer-stmt env stmt)
(and (list? stmt) (= (first stmt) :go))
;; v0: synchronous spawn. A panic from the spawned expression
;; that the goroutine didn't recover propagates here — real
;; Go would crash the whole program; the sync model surfaces
;; it back to the spawner which has the same end-effect.
(let
((v (go-eval env (nth stmt 1))))
(cond (go-eval-error? v) v :else env))
(cond
(go-eval-error? v) v
(go-panic? v) v
:else env))
(and (list? stmt) (= (first stmt) :select))
(let
((r (go-eval-select-stmt env stmt)))