Control Flow

Blocks introduced by for and if..else use braces { ... }. A brace block always starts a new local scope, so any variable you assign inside it becomes a fresh local binding even when a variable with the same name already exists outside.

A typical if..else block looks like this,

x = 11;

if (x > 10) {
    x = x + 1;
    y = 0;
    print "1st if branch";
    print x; // output: 12.0
} else if (x < 2) {
    seq {
        print "else if branch";
        print x;
    }
} else {
    print "else branch";
    print x;
}

// error, y not defined. different from python/julia
// print y;
// x is the outter scope x
print x;  // output: 11.0

An example for loop like this,

x = 0;
for x in [1, 2, 3, 4] {
    print x + 1;
    y = x + 1;
    print y;
}

print "-------";
print x; // output: 0.0
// y is not defined in the outer scope.
// print y;

A while loop, by contrast, is closed with the keyword end and does not create a new scope. This lets you declare the loop variable before the loop, update it inside the loop body, and keep using it afterward.

The while loop looks like so,

x = 0;

while (x < 10)
    x = x + 1;
    print x;
end

print "----";
print x;  // print 10.0

The language has no separate declaration keywords like let or var. A simple assignment both declares and assigns if the variable was not found in the scope. Because of this, block delimiters themselves signal scope changes: braces mean "new scope", while..end means "stay in the current one."

With this scheme, a for loop behaves like Julia (the loop variable is local), whereas a while loop behaves like Python (the variable remains shared). The result is a minimal grammar that makes scope boundaries visually obvious and mutation rules predictable.