← Back to AILP Home

Labeled control

A loop may carry a label. Labeled break(label); and continue(label); then target that loop specifically, which is how you escape or restart an outer loop from inside an inner one.

Naming a loop

Prefix any loop form with label::

func:failsafe = int32(tbb32:err) {
    exit 1;
};

func:main = int32() {
    int32:hits = 0i32;
    outer: loop(0i32, 3i32, 1i32) {
        inner: loop(0i32, 3i32, 1i32) {
            if ($ == 1i32) { continue(outer); }
            hits += 1i32;
        }
    }
    exit hits;
};

break(label)

break(label); leaves the named loop and every loop nested inside it, resuming after the named loop:

search: loop(0i32, 10i32, 1i32) {
    loop(0i32, 10i32, 1i32) {
        if (found()) { break(search); }   // exits both loops
    }
}

continue(label)

continue(label); jumps to the back-edge of the named loop, abandoning any inner loops' remaining work for that pass:

rows: loop(0i32, h, 1i32) {
    loop(0i32, w, 1i32) {
        if (skip_row()) { continue(rows); }   // next row, skip rest of cols
    }
}

Bare vs labeled

Use a label only when you actually need to steer an outer loop; bare forms keep the common case uncluttered.

Next: Nested loops.