Fixes follow-up #1 from step 2b. Pack-fns can now mix non-pack
comptime params with the trailing pack:
tagged :: ($tag: s32, ..$args) -> s64 {
return tag * 100 + args.len;
}
`isPackFn` relaxed to "exactly one trailing pack + any number
of non-pack comptime params". The mono path takes over.
Plumbing in src/ir/lower.zig:
- `lowerPackFnCall` walks fd.params + call_node.args in lockstep:
comptime non-pack args fold into the mangle (`__ct_<value>`
segments); non-comptime non-pack args contribute to the
runtime arg-type list; remaining call args populate the pack
expansion.
- `appendComptimeValueMangle` mangles int / bool / float /
string literals stably. Strings hash to keep the symbol short.
Distinct comptime values get distinct monos.
- `monomorphizePackFn` takes `call_node` so it can read comptime
call args. Skips comptime non-pack params when building the
runtime IR signature. Binds each comptime non-pack param both
as a `comptime_param_nodes` entry (for `#insert`) AND as a
runtime local via alloca+store (for bare-name body access).
`examples/164-pack-mixed-comptime.sx` flips from "unresolved
'tag'" to `703` / `900`. Two calls of `tagged` with
different comptime tags get distinct monos
(`tagged__ct_7__pack_...` and `tagged__ct_9__pack`).
This is the load-bearing prerequisite for step 6 of the plan
(stdlib `print` / `format` refactor to `(\$fmt, ..\$args)`).
Out of scope:
- Non-literal comptime args. `appendComptimeValueMangle`
degrades them to `?` (so two distinct non-literal expressions
in the same call slot would collide). Acceptable since
literal args are the only common case; non-literal would need
comptime evaluation to determine the value.
203/203 example tests + `zig build test` green.
Follow-up #1 from step 2b: pack-fns that mix a non-pack
comptime param with the trailing pack (e.g. `tagged($tag: s32,
..$args)`). Today's `isPackFn` requires the pack to be the
ONLY comptime param; mixed shapes fall through to the inline
`lowerComptimeCall` path. That path adds non-string comptime
params to `comptime_param_nodes` for #insert substitution but
does NOT bind them as runtime locals, so the body's bare
`tag` reference hits "unresolved 'tag'" at the call site.
Next commit:
- Relax `isPackFn` to "exactly one trailing pack + any number
of non-pack comptime params" so the mono path takes over.
- Fold comptime VALUES into the mangled name (`tagged(7, ...)`
and `tagged(9, ...)` get distinct monos so each body sees
its own comptime constants).
- Bind comptime args as both `comptime_param_nodes` (for
#insert substitution) AND runtime locals (for bare-name
references). String literals stay as string locals;
int/bool/float literals become typed locals of the
appropriate primitive type.
This is the load-bearing prerequisite for step 6 (stdlib
`print`/`format` refactor to `(\$fmt, ..\$args)`) — without
mixed-mode mono support, stdlib stays on the inline path
forever.
203/203 example tests + `zig build test` green (the lock-in
captures the wrong-shape diagnostic as the snapshot to flip).