//! returns: 0

/// Carry several values through nested loop, continue, break, and match edges.
fn run(limit: u32) -> u32 {
    let mut total: u32 = 0;
    let mut count: u32 = 0;
    let mut left: u32 = 3;
    let mut right: u32 = 7;
    for outer in 0..limit {
        if outer == 2 {
            continue;
        }
        let mut inner: u32 = 0;
        loop {
            if inner == limit {
                break;
            }
            let current = inner;
            set inner += 1;
            if current == 1 {
                continue;
            }
            let saved = left;
            set left = right;
            set right = saved;
            match current % 3 {
                case 0 => set total += left,
                case 1 if outer > 0 => set total += right,
                else => set total += left + right,
            }
            set count += 1;
        }
    }
    return total + count * 100 + left * 10000 + right * 100000;
}

/// Compute the same result with bounded loops and explicit selection.
fn expected(limit: u32) -> u32 {
    let mut total: u32 = 0;
    let mut count: u32 = 0;
    for outer in 0..limit {
        for inner in 0..limit {
            if outer <> 2 and inner <> 1 {
                set count += 1;
                let left: u32 = 7 if count % 2 == 1 else 3;
                let right: u32 = 10 - left;
                if inner % 3 == 0 {
                    set total += left;
                } else if inner % 3 == 1 and outer > 0 {
                    set total += right;
                } else {
                    set total += 10;
                }
            }
        }
    }
    let left: u32 = 7 if count % 2 == 1 else 3;
    return total + count * 100 + left * 10000 + (10 - left) * 100000;
}

/// Check empty loops and repeated execution of every control-flow edge.
@default fn main() -> u32 {
    for limit in 0..9 {
        assert run(limit) == expected(limit);
    }
    return 0;
}
