comptime value params: generalize to tagged_union (+ aggregate hook)

`$s: <TaggedUnion>` now binds a constant variant-literal argument as a
compile-time-known value and resolves it in the inlined body — the
payload-bearing generalization of the enum value param (3c4305f). A bare
variant (`.point`) or a payload variant (`.circle(5.0)`) both bind:

  * the variant TAG goes into `comptime_value_bindings` (i64), so
    `comptimeIntNamed`/`if s == .circle` keep working and the param is
    readable in a TYPE position (`[s]i64`);
  * the full materialized `enum_init(tag, payload)` value goes into a new
    `comptime_value_ref_bindings` (param -> Ref) AND is scoped, so a
    payload read off the bound value (`s.rect`) resolves. A new
    lowering-time accessor `comptimeValueRefNamed(param)` reads it.

`bindEnumValueParams` is generalized to `bindComptimeValueParams`, which
switches on the constraint kind: `.@"enum"` -> tag-only bind,
`.tagged_union` -> tag + value bind. Other value kinds (struct/array
aggregates) are left with an explicit `else` (no silent default) and a
comment marking where the aggregate-const arm goes when a repro lands; a
non-constant arg / unknown variant is a loud, well-spanned diagnostic.

Locked by examples/0640-comptime-tagged-union-value-param.sx (bare +
payload variants, tag comparison, tag-as-dimension, payload read).
0627 (enum) stays green.
This commit is contained in:
agra
2026-06-20 09:39:10 +03:00
parent 8144a88a21
commit d7a6857ee1
6 changed files with 277 additions and 83 deletions

View File

@@ -309,7 +309,16 @@ pub const Lowering = struct {
struct_instance_bindings: std.StringHashMap(std.StringHashMap(TypeId)), // mangled struct name → type param bindings
struct_instance_template: std.StringHashMap([]const u8), // mangled struct name → template name
struct_instance_author: std.StringHashMap(*const ast.StructDecl), // mangled struct name → authoring StructDecl (CP-2: body-author ≡ layout-author)
comptime_value_bindings: ?std.StringHashMap(i64) = null, // comptime value bindings ($N → integer value)
comptime_value_bindings: ?std.StringHashMap(i64) = null, // comptime value bindings ($N → integer value: int / enum-tag / tagged-union-tag)
/// Comptime value params bound to a NON-scalar materialized value (a
/// tagged-union literal, a struct/array aggregate). Keyed by param name →
/// the IR `Ref` of the materialized value (an `enum_init(tag, payload)` for
/// a tagged union, an aggregate const for a struct/array). The companion to
/// `comptime_value_bindings`: the i64 map carries the comptime-readable
/// scalar (the variant TAG for a tagged union, so `comptimeIntNamed` keeps
/// returning it); this map carries the full value Ref so a lowering-time
/// consumer can read the whole bound value (`comptimeValueRefNamed`).
comptime_value_ref_bindings: ?std.StringHashMap(Ref) = null,
protocol_thunk_map: std.StringHashMap([]const FuncId), // "Proto\x00Type" → thunk FuncIds
protocol_vtable_type_map: std.StringHashMap(TypeId), // protocol name → vtable struct TypeId
protocol_vtable_global_map: std.StringHashMap(inst_mod.GlobalId), // "Proto\x00Type" → vtable GlobalId
@@ -1572,7 +1581,13 @@ pub const Lowering = struct {
pub const lowerComptimeGlobal = lower_comptime.lowerComptimeGlobal;
pub const lowerComptimeSideEffect = lower_comptime.lowerComptimeSideEffect;
pub const lowerComptimeCall = lower_comptime.lowerComptimeCall;
pub const bindEnumValueParams = lower_comptime.bindEnumValueParams;
pub const bindComptimeValueParams = lower_comptime.bindComptimeValueParams;
pub const recordComptimeTag = lower_comptime.recordComptimeTag;
pub const recordComptimeValueRef = lower_comptime.recordComptimeValueRef;
pub const bindEnumValueParam = lower_comptime.bindEnumValueParam;
pub const bindTaggedUnionValueParam = lower_comptime.bindTaggedUnionValueParam;
pub const enumHasVariant = lower_comptime.enumHasVariant;
pub const comptimeValueRefNamed = lower_comptime.comptimeValueRefNamed;
pub const lowerInlineComptime = lower_comptime.lowerInlineComptime;
pub const lowerInsertExpr = lower_comptime.lowerInsertExpr;
pub const lowerInsertExprValue = lower_comptime.lowerInsertExprValue;