`$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.
44 lines
1.6 KiB
Plaintext
44 lines
1.6 KiB
Plaintext
// 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
|
|
}
|