go: eval.sx — range-over-{slice,map,chan} + 7 tests; break-env fix [nothing]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 30s

Phase 5 cont. New go-eval-range-for handles the parser's :range-for
AST shape. Dispatches on the collection's runtime type:

  :go-slice  → bind index + element, iterate by position
  :go-map    → bind key + value, walk entries assoc list
  :go-chan   → bind value, drain until buffer empty (v0 limitation)

Each loop carries:
  - go-range-extend: handles 0/1/2-name binding patterns uniformly
  - go-range-body:   evaluates body whether it's a :block or other shape
  - per-collection loop helper: threads env, catches :break/:continue/
    :return-value/:eval-error sentinels

**Subtle break fix:** loops were previously returning the *pre-loop*
env when break fired, clobbering all assignments made in prior
iterations. Now returns the current iteration's input env (which
carries forward successful iterations' state). Patched for the three
range variants and for the regular for-loop where the same pattern
applied. The shape:

  (= r :break) env    ;; was: (= r :break) original-env

Tests:
  range: slice — sum of 1..5 = 15
  range: slice — key only (index)
  range: map — sum values
  range: channel — collect all buffered
  range: slice with break exits early
  range: slice with continue skips an element
  range: empty slice — body never runs
  range: chan + goroutine producer

runtime 26/26, total 483/483.

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

View File

@@ -320,7 +320,11 @@ Progress-log line → push `origin/loops/go`.
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.
- [x] `range` over slices / maps / channels. New `go-eval-range-for`
dispatches on collection type: slice (index+elem), map (key+val),
channel (just value). v0 chan-range stops when buffer empties
(no preemption to wait for new sends). break exits with the
pre-break env (preserving prior-iteration assignments).
- [ ] `time.After`-like timer channel.
- **Independent implementation.** Do NOT use lib/guest/scheduler/ — that
kit doesn't exist yet and depends on this work for its design. See
@@ -603,6 +607,20 @@ 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.: range-over-{slice,map,channel}. New
`go-eval-range-for` dispatches on the collection type:
slice → bind index + element, iterate by position
map → bind key + value, iterate over entries assoc list
chan → bind value, drain until empty (v0: no preemption to wait
for new sends; real Go blocks until close + empty)
break/continue propagate via the existing sentinel scheme.
Subtle fix in break-from-loop: was returning the pre-loop env
(clobbering prior-iteration assignments); now returns the current
iteration's input env so successful iterations stick. Patched for
range-slice, range-map, range-chan in one go. +7 tests, runtime
26/26, total 483/483. `[nothing]` — collection-iteration semantics
are Go-specific; the cross-language scheduler insights are already
in the sister-plan diary.
- 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