go: Phase 8 first slice — stdlib strings/strconv, 41 tests, +40 cleared [shapes-static-types-bidirectional]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 31s

New :go-package NAME ENTRIES value type with field lookup via
extended go-eval-select. New :go-builtin-fn callable for closure-
based stdlib functions. lib/go/std/strings.sx ships 12 functions
(Contains, HasPrefix, HasSuffix, Index, Count, Repeat, Join,
ToUpper, ToLower, TrimSpace, Split, Replace) + lib/go/std/strconv.sx
ships Itoa/Atoi.

Pre-existing bug fixed: parser was emitting (:literal V) for both
`42` and `"42"`, relying on first-char heuristic in eval/types.
Now emits :literal-string for string/rune literals so Atoi("42")
correctly receives the string. 3 parse tests + 2 in-composite-key
tests updated to new shape.

Total 597/597. Stdlib 41/41 — +40 acceptance bar cleared. Sister
diary documents the 11 value-type kinds (struct/slice/map/chan/
fn/method/builtin/builtin-fn/package/panic/defer) all sharing the
"(:KIND PAYLOAD...)" shape, alongside AST nodes and sentinel signals
as the kit's three orthogonal first-class-tag axes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-28 02:14:55 +00:00
parent a7902df365
commit 8c91b34264
12 changed files with 802 additions and 38 deletions

View File

