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

@@ -0,0 +1,43 @@
// Comptime TAGGED-UNION value parameter: `$s: <TaggedUnion>` generalizes the
// enum value-param mechanism (examples/0627) to a payload-bearing enum. The
// argument is a constant variant literal — either bare (`.point`) or with a
// payload (`.circle(5.0)`) — and binds the param so it resolves in the body:
// * `if s == .circle` lowers as an ordinary tag comparison,
// * the variant tag is comptime-readable in a TYPE position (`[s]i64`),
// * a payload read off the bound value (`s.rect`) resolves to the
// compile-time-known payload.
// Distinct variant args monomorphize the inlined body per value.
#import "modules/std.sx";
Shape :: enum {
circle: f64;
rect: i64;
point;
}
// Tag comparison in the body — bare AND payload variants both bind.
classify :: ($s: Shape) -> i64 {
if s == .circle { return 1; }
if s == .rect { return 2; }
return 3;
}
// Variant tag read as a compile-time integer in a TYPE position (the array
// dimension), exercising the `comptime_value_bindings` / `comptimeIntNamed`
// integration contract for a tagged union.
tag_dim :: ($s: Shape) -> i64 {
arr : [s]i64 = ---;
return arr.len;
}
// Payload read off the bound comptime value.
rect_payload :: ($s: Shape) -> i64 {
if s == .rect { return s.rect; }
return -1;
}
main :: () {
print("{} {} {}\n", classify(.circle(5.0)), classify(.rect(7)), classify(.point)); // 1 2 3
print("{} {} {}\n", tag_dim(.circle(0.0)), tag_dim(.rect(0)), tag_dim(.point)); // 0 1 2
print("{}\n", rect_payload(.rect(42))); // 42
}

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,3 @@
1 2 3
0 1 2
42