//! returns: 0

/// Exercise repeated block joins, loop back edges, and early exits.
fn run(limit: u32, skip: bool) -> u32 {
    let mut total: u32 = 7;
    let mut index: u32 = 0;
    while index < limit {
        set index += 1;
        if skip and index % 2 == 0 {
            continue;
        }
        let mut value: u32 = 0;
        match index % 4 {
            case 0 => set value = 11,
            case 1 => set value = 13,
            case 2 => set value = 17,
            else => set value = 19,
        }
        if index > 15 {
            break;
        }
        set total += value;
    }
    return total;
}

/// Return through either a loop-body block or the final block.
fn early(limit: u32) -> u32 {
    for index in 0..limit {
        if index == 3 {
            return index;
        }
    }
    return limit;
}

/// Exercise distinct labels across decimal suffix boundaries.
fn staircase(value: u32) -> u32 {
    let mut result: u32 = 0;
    if value >= 1 { set result += 1; }
    if value >= 2 { set result += 2; }
    if value >= 3 { set result += 3; }
    if value >= 4 { set result += 4; }
    if value >= 5 { set result += 5; }
    if value >= 6 { set result += 6; }
    if value >= 7 { set result += 7; }
    if value >= 8 { set result += 8; }
    if value >= 9 { set result += 9; }
    if value >= 10 { set result += 10; }
    if value >= 11 { set result += 11; }
    if value >= 12 { set result += 12; }
    return result;
}

/// Compare repeated branch and loop execution with a straight-line reference.
@default fn main() -> u32 {
    let values = [11 as u32, 13, 17, 19];
    for limit in 0..24 {
        let steps: u32 = 12 if limit > 12 else limit;
        assert staircase(limit) == steps * (steps + 1) / 2;
        assert early(limit) == (3 if limit > 3 else limit);
        let mut all: u32 = 7;
        let mut odd: u32 = 7;
        for index in 1..16 {
            if index <= limit {
                set all += values[index % 4];
                if index % 2 <> 0 {
                    set odd += values[index % 4];
                }
            }
        }
        assert run(limit, false) == all;
        assert run(limit, true) == odd;
        assert run(limit, false) == all;
    }
    return 0;
}