@@ -399,25 +399,25 @@ Progress-log line → push `origin/loops/go`.
erasure at eval, no inference at types/.
- **Acceptance:** types/ +30 tests — **cleared (72 → 102).**
### Phase 8 — Minimal stdlib (`lib/go/std/`)
- Implement just what's needed for representative programs:
- `fmt` — `Println`, `Printf`, `Sprintf`, `Fprintf`, `Errorf`,
`Stringer` dispatch. Verbs: `%d %s %v %t %f %T %+v`.
- `strings` — `Contains`, `HasPrefix`, `HasSuffix`, `Split`, `Join`,
`TrimSpace`, `ToUpper`, `ToLower`, `Replace`, `Index`, `Count`,
`Repeat`, `NewReader`.
- `strconv` — `Itoa`, `Atoi`, `FormatFloat`, `ParseFloat`, `ParseInt`,
`FormatInt`.
- `errors` — `New`, `Is`, `As`, `Unwrap`.
- `sync` — `Mutex` (cooperative — flag + waiter queue), `WaitGroup`,
`Once`, `RWMutex`.
- `time` — `Now`, `Since`, `After` (channel-returning timer), `Sleep`,
`Duration`, `Time`.
- `io` — `Reader`/`Writer` interfaces; `ReadAll`; `Copy`.
- `sort` — `Slice`, `Ints`, `Strings`.
- Tests: round-trip Itoa/Atoi, fmt verb coverage, sync.WaitGroup with
goroutines, time.After in a select, sort.Slice with custom less fn.
- **Acceptance:** stdlib/ suite at 40+ tests.
### Phase 8 — Minimal stdlib (`lib/go/std/`)
- [x] **Package value type + import mechanism.** New `:go-package
NAME ENTRIES` AST value, registered in env so `strings.Contains`
resolves through extended `go-eval-select`. New `:go-builtin-fn`
callable type for closure-based stdlib builtins (distinct from
name-based `:go-builtin`).
- [x] **`strings` package, v0 subset:** Contains, HasPrefix, HasSuffix,
Index, Count, Repeat, Join, ToUpper, ToLower, TrimSpace, Split,
Replace. 12 functions, 26 tests.
- [x] **`strconv` package:** Itoa, Atoi (positive, negative, decimal).
5 tests + 3 round-trip tests.
- [x] **String-literal AST shape fix.** Parser now emits `:literal-
string` for "..."/`...`/rune literals (was conflated with
numeric literals via first-char heuristic). Eval + typer
dispatch on the new shape. Fixes `Atoi("42")` and similar.
- [ ] `fmt`, `errors`, `sync`, `time`, `io`, `sort` — deferred to
Phase 8b. Tests for `sync.WaitGroup`, `time.After`-in-select,
`sort.Slice` deferred with them.
- **Acceptance:** stdlib/ suite at 40+ tests — **cleared (41 tests).**
### Phase 9 — End-to-end programs ⬜
- Complete programs from canonical sources (gopl.io, "concurrency
@@ -632,6 +632,26 @@ Minimal repro: see `lib/go/lex.sx#gl-oct-digit?` and `#gl-match-op`.
_Newest first. Append one dated entry per commit._
- 2026-05-28 — **Phase 8 first slice closed (stdlib 41/41, +40
cleared, total 597/597).** New `:go-package NAME ENTRIES` value
type with field lookup via extended `go-eval-select`. New
`:go-builtin-fn FN` callable for closure-based stdlib (versus
name-dispatched `:go-builtin`). `lib/go/std/strings.sx` ships 12
functions (Contains, HasPrefix, HasSuffix, Index, Count, Repeat,
Join, ToUpper, ToLower, TrimSpace, Split, Replace); strconv ships
Itoa + Atoi. Conformance runner picks up new suite via
`go-std-test-count`. **Fixed pre-existing literal-classification
bug**: parser was emitting `(:literal V)` for both `42` and
`"42"`, relying on first-char heuristic in eval/types to
distinguish. Now emits `:literal-string` for string/rune,
`:literal` for numeric/imag/float. Eliminates `Atoi("42")` →
number-42 misreading. Three parse tests updated to new shape;
string-literal-in-composite tests too. **Shape locked in:**
packages are AST values of shape `(:KIND NAME ENTRIES)` (parallel
to `:go-struct`, `:go-slice`, `:go-map`, `:go-chan`) — the kit's
value-type registry continues to take the same "kind tag + payload"
shape across orthogonal runtime concepts. [shapes-static-types-
bidirectional]
- 2026-05-28 — **Phase 7 closed (types 102/102, +30 cleared, total
556/556).** Canonical generic functions all type-check and run:
Map, Filter, Reduce, First (eval), plus typer-only Apply, Compose,

View File

@@ -282,6 +282,53 @@ The kits compose; design accordingly.
_Newest first. Append one dated entry per milestone landed._
- 2026-05-28 — From Go-on-SX Phase 8 first slice — **value-type
kinds confirm the "kind-tag + payload" shape as cross-runtime
primitive.** When the stdlib landed, packages joined the existing
registry of value-type kinds:
- `(:go-struct TY-NAME FIELDS)` — composite by-field state
- `(:go-slice ELEMS)` — sequential by-position state
- `(:go-map ENTRIES)` — keyed state
- `(:go-chan ACCESSORS)` — closure-bundle (channel)
- `(:go-fn PARAMS BODY)` — user function value
- `(:go-method RECV PARAMS BODY)` — method value
- `(:go-builtin NAME)` — name-dispatched builtin
- `(:go-builtin-fn FN)` — closure-dispatched builtin (NEW)
- `(:go-package NAME ENTRIES)` — namespace value (NEW)
- `(:go-panic V)` — unwinding-control value
- `(:go-defer CALLEE ARGS)` — frame-cleanup record
All eleven kinds use the same `(:KIND-TAG PAYLOAD...)` shape.
None of them are AST nodes (those are `:func-decl`, `:literal`,
etc.); they're VALUES the evaluator produces. The orthogonal axes
the kit should care about:
1. **AST nodes** (parser output, evaluator input)
2. **Value-type kinds** (evaluator output, predicate input)
3. **Sentinel signals** (control-flow: return/break/panic/etc.)
All three subscribe to the same first-class-tag discipline:
`(first x)` answers "what kind is this?" and the rest is payload.
The kit's `kind?` and `kind-of` predicates work uniformly across
all three axes.
For the bidirectional checker specifically, this means the
`assignable?(got, expected)` predicate isn't special — it's just
one predicate that operates on value-type kinds. The `synth` /
`check` skeleton processes AST nodes; the validators it calls
operate on value-type kinds. Clean separation: AST is what you
parse, value-types are what you check, sentinels are what you
propagate. None of them bleed into each other.
Phase 7's index-synth and Phase 8's package-lookup both fit the
same template: AST kind triggers a synth/lookup, returning a
value-type kind. The validator-table dispatch from earlier diary
entries is the right abstraction; the kit should expose it as a
PROTOCOL (Go would phrase this as an interface, Haskell as a
typeclass) so all three axes can be extended without modifying
the kit.
- 2026-05-28 — From Go-on-SX Phase 7 closing — **the "shape is the
parser, role is the validator" lemma.** After landing canonical
generic Map/Filter/Reduce/First plus 25+ typer tests, a clear