← Back to AILP Home

limit

limit<Rules> attaches a named value constraint to a variable. v0.34.6 locked both compile-time and runtime behavior for limit violations.

Define Rules

A Rules block names predicates over $, the value being constrained:

Rules:Positive = { $ > 0 };
Rules:Percentage = { $ >= 0, $ <= 100 };

Multiple predicates are ANDed together.

Apply a limit

func:check = NIL(int32:x) {
    limit<Positive> int32:safe = x;
    pass(NIL);
};

The compiler records the constraint as solver evidence for later prove, requires, ensures, and overflow/range checks.

Compile-time failures

If a limit violation is known at compile time, compilation fails with ARIA-076:

Rules:Positive = { $ > 0 };

func:main = int32() {
    fixed int32:zero = 0;
    limit<Positive> int32:x = zero;
    exit x;
};

Diagnostic prefix:

This applies to integer and float-backed Rules checks.

Runtime failsafe checks

When the value is runtime-dependent, the compiler emits a guard. v0.34.6 routes both declaration and assignment violations through failsafe code 49:

func:failsafe = int32(tbb32:err) {
    if (err == 49i32) { exit 49; }
    exit 88;
};

Rules:Positive = { $ > 0 };

func:main = int32() {
    limit<Positive> int32:safe = 1;
    safe = 0; // runtime limit violation → failsafe(49)
    exit 0;
};

Good pattern

Use limit<Rules> at data boundaries or after validation:

Rules:Port = { $ >= 1, $ <= 65535 };

func:connect = NIL(int32:raw_port)
    requires raw_port >= 1i32, raw_port <= 65535i32
{
    limit<Port> int32:port = raw_port;
    prove(port >= 1i32);
    pass(NIL);
};

See also