// Tuple values: construction, element access, struct-field storage,
// return, and operators. Regression for the tuple-construction bug where
// an inferred `:=` tuple literal lowered its element values under the
// enclosing fn's (narrower) return `target_type`, mismatching the
// independently-inferred s64 field types and yielding garbage on read.

#import "modules/std.sx";

Box :: struct { xs: (s32, s32); }

swap :: (a: s64, b: s64) -> (s64, s64) { (b, a); }
fst  :: (t: (s64, s64)) -> s64 { t.0; }

main :: () -> s32 {
    // Inferred positional tuple + numeric field access.
    pair := (40, 2);
    print("pair {} {}\n", pair.0, pair.1);

    // Named tuple: named + numeric access.
    named := (x: 10, y: 20);
    print("named {} {} {}\n", named.x, named.0, named.1);

    // Element into a typed local (access path, not just print).
    a : s64 = pair.0;
    b : s64 = pair.1;
    print("locals {} {}\n", a, b);

    // Tuple-typed struct field: store a tuple value, read both elements.
    box : Box = ---;
    box.xs = (7, 9);
    print("field {} {}\n", box.xs.0, box.xs.1);

    // Return a tuple from a function.
    s := swap(1, 2);
    print("ret {} {}\n", s.0, s.1);

    // Pass a tuple by value.
    print("pass {}\n", fst((11, 22)));

    // Operators: equality, concatenation, repetition, membership, lex.
    print("eq {}\n", (1, 2) == (1, 2));
    c := (1, 2) + (3, 4);
    print("concat {} {}\n", c.0, c.3);
    r := (1, 2) * 3;
    print("rep {} {}\n", r.0, r.5);
    print("mem {}\n", 3 in (1, 2, 3));
    print("lex {}\n", (1, 2) < (1, 3));

    // Mixed-size fields: a tuple with both an s64 and a string (16-byte fat
    // pointer). Field types are tracked per-position, so reading each back is
    // typed correctly (s64 prints as a number, string as text).
    mixed := (42, "hi");
    print("mixed {} {}\n", mixed.0, mixed.1);
    0;
}
