Files
sx/examples/167-pack-type-fnptr.sx
agra 9137f4158d ffi M5.A.next.3a.C: $args[$i] in fn-pointer type literals
Adds `resolveFunctionTypeWithBindings` so `function_type_expr`
in a binding-aware context — local var annotations, return
types, nested type expressions — recursively resolves through
the active pack bindings. Without this, the fall-through to
`type_bridge.resolveAstType` lost pack context and the new
`pack_index_type_expr` arm spammed the "outside pack-aware
context" diagnostic (the function still worked by accident
thanks to the `.s64` fallback).

Plumbing:
- `resolveTypeWithBindings` adds a `function_type_expr` case
  in both the bindings-active branch and the fallthrough
  switch (the same shape as `closure_type_expr`).
- `resolveFunctionTypeWithBindings` recursively resolves each
  param + return type with bindings, then calls
  `functionTypeCC` with the AST's calling convention.

`examples/167-pack-type-fnptr.sx` exercises the pattern step
5's trampoline needs:
  fp : (*void, $args[0]) -> $args[1] = double_s64;
  return fp(null, args[0]);
Output: 14 (= 7*2 via the typed fn-pointer).

207/207 example tests + `zig build test` green.
2026-05-27 17:26:27 +03:00

31 lines
1013 B
Plaintext

// Variadic heterogeneous type packs — step 3: `$args[$i]` in
// fn-pointer type literals.
//
// `(*void, $args[0]) -> $args[1]` is the shape step 5's generic
// `Into(Block) for Closure(..$args) -> $R` body needs for its
// trampoline:
// typed_fn : (*void, $args[0], $args[1], ...) -> $R =
// xx block_self.sx_fn;
// — the trampoline's invoke slot is typed against the pack
// positions to bridge the Block ABI to the sx closure.
//
// This test exercises the same plumbing on a smaller scale: a
// local var with a fn-pointer type whose param + return types
// both interpolate through `$args[$i]`.
#import "modules/std.sx";
// Two concrete handlers that match the per-mono fn-pointer shape.
double_s64 :: (env: *void, x: s64) -> s64 => x * 2;
via_fnptr :: (..$args) -> $args[1] {
fp : (*void, $args[0]) -> $args[1] = double_s64;
return fp(null, args[0]);
}
main :: () -> s32 {
n := via_fnptr(7, 0); // (s64, s64) → fp : (*void, s64) -> s64
print("{}\n", n);
return 0;
}