ffi checkpoint: step 3 done — type-position $args[$i] + intrinsics

Logs the 4-commit step-3 batch (69dcee88b457ff):

- 3a.A/3a.B: parser + AST + resolver for `$args[$i]` in type
  positions (return, param, local-var annotation).
- 3a.C: extend resolution to fn-pointer type literals — the
  shape step 5's generic Into(Block) trampoline body needs.
- 3b: `type_eq` + `has_impl` comptime intrinsics (`type_name`
  already existed). Both fold via `tryConstBoolCondition` so
  `inline if type_eq/has_impl` collapses at lower time.

Step 5 (generic Into(Block) impl) is now type-system-unblocked.
Step 4 (#insert pack passthrough + compile_error) is the
smaller intermediate slice if needed before pushing into the
stdlib refactor.

Issue 0047 (`#run` stderr vs runtime stdout split) noted in
"Current state" — filed but not blocking.

Test count: 208/208.
This commit is contained in:
agra
2026-05-27 17:50:02 +03:00
parent 8b457ffc44
commit 8990edbec8

View File

@@ -6,6 +6,70 @@ add a test and make it pass — that's two commits).
## Last completed step
**M5.A.next.3 — type-position `$args[$i]` + reflection intrinsics**
(commits `69dcee8``8b457ff`, 5 total).
Step 3 of the variadic heterogeneous type packs feature.
`$args[$i]` (literal index) now parses + resolves in every
type position. Three comptime intrinsics — `type_name`,
`type_eq`, `has_impl` — let pack-fn bodies branch on type
identity / protocol membership at compile time.
| Commit | Slice |
|---|---|
| `69dcee8` | 3a.A lock-in: pre-fix parse error for `$args[$i]` in type positions |
| `3df58fe` | 3a.B fix: parser + AST (`PackIndexTypeExpr`) + `resolveTypeWithBindings` arm + sema no-op cases |
| `9137f41` | 3a.C: extend resolution to fn-pointer type literals (`fp : (*void, $args[0]) -> $args[1] = ...`) |
| `8b457ff` | 3b: `type_eq` + `has_impl` intrinsics, both wired through `tryConstBoolCondition` for `inline if` folding |
What works:
- `(..$args) -> $args[0]` — return type position.
- `x : $args[1] = args[1]` — local-var annotation.
- `fp : (*void, $args[0]) -> $args[1] = handler;` — fn-pointer
type literal (the shape step 5's generic trampoline body needs).
- `inline if type_eq($args[0], s64) { ... }` (when the `$args[0]`
argument is in a type position — `type_eq` reads call args via
`resolveTypeArg` which routes to `resolveTypeWithBindings`).
- `has_impl(Hash, s64)` (plain protocols).
- `has_impl(Into(Block), s64)` (parameterised protocols).
New tests:
- `examples/165-pack-type-position.sx` — return type + local
var annotation; two heterogeneous call shapes (s64+string,
string+s64) confirm distinct monos.
- `examples/166-pack-type-position-three.sx``args[2]` (third
element) as return type across three (s64,s64,string),
(bool,f64,s64), (string,string,bool) shapes.
- `examples/167-pack-type-fnptr.sx` — fn-pointer type literal
with `$args[$i]` in both param + return positions.
- `examples/168-pack-reflection-intrinsics.sx` — type_name,
type_eq (with inline-if folding), has_impl for both plain
(Allocator/CAllocator) and parameterised (custom Wrap(s64)
for s32) protocols.
Out of scope (deferred):
- `$args[$i]` in EXPRESSION position (the parser only accepts
it in type positions today — `type_eq($args[0], s64)` works
because the call-arg path resolves through `resolveTypeArg`,
but bare `$args[0]` as a value would need an extra parser arm).
- `$args[$i]` in struct field types.
- has_impl static-only false-negative for protocols whose
thunks haven't been instantiated yet (relies on
`protocol_thunk_map` for plain protocols; a more robust
walk over `fn_ast_map["<T>.<method>"]` is deferred).
- LSP "undefined variable" warnings on type names passed to
reflection intrinsics (cosmetic; sema doesn't know these
builtins accept types as args).
Step 5 (generic `Into(Block) for Closure(..$args) -> $R` impl
in stdlib) is now unblocked from the type-system side. The
trampoline body can finally interpolate `(*void, $args[0],
$args[1], ...) -> $R` per-position types.
208/208 example tests + `zig build test` green.
---
**issue-0046 fix — save/restore outer state in createComptimeFunction**
(commit `248d6e6`, lock-in `13efc56`).
@@ -660,7 +724,7 @@ plus 2 codegen fixes surfaced along the way.**
## Current state
- 204/204 example tests pass; `zig build test` green.
- 208/208 example tests pass; `zig build test` green.
- Phase 3.0/3.1/3.2 + M1.0M1.3 + M2.1M2.3 + M3 + M4.0 + M4.A all landed.
- Pack feature step 1 done (1c.A → 1d.B; commits bb6eca6 → 08feb60).
- Pack feature step 2 done — typed `args[$i]` at literal indices
@@ -673,36 +737,44 @@ plus 2 codegen fixes surfaced along the way.**
- issue-0045 (comptime-fn-with-return verifier crash) fixed (9e78790).
- issue-0046 (nested-comptime-call + return) FIXED (248d6e6) —
`createComptimeFunction` now saves/restores outer state.
- issue-0047 (#run stderr vs runtime stdout split) FILED.
- Pack feature step 3 done — type-position `$args[$i]` +
reflection intrinsics (`type_name`, `type_eq`, `has_impl`).
- iOS-sim chess running end-to-end (verified post-step-2b screencap).
- Chess on macOS / iOS-sim / Android all build and run.
## Pack feature — next slice options
Step 2 + all four follow-ups done. Pack-fns are functionally
complete on the mono path: typed indexing, generic returns,
Steps 1, 2 (+ four follow-ups), and 3 all done. Pack-fns are
functionally complete: typed indexing, generic returns,
heterogeneous picks, OOB diagnostics, bare/runtime `args`
access, mixed comptime+pack — all work.
Step 3 ("Type-reflection intrinsics") is the natural next:
- `$args[$i]` in TYPE positions (param types, return types,
fn-pointer types, struct fields). Unlocks the block-trampoline
body in stdlib's generic `Into(Block) for Closure(..$args) ->
$R` impl — the body needs `typed_fn : (*void, $args[0],
$args[1]) -> $R = xx ...` per-position type interpolation.
- `type_name`, `type_eq`, `has_impl` comptime intrinsics.
access, mixed comptime+pack, `$args[$i]` in type positions,
type-reflection intrinsics.
Step 4 (`#insert` pack passthrough + `compile_error`) is a
parser/interp tweak letting builders raise build-time
diagnostics from inside `#insert` bodies.
small parser/interp tweak letting builders accept `$args` as a
comptime `[]Type` value AND raise build-time diagnostics from
inside `#insert` bodies. Prep work for step 5/6.
Step 5 (generic `Into(Block)` impl) and step 6 (stdlib
`print`/`format` refactor) are the visible payoff slices,
gated on step 3 (and partially step 4).
Step 5 (generic `Into(Block)` impl) — the visible end-user
payoff. Replaces stdlib's per-signature hand-rolled Into
impls with ONE generic that the compiler emits per-call-shape.
Body uses `$args[$i]` in fn-pointer type positions for the
trampoline signature (step 3 unblocked this) + emits a
trampoline-fn per mono.
Outstanding items not blocking step 3:
- Non-literal comptime args in mixed-mode pack-fns (degrades
to a `?` mangle segment today — would need comptime
evaluation for proper handling).
Step 6 (stdlib `print` / `format` refactor) — rewrite the
existing `($fmt: string, args: ..Any)` signatures to use the
new pack feature. Compile-time arity and type checking
instead of runtime Any boxing.
Outstanding items not blocking the next slice:
- `$args[$i]` in EXPRESSION position (parser limitation).
- Non-literal comptime args in mixed-mode pack-fns.
- LSP "undefined variable" warnings on type-name args to
reflection intrinsics (cosmetic).
- has_impl static-only false-negative for un-instantiated
plain protocols.
**M4.0 — context.allocator threading** (4 commits this session):
- `__sx_allocator: Allocator` prepended at field index 0 of every