ffi M5.A.next: checkpoint — pack feature step 1 done (1c.A → 1d.B)
Logs the four commits that closed out step 1 of the variadic heterogeneous type packs feature: - 1c.A: parser-rejection lock-in for `..$args` inside `Closure(...)`. - 1c.B: parser + AST + types.zig `pack_start` representation. - 1d.A: impl-matching concrete-only miss lock-in. - 1d.B: pack-aware impl matching with $args + $R binding through `param_impl_pack_map` and `pack_bindings`. Next step is plan step 2 — runtime `args[$i]` indexing + per-mono mangling — opening the door to body-side pack reflection that step 5 needs to retire the hand-rolled `Into(Block)` impls. Also catches up the 1b entry which the prior session left uncommitted in the working tree.
This commit is contained in:
@@ -6,8 +6,148 @@ add a test and make it pass — that's two commits).
|
|||||||
|
|
||||||
## Last completed step
|
## Last completed step
|
||||||
|
|
||||||
|
**M5.A.next.1d.B — variadic heterogeneous type packs: pack-aware impl
|
||||||
|
matching** (commit `08feb60`).
|
||||||
|
|
||||||
|
Pack-shaped impls (`impl P(...) for Closure(..$args) -> $R`) now
|
||||||
|
match concrete closure sources at xx resolution time. Concrete
|
||||||
|
impls retain priority — pack matching only fires when
|
||||||
|
`param_impl_map` misses on the concrete key.
|
||||||
|
|
||||||
|
New plumbing in [src/ir/lower.zig](../src/ir/lower.zig):
|
||||||
|
|
||||||
|
- `PackParamImplEntry` carries the pack-shaped source TypeId plus
|
||||||
|
the pack-var and ret-var names extracted from the impl AST's
|
||||||
|
`target_type_expr`. `registerParamImpl` detects pack-shaped
|
||||||
|
sources via `pack_start != null` on the resolved closure type
|
||||||
|
and additionally registers in a new `param_impl_pack_map`
|
||||||
|
keyed by `"Proto\x00<arg_mangled>"` (no source suffix).
|
||||||
|
- `tryUserConversion` re-shapes the lookup so the pack path runs
|
||||||
|
on miss. `tryPackImplMatch` walks the pack entries, verifies
|
||||||
|
the source's fixed prefix matches the impl's prefix, binds
|
||||||
|
the pack-var to the source's tail param TypeIds, binds the
|
||||||
|
ret-var (when the impl's return is generic) to the source
|
||||||
|
return, and monomorphises the convert method. Mangled name
|
||||||
|
stays keyed on the concrete source so distinct call shapes
|
||||||
|
monomorphise separately.
|
||||||
|
- `pack_bindings: ?StringHashMap([]const TypeId)` is saved /
|
||||||
|
restored around monomorphisation, mirroring `type_bindings`.
|
||||||
|
- `resolveClosureTypeWithBindings` handles the `closure_type_expr`
|
||||||
|
node during type resolution: when the closure carries a
|
||||||
|
`pack_name` AND `pack_bindings` has a binding for it, the
|
||||||
|
bound TypeIds are appended after the fixed prefix and the
|
||||||
|
result is a concrete (non-pack) closure type — so the impl
|
||||||
|
body's `self: Closure(..$args) -> $R` substitutes to the
|
||||||
|
concrete source closure during monomorphisation.
|
||||||
|
|
||||||
|
`examples/155-pack-impl-match.sx` flips from the
|
||||||
|
"no Into(Block) for cl_s32_bool__bool" lock-in diagnostic to
|
||||||
|
"pack impl match ok": one user-declared
|
||||||
|
`impl Into(Block) for Closure(..$args) -> $R` covers a
|
||||||
|
`Closure(s32, bool) -> bool` source that stdlib has no
|
||||||
|
hand-rolled impl for. The constructed Block isn't invoked
|
||||||
|
(invoke=null) — the test exercises matching + monomorphisation,
|
||||||
|
not the trampoline (step 5 of the plan).
|
||||||
|
|
||||||
|
Same-file duplicate pack impls diagnose at registration;
|
||||||
|
cross-module pack-impl visibility and multi-pack-impl
|
||||||
|
specificity are deferred (matching the concrete path's existing
|
||||||
|
TODOs).
|
||||||
|
|
||||||
|
193/193 example tests + `zig build test` green. Step 1 of the
|
||||||
|
pack-feature plan ("Parser + type rep + impl matching") is now
|
||||||
|
done.
|
||||||
|
|
||||||
|
**Next step** — Step 2 of the plan: runtime indexing
|
||||||
|
(`args[$i]`) lowers to positional access; per-mono mangling
|
||||||
|
extends with a stable pack-shape hash. Builder fns receive
|
||||||
|
`$args` (a comptime `[]Type`) as a regular value parameter.
|
||||||
|
Replaces a hand-rolled Into impl in stdlib once step 2 + step
|
||||||
|
3 (type-reflection intrinsics) land.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**M5.A.next.1d.A — pack impl matching: lock in concrete-only miss**
|
||||||
|
(commit `ce3c2fe`).
|
||||||
|
|
||||||
|
Pinned today's matching behaviour ahead of 1d.B. A user-declared
|
||||||
|
`impl Into(Block) for Closure(..$args) -> $R` registers under a
|
||||||
|
pack-shaped source key in `param_impl_map`; the xx site mangles
|
||||||
|
the concrete `Closure(s32, bool) -> bool` source and finds
|
||||||
|
nothing → the existing focused diagnostic fires ("no `Into(Block)
|
||||||
|
for cl_s32_bool__bool` impl — add a per-signature
|
||||||
|
`__block_invoke_<sig>` trampoline + Into impl..."). The pack impl
|
||||||
|
is reachable in the file but never considered.
|
||||||
|
|
||||||
|
`examples/155-pack-impl-match.sx` captures the rejection at line
|
||||||
|
43 column 21 (the `xx cl : *Block` site). 193/193 example tests
|
||||||
|
+ `zig build test` green.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**M5.A.next.1c.B — pack type rep: Closure(..$args) parses + interns**
|
||||||
|
(commit `6582449`).
|
||||||
|
|
||||||
|
`parseTypeExpr`'s `Closure(...)` arm now accepts a trailing
|
||||||
|
`..$name` (sigil optional) as a variadic-pack marker. Pack must
|
||||||
|
be terminal — `)` is the only token accepted after the name.
|
||||||
|
`ClosureTypeExpr` AST gains `pack_name: ?[]const u8` carrying
|
||||||
|
the identifier so later slices can name the binding.
|
||||||
|
|
||||||
|
`FunctionInfo` / `ClosureInfo` in `src/ir/types.zig` grow a
|
||||||
|
`pack_start: ?u32 = null` field. `Closure(..$args) -> R` interns
|
||||||
|
as `params = []`, `pack_start = Some(0)` — distinct from any
|
||||||
|
concrete `Closure(...) -> R` shape thanks to updated hash/eql
|
||||||
|
arms. New constructor pair `closureTypePack` /
|
||||||
|
`functionTypePack` keeps the existing single-shape constructors
|
||||||
|
unchanged.
|
||||||
|
|
||||||
|
`type_bridge.resolveClosureType` calls `closureTypePack` when
|
||||||
|
`pack_name != null`. The pack starts after the fixed prefix,
|
||||||
|
so `Closure(Prefix, ..$args)` resolves with `params = [Prefix]`,
|
||||||
|
`pack_start = Some(1)`.
|
||||||
|
|
||||||
|
`examples/154-pack-type-rep.sx` flips from rejecting-with-error
|
||||||
|
to positive parse smoke. 192/192 example tests + `zig build
|
||||||
|
test` green.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**M5.A.next.1c.A — pack type rep: lock in parser rejection**
|
||||||
|
(commit `bb6eca6`).
|
||||||
|
|
||||||
|
Locked in today's `parseTypeExpr` Closure-arm rejection of `..$args`.
|
||||||
|
`examples/154-pack-type-rep.sx` uses `..$args` inside a
|
||||||
|
`Closure(...)` type expression — the pack-shape spelling used by
|
||||||
|
impl headers like `impl Into(Block) for Closure(..$args) -> $R`.
|
||||||
|
Today's parser recognized `..$args` only at parameter-list sites
|
||||||
|
(1b); the Closure type arm called `parseTypeExpr` per position
|
||||||
|
and hit "expected type name" at line 18 column 26.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**M5.A.next.1b — variadic heterogeneous type packs: parser accepts
|
||||||
|
`..$args`** (commit `a51fe26`).
|
||||||
|
|
||||||
|
`parseParams()` in `src/parser.zig:1558` accepts a leading `..`
|
||||||
|
before the optional `$` sigil and the parameter name. The old
|
||||||
|
`args: ..T` form (variadic marker after the colon) still works —
|
||||||
|
both paths set the same `is_variadic` flag. A pack declaration
|
||||||
|
`..$args` parses as:
|
||||||
|
- `is_variadic = true` (leading `..`)
|
||||||
|
- `is_comptime = true` (the `$` sigil)
|
||||||
|
- `type_expr = inferred_type` (no `:` annotation)
|
||||||
|
|
||||||
|
`examples/150-pack-parse.sx` flipped from rejecting-with-error to
|
||||||
|
positive parse smoke. The no-colon branch of `parseParams`
|
||||||
|
propagates `is_variadic` and `is_comptime` onto the Param
|
||||||
|
struct, so later slices can read both flags from the parsed AST.
|
||||||
|
191/191 example tests + `zig build test` green.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
**M5.A.next.1a — variadic heterogeneous type packs: parse lockin**
|
**M5.A.next.1a — variadic heterogeneous type packs: parse lockin**
|
||||||
(this commit).
|
(`ad82847`).
|
||||||
|
|
||||||
First slice of the `..$args` (variadic heterogeneous type pack)
|
First slice of the `..$args` (variadic heterogeneous type pack)
|
||||||
feature per the plan saved at
|
feature per the plan saved at
|
||||||
|
|||||||
Reference in New Issue
Block a user