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
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:
@@ -231,6 +231,41 @@ real result.
|
||||
|
||||
_Newest first. Append one dated entry per milestone landed._
|
||||
|
||||
- 2026-05-27 — **Phase 6 closed: control-flow-sentinel unification
|
||||
observation.** After wiring panic propagation through 4 sites
|
||||
(go-eval-block, go-eval-for, go-eval-stmt's catch-all, go-eval-
|
||||
program-loop), a clear pattern emerged: every control-flow boundary
|
||||
needs the same dispatch arm — check for `:return-value`, `:break`,
|
||||
`:continue`, `:eval-error`, `(:go-panic ...)` — in the same order.
|
||||
Adding a new sentinel (say `:goroutine-killed` from a real
|
||||
preemption model) means hunting for every site and adding another
|
||||
arm. This is precisely the kind of cross-cutting concern a
|
||||
scheduler kit should abstract.
|
||||
|
||||
**Concrete kit hint:** define ONE `propagates?` predicate +
|
||||
helper:
|
||||
|
||||
```
|
||||
(define (control-sentinel? r)
|
||||
(or (terminal-return? r)
|
||||
(break? r) (continue? r)
|
||||
(raised-error? r) (raised-panic? r)
|
||||
(goroutine-killed? r)))
|
||||
```
|
||||
|
||||
Every control-flow site calls this once. New sentinel = one place
|
||||
to add an arm; not 7. The kit's `frame-driver` should expose this
|
||||
primitive so guest evaluators (Go, Erlang, future targets) all
|
||||
share the dispatch logic and only differ on which sentinels they
|
||||
emit.
|
||||
|
||||
This is the second cross-cutting abstraction (after panic cell +
|
||||
defer queue) the Go consumer has chiselled out. The pattern is:
|
||||
scheduler kit primitives = "things every guest evaluator's control-
|
||||
flow boundary needs once" — not "things only the scheduler runtime
|
||||
needs." The scheduler runtime is the *driver*; the boundary
|
||||
primitives are kit-grade shared infrastructure.
|
||||
|
||||
- 2026-05-27 — **Phase 6: panic/recover shape lands.** The panic
|
||||
cell is the missing piece. It's a per-frame mutable record of
|
||||
shape `(STATE VALUE)` carrying one of `:none` / `:raised` /
|
||||
|
||||
Reference in New Issue
Block a user