go: panic + recover → eval 92/92, total 509/509, Phase 6 closed [shapes-scheduler]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 36s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 36s
Panic/recover builtins + per-frame __go-panic-cell of shape (STATE V). Body panic flips cell :none→:raised BEFORE defers drain so recover() can find it. recover() walks env chain past shadowing cells to the outermost :raised one — flips it :recovered, returns V. Frame exit checks cell: :recovered → return clean; :raised → propagate (:go-panic V). 6 tests: uncaught-from-program, panic-from-fn, defer-recover-swallow, recover-captures-via-channel, propagation-through-no-defer-chain, middle-frame-catches-deeper-panic. Shape: panic cell is a frame-attached out-of-band channel that survives function boundaries via env-chain walk. Same primitive slots into the scheduler kit's termination-record + cleanup-with- error-context hook. Maps cleanly to Erlang try/catch/after. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -516,6 +516,48 @@
|
||||
(go-env-lookup env "e")))
|
||||
(list 3 2 1 0))
|
||||
|
||||
(go-eval-test
|
||||
"panic: uncaught panic surfaces as (:go-panic V) from program"
|
||||
(let
|
||||
((r (go-eval-program go-env-builtins (list (go-parse "panic(\"boom\")")))))
|
||||
r)
|
||||
(list :go-panic "boom"))
|
||||
|
||||
(go-eval-test
|
||||
"panic inside fn: surfaces from fn call too"
|
||||
(let
|
||||
((r (go-eval-program go-env-builtins (list (go-parse "func boom() { panic(\"oops\") }") (go-parse "boom()")))))
|
||||
r)
|
||||
(list :go-panic "oops"))
|
||||
|
||||
(go-eval-test
|
||||
"recover: deferred recover swallows panic, fn returns normally"
|
||||
(let
|
||||
((env (go-eval-program go-env-builtins (list (go-parse "func safe() { defer recover() ; panic(\"x\") }") (go-parse "safe()") (go-parse "after := 42")))))
|
||||
(go-env-lookup env "after"))
|
||||
42)
|
||||
|
||||
(go-eval-test
|
||||
"recover: deferred recover captures the panic value"
|
||||
(let
|
||||
((env (go-eval-program go-env-builtins (list (go-parse "ch := make()") (go-parse "func grab(c chan int) { r := recover() ; c <- r }") (go-parse "func safe(c chan int) { defer grab(c) ; panic(99) }") (go-parse "safe(ch)") (go-parse "got := <-ch")))))
|
||||
(go-env-lookup env "got"))
|
||||
99)
|
||||
|
||||
(go-eval-test
|
||||
"panic: propagates through intermediate frames without defers"
|
||||
(let
|
||||
((r (go-eval-program go-env-builtins (list (go-parse "func inner() { panic(\"deep\") }") (go-parse "func middle() { inner() }") (go-parse "func outer() { middle() }") (go-parse "outer()")))))
|
||||
r)
|
||||
(list :go-panic "deep"))
|
||||
|
||||
(go-eval-test
|
||||
"recover: middle-frame defer catches panic from deeper frame"
|
||||
(let
|
||||
((env (go-eval-program go-env-builtins (list (go-parse "func inner() { panic(\"deep\") }") (go-parse "func middle() { inner() }") (go-parse "func outer() { defer recover() ; middle() }") (go-parse "outer()") (go-parse "after := 7")))))
|
||||
(go-env-lookup env "after"))
|
||||
7)
|
||||
|
||||
(define
|
||||
go-eval-test-summary
|
||||
(str "eval " go-eval-test-pass "/" go-eval-test-count))
|
||||
|
||||
Reference in New Issue
Block a user