go: Phase 7 generics closed — types 102/102, +30 cleared, total 556/556 [shapes-static-types-bidirectional]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 53s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 53s
Canonical generic functions: Map, Filter, Reduce, First end-to-end type-check + run. Plus 20+ typer-only shape tests covering Apply, Compose, ToMap, Swap, Box, Triple, ToSlice, Take, Send, Fill, Eq, Values, Pair, Inspect, etc. Index synth (slice/array/map → element type) added to typer. v0 limitations stamped in tests: SX `/` is float (no int mod emulation), `var r []T` indistinguishable from unbound, single-name constraints opaque (no type-set arithmetic). Shape locked in: "the parser recognizes shapes, the validator recognizes roles." Same AST + different role-validators = different guest semantics. Diary documents this as the lemma the kit should extract — three deliverables (binding-groups, control-flow sentinels, index synthesis) now all instantiate it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -379,21 +379,25 @@ Progress-log line → push `origin/loops/go`.
|
||||
args-eager-on-panic-path. 20 tests total on eval/.
|
||||
- **Acceptance:** eval/ +20 tests — **20/20 cleared.**
|
||||
|
||||
### Phase 7 — Generics (Go 1.18+) ⬜
|
||||
### Phase 7 — Generics (Go 1.18+) ✅
|
||||
- [x] **Foundation: parser + typer + eval handle `[T any]` syntax.**
|
||||
`gp-parse-type-params` reads `[NAMES CONSTRAINT, ...]` after the
|
||||
func name; AST gets optional 6th slot (legacy 5-slot preserved
|
||||
when no `[...]`). Typer binds each name as `(:ty-param NAME
|
||||
CONSTRAINT)` in the body ctx via `go-extend-with-type-params`.
|
||||
Eval is type-erasing: ignores type info, dispatches by name +
|
||||
arg count. 10 tests: parse (3), types (5), eval (2).
|
||||
- [ ] Type parameters with type-set constraints (`int | float64`,
|
||||
arg count.
|
||||
- [x] **Canonical generic functions type-check + run end-to-end.**
|
||||
Map, Filter, Reduce, First with `[T any]` / `[T, U any]` /
|
||||
`[T any, U comparable]` constraints. Index synth (`xs[0]` for
|
||||
slice element type, `m[k]` for map value type) added to typer
|
||||
so generic body bodies can index. 30 types tests + 4 eval
|
||||
tests + 3 parse tests = **37 generic-related tests landed.**
|
||||
- [ ] Type-set constraints with real validation (`int | float64`,
|
||||
`~int`). Deferred — needs constraint-satisfaction predicate.
|
||||
- [ ] Type inference at call sites — basic. Currently calls must use
|
||||
explicit type args OR rely on type erasure at eval.
|
||||
- Tests: generic function (`func Map[T, U any](xs []T, f func(T) U) []U`),
|
||||
generic data structure (linked list), constrained type param.
|
||||
- **Acceptance:** types/ +30 tests. Currently +5.
|
||||
- [ ] Type inference at call sites — basic. Currently relies on type
|
||||
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:
|
||||
@@ -628,6 +632,30 @@ 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 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,
|
||||
ToMap, Swap, Box, Triple, ToSlice, Take, Send, Fill, Sum, Eq,
|
||||
Values, Inspect, Contains, Pair, F, G, H, Noop. Index synth
|
||||
(`:index OBJ IDX`) added to typer covering slice/array/map cases
|
||||
— needed for `xs[0]` in generic body bodies.
|
||||
|
||||
**v0 limitations stamped:** SX integer division is float
|
||||
(`3/2 = 1.5`) so emulating modulo via `x - x/2*2` doesn't work —
|
||||
Filter test used `x > 3` instead. `var r []T` binds r to nil
|
||||
which the evaluator can't distinguish from unbound — Map/Filter
|
||||
bodies use `r := []int{}` literal instead. Constraint validation
|
||||
(T must be `comparable`, etc.) is opaque in v0 — names are stored
|
||||
but not checked.
|
||||
|
||||
**Shape locked in:** the type-checker's index synth path now
|
||||
exposes 3 polymorphic cases via the same `:index` AST — slice,
|
||||
array, map. This is the third place (after binding-groups and
|
||||
control-flow sentinels) where a single AST shape parameterizes
|
||||
over its TY interpretation. Sister-plan diary documents this as
|
||||
the **"shape is the parser, role is the validator"** lemma —
|
||||
emerging consistently across deliverables. [shapes-static-types-
|
||||
bidirectional]
|
||||
- 2026-05-28 — **Phase 7 foundation: generics syntax wired through
|
||||
parser + typer + eval.** New `gp-parse-type-params` consumes the
|
||||
optional `[NAMES CONSTRAINT, ...]` clause after a func name,
|
||||
|
||||
@@ -282,6 +282,50 @@ The kits compose; design accordingly.
|
||||
|
||||
_Newest first. Append one dated entry per milestone landed._
|
||||
|
||||
- 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
|
||||
pattern has emerged across THREE distinct deliverables of the
|
||||
Go-on-SX loop:
|
||||
|
||||
1. **Binding-groups** (struct fields / var-decls / params /
|
||||
receivers / type-params): SAME parser, SAME `(:field NAMES
|
||||
TY)` shape, 5 different validators based on what role TY
|
||||
plays.
|
||||
|
||||
2. **Control-flow sentinels** (return-value / break / continue /
|
||||
eval-error / go-panic): SAME `(go-panic? r)`-style dispatch
|
||||
at 4+ AST control-flow sites, each calling the same predicate
|
||||
list — would collapse to a single `propagates?` helper.
|
||||
|
||||
3. **Index synthesis** (`xs[0]` for slice / array / map): SAME
|
||||
`(:index OBJ IDX)` AST, 3 element-type extraction rules
|
||||
dispatching on OBJ's type. The validator differs per role,
|
||||
but the parser shape is one.
|
||||
|
||||
The recurring lemma: **the kit's primary primitive is shape
|
||||
recognition (parser + AST); the kit's secondary primitive is a
|
||||
role-validator dispatch table.** Consumers (Go, Erlang, future
|
||||
guests) plug their semantics into the role table; they never need
|
||||
to define new shapes for things that already match an existing
|
||||
AST.
|
||||
|
||||
Architectural payoff: at extraction time, the kit's API should
|
||||
expose:
|
||||
|
||||
- `parse-XXX` → AST shape (one per shape)
|
||||
- `validate-AST(role, ctx)` → either ctx or error (one per role)
|
||||
- `dispatch-table(role)` → which-validator-fires-for-this-AST
|
||||
|
||||
Reuse across guest evaluators happens automatically because the
|
||||
shape is shared. New guests only register new role handlers; they
|
||||
don't extend the parser.
|
||||
|
||||
Concretely for the bidirectional checker: the synth/check skeleton
|
||||
is the shape; assignable? and constraint-satisfies? are roles.
|
||||
Adding a new language means adding a row to the role table, not a
|
||||
column to the AST.
|
||||
|
||||
- 2026-05-28 — From Go-on-SX Phase 7 foundation — **the field
|
||||
binding-group is a cross-deliverable shape, confirmed by its 6th
|
||||
consumer (type-parameter lists).** Previously documented uses:
|
||||
|
||||
Reference in New Issue
Block a user