// `make_variant($E, idx, payload)` (modules/std/meta.sx) — the WRITE side of the // metatype reflection triad: construct a value of a MINTED tagged-union by // VARIANT INDEX, when the variant is chosen at runtime and the union was // synthesized at comptime (so its labels can't be a literal `.label(…)`). This // is the shape the `race` result uses: an `inline for 0..N (i)` arm builds the // i-th variant of a synthesized result carrying the winner's value. // // Covers heterogeneous + COMPLEX payloads (multi-field struct, string fat // pointer, a larger struct, scalar) — make_variant zeroes the value then writes // the i64 tag @0 and the payload @ size_of(i64), so payloads of any size/shape // round-trip. Built with the natural early-return-per-arm pattern (a `return` // inside an `inline if` inside an `inline for`). #import "modules/std.sx"; #import "modules/std/meta.sx"; Vec3 :: struct { x: f64; y: f64; z: f64; } // 24 bytes Big :: struct { a: i64; b: i64; c: i64; d: i64; tag: bool; } // 40 bytes (largest payload) // A synthesized 4-variant tagged-union with complex, differently-sized payloads. R :: make_enum("R", .[ EnumVariant.{ name = "v", payload = Vec3 }, EnumVariant.{ name = "s", payload = string }, EnumVariant.{ name = "big", payload = Big }, EnumVariant.{ name = "n", payload = i64 }, ]); // Build the variant chosen by a RUNTIME index, in the matching unrolled arm — // each arm's payload type differs. The `return` inside the `inline if` inside the // `inline for` is the pattern make_variant exists to enable. pick :: (idx: i64, vv: Vec3, sv: string, bv: Big, nv: i64) -> R { inline for 0..field_count(R) (i) { if idx == i { // Comptime match on the loop cursor `i` selects the arm whose payload // type matches variant `i` — cleaner than nested `inline if`/`else`. inline if i == { case 0: { return make_variant(R, i, vv); } case 1: { return make_variant(R, i, sv); } case 2: { return make_variant(R, i, bv); } else: { return make_variant(R, i, nv); } } } } return make_variant(R, 3, -1); // unreachable for a valid idx } show :: (r: R) { if r == { case .v: (p) { print("v = {} {} {}\n", p.x, p.y, p.z); } case .s: (p) { print("s = {}\n", p); } case .big: (p) { print("big = {} {} {} {} {}\n", p.a, p.b, p.c, p.d, p.tag); } case .n: (p) { print("n = {}\n", p); } } } main :: () -> i32 { v :: Vec3.{ x = 1.5, y = 2.5, z = 3.5 }; b :: Big.{ a = 10, b = 20, c = 30, d = 40, tag = true }; show(pick(0, v, "hello", b, 99)); show(pick(1, v, "hello", b, 99)); show(pick(2, v, "hello", b, 99)); show(pick(3, v, "hello", b, 99)); return 0; }