go: eval.sx + sched.sx — select stmt evaluation + 6 tests [nothing]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 28s

Phase 5 cont. Adds `select` statement evaluation:

  go-select-try-case env COMM →
    :not-ready / extended-env / :eval-error
  go-select-pick env CASES DEFAULT-OR-NIL →
    body-result / blocked-error
  go-eval-select-stmt env STMT  — public entry

Walks cases in declared order:
  * :send case — always ready in v0 (unbounded buffer). Sends value
    via go-chan-send! and returns env unchanged.
  * :short-decl / :assign case — RHS expected to be unary <- on a
    channel. Ready iff go-chan-len > 0; on success, recv-into-var
    binds the new value in env.
  * Bare recv (:app (:var "<-") [CHAN]) — ready iff len > 0; consumes
    the value (discarded).
  * :default — deferred until end of walk. Runs if no other case
    ready. Absence + no ready case → (:eval-error :select-blocked-
    no-default).

New `go-chan-len` accessor on the channel closure-bundle so the
select can peek without consuming.

Subtle bug fix: the :select stmt branch in go-eval-stmt was returning
the old env instead of the env returned by the case body. Assignments
inside select cases (`select { case <-ch: x = 1 ; default: x = 99 }`)
now stick.

Tests (6):
  default fires when no case ready
  recv case fires when ready
  recv-into-var binds the value
  send case always ready
  picks first ready case (deterministic order in v0)
  no default + nothing ready → blocked error
  combined with goroutine fan-in

runtime 18/18, total 475/475.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 22:03:17 +00:00
parent b693854dc4
commit 4807bc9c58
6 changed files with 183 additions and 7 deletions

View File

@@ -313,7 +313,13 @@ Progress-log line → push `origin/loops/go`.
sched.sx header).
- [ ] Real preemption (suspending sends on full buffer / recvs on empty).
Requires reified execution state; deferred to Phase 5b.
- [ ] `select { case ... }` multiplexing.
- [x] `select { case ... }` multiplexing. v0 tries cases in declared
order, picks first ready (sends always ready; recv ready iff
channel has buffered values). Default runs if nothing else
ready; no default and nothing ready → typed error.
Recv-into-var (`case v := <-ch`) binds; recv-into-assign
(`case v = <-ch`) re-binds. Real-Go random selection among
ready cases deferred (v0 deterministic).
- [ ] `range` over channels.
- [ ] `time.After`-like timer channel.
- **Independent implementation.** Do NOT use lib/guest/scheduler/ — that
@@ -597,6 +603,18 @@ Minimal repro: see `lib/go/lex.sx#gl-oct-digit?` and `#gl-match-op`.
_Newest first. Append one dated entry per commit._
- 2026-05-27 — Phase 5 cont.: `select` statement evaluation. New
`go-eval-select-stmt` + `go-select-pick` + `go-select-try-case`.
Walks cases in declared order: send always ready in v0; recv ready
iff `(go-chan-len ch) > 0` (new accessor added to sched.sx);
recv-into-decl/assign binds the value into env. Default deferred
until end of walk; if nothing ready and no default, returns
`(:eval-error :select-blocked-no-default)`. Subtle bug fixed where
`:select` stmt was returning the old env instead of the
case-body-extended env — assignments inside cases now stick. +6
tests, runtime 18/18, total 475/475. `[nothing]` — `:select-case`
uniform shape was already chiselled into the sister-plan diary when
the parser landed.
- 2026-05-27 — **Phase 5 first slice.** `lib/go/sched.sx` lands with
the v0 channel primitive: `go-make-chan` returns a closures-over-
mutable-buf channel. Send appends, recv pops first, close flips a