go: Phase 7 foundation — generics syntax through parser/typer/eval [shapes-static-types-bidirectional]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 31s

gp-parse-type-params consumes the optional [NAMES CONSTRAINT, ...]
clause after a func name. AST stays backward-compatible: 5-slot
func-decl when no [...] is present, 6-slot when it is.

Typer binds each type-param name as (:ty-param NAME CONSTRAINT) so
body's (:ty-name "T") references resolve. Eval is type-erasing —
ignores type info, dispatches by name + arity.

10 new tests: parse (3), types (5), eval (2). Total 527/527.

Shape: the field binding-group from the canonical kit now feeds
6 consumers (struct fields, var-decls, const-decls, params,
receivers, type-params). Confirms it as a TRUE cross-deliverable
shape — sister-plan diary documents the 5 roles binding-groups
take and why the kit should expose ONE parser + pluggable validators.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-28 00:31:28 +00:00
parent c50f5d5155
commit 459427512d
9 changed files with 264 additions and 34 deletions

View File

@@ -380,14 +380,20 @@ Progress-log line → push `origin/loops/go`.
- **Acceptance:** eval/ +20 tests — **20/20 cleared.**
### Phase 7 — Generics (Go 1.18+) ⬜
- Type parameters with constraints (type sets: `interface{ int | float64
}`, `comparable`, `any`).
- Type inference at call sites — basic; the full Go inference algorithm
is notoriously complex. Implement enough for common cases; document
limitations in a Blockers section below.
- [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`,
`~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.
- **Acceptance:** types/ +30 tests. Currently +5.
### Phase 8 — Minimal stdlib (`lib/go/std/`) ⬜
- Implement just what's needed for representative programs:
@@ -622,6 +628,21 @@ 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 foundation: generics syntax wired through
parser + typer + eval.** New `gp-parse-type-params` consumes the
optional `[NAMES CONSTRAINT, ...]` clause after a func name,
reusing `gp-parse-decl-param-group` so the same field shape that
recurs in struct fields / var-decls / func params / receivers
now also feeds type-parameter lists (6th cross-deliverable use).
AST stays backward-compatible: 5 slots when no `[...]` was
present, 6 slots when it was. Typer binds each name as
`(:ty-param NAME CONSTRAINT)` so body's `(:ty-name "T")`
references resolve. Eval ignores type info entirely (type
erasure) — generic calls just dispatch by name + arity. 10 new
tests (3 parse, 5 types, 2 eval). Total 527/527. **Shape:** the
field-binding-group from canonical kit now feeds 6 consumers,
validating it as a TRUE cross-deliverable shape (not just a
Go-internal artifact). [shapes-static-types-bidirectional]
- 2026-05-27 — **Phase 6 closed (eval 100/100, +20 cleared, total
517/517).** Wired panic propagation through `:go` stmt (v0 sync
surfaces the panic back to the spawner — same end-effect as real

View File

@@ -282,6 +282,44 @@ The kits compose; design accordingly.
_Newest first. Append one dated entry per milestone landed._
- 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:
struct fields, var-decls, const-decls, func params, method
receivers. Now type-parameters re-use the EXACT same parser
(`gp-parse-decl-param-group`) and the same `(list :field NAMES TY)`
shape — only the meaning of TY differs (it's a *constraint* type,
not a value type).
This is the strongest evidence yet that the kit's primary shape
should be a generic `binding-group<TyKind>` parametric over the
role TY plays. Five roles emerge:
1. **value-typing** (struct fields, var-decls, params, receivers):
TY is the type of values that bind to NAMES.
2. **value-pinning** (const-decls): TY is the type of compile-
time-known values.
3. **constraint-binding** (type-parameter lists): TY is a
constraint that the type-variables NAMES must satisfy.
4. **kind-binding** (anticipated for higher-kinded types):
TY would be a kind that type-constructors NAMES inhabit.
5. **trait-binding** (anticipated for Rust-style impl blocks):
TY would be the trait the implementations NAMES provide.
All five share parser + AST shape; they differ in (a) which
predicate validates the relationship between NAMES and TY, and
(b) what scope NAMES are visible in. The kit should expose a
single `parse-binding-group` consumer and let each role plug in
its own validator. This is the same lesson the assignable? +
constraint-satisfies? pluggable-predicate work surfaced — kit
primitives are SHAPES, validators are PLUGINS.
Concretely: when the kit extracts, the bidirectional checker
exposes `extend-ctx-with-binding-group(role, group)` where role
selects the validator. Go's type-params bind via role=
"constraint-binding"; struct fields bind via "value-typing".
Erlang's pattern bindings will bind via something else again.
- 2026-05-27 — From Go-on-SX Phase 3 — **interface satisfaction** is the
third pluggable predicate the kit should ship, alongside `assignable?`
and the synth/check skeleton. Go's structural-and-silent