//! returns: 0

/// Aggregate result that uses a hidden return-buffer parameter.
record Result: Copy {
    /// Weighted argument sum.
    sum: u32,
    /// Last argument.
    last: u64,
}

/// Return a scalar without explicit parameters.
fn zero() -> u32 {
    return 17;
}

/// Return an aggregate without explicit parameters.
fn empty() -> Result {
    return Result { sum: 19, last: 0x100000000 };
}

/// Check each of the eight scalar parameter positions.
fn scalar(a: u32, b: u32, c: u32, d: u32, e: u32, f: u32, g: u32, h: u32) -> u32 {
    return a + 2*b + 3*c + 4*d + 5*e + 6*f + 7*g + 8*h;
}

/// Check explicit parameters alongside the hidden return buffer.
fn aggregate(a: u32, b: u32, c: u32, d: u32, e: u32, f: u32, h: u64) -> Result {
    return Result { sum: scalar(a, b, c, d, e, f, 7, h as u32), last: h };
}

/// Verify parameter order over repeated scalar and aggregate calls.
@default fn main() -> u32 {
    assert zero() == 17;
    let initial = empty();
    assert initial.sum == 19;
    assert initial.last == 0x100000000;
    for index in 0..8 {
        assert scalar(index, 2, 3, 4, 5, 6, 7, 8) == index + 203;
        let result = aggregate(index, 2, 3, 4, 5, 6, 0x100000008);
        assert result.sum == index + 203;
        assert result.last == 0x100000008;
        assert initial.sum == 19;
        assert initial.last == 0x100000000;
    }
    return 0;
}
