FREAKV3 docs freak 0.15.1 (Maverick)

Control flow#

Two branch forms, six loop forms, and a bounded loop you will not find in other languages.

if / else if / else#

Conditions take no parentheses. Braces are mandatory even for one statement.

examples/control_if.fk compilesruns
-- `if` / `else if` / `else`. Conditions take no parentheses.
task describe(power: int) -> word {
    if power > 9000 {
        give back "over nine thousand"
    } else if power > 5000 {
        give back "high"
    } else if power > 1000 {
        give back "moderate"
    } else {
        give back "low"
    }
}

task main() -> void {
    say describe(9001)
    say describe(6000)
    say describe(2000)
    say describe(10)
}
Program output
over nine thousand
high
moderate
low

else if chains to any depth. Internally V3 flattens these rather than nesting them, which is one of the architectural fixes that made the self-hosted compiler possible.

when#

when matches a subject against literal arms. _ is the catch-all.

examples/control_when.fk compilesruns
-- `when` matches a subject against literal arms. `_` is the catch-all.
-- Each arm takes one statement; use a block to run several.
task main() -> void {
    pilot code: int = 2

    when code {
        1 -> say "launch"
        2 -> {
            say "hold"
            say "await orders"
        }
        3 -> say "abort"
        _ -> say "unknown"
    }

    pilot phase: word = "sortie"
    when phase {
        "briefing" -> say "in the briefing room"
        "sortie"   -> say "in the air"
        _          -> say "elsewhere"
    }
}
Program output
hold
await orders
in the air

Rules:

  • Each arm is pattern -> statement. One statement — wrap several in a block.
  • Arms are separated by nothing at all; newlines are enough.
  • The subject may be int, word, bool or num.
  • Arm patterns are expressions compared for equality, not patterns. There is no destructuring, no binding, no guards, no ranges.
  • Exhaustiveness is not checked. Without a _ arm and with no match, nothing runs.
  • when is a statement, not an expression. It cannot appear on the right of = or inside give back.

To produce a value from a match, assign inside the arms:

Illustrative snippet; not independently verified. Use the badged executable examples for tested programs.

FREAK
task main() -> void {
    pilot code: int = 2
    pilot mut label: word = ""
    when code {
        1 -> label = "launch"
        2 -> label = "hold"
        _ -> label = "unknown"
    }
    say label
}
Not in V3

Destructuring arms — BETA::Soldier { position } -> engage_at(position) — need variants, which V3 does not have. So does check over maybe / result, and check route. See Not in V3.

Loops#

The listing shows the counted loop, the condition loop and the bounded training arc. for each, the C-style for and while have their own sections below.

examples/control_loops.fk compilesruns
-- Three of V3's loop forms: a counted loop, a condition loop,
-- and the bounded `training arc`.
task main() -> void {
    -- repeat N times
    pilot mut total: int = 0
    repeat 5 times {
        total += 2
    }
    say word_from_int(total)

    -- repeat until CONDITION  (tested before each pass)
    pilot mut countdown: int = 3
    repeat until countdown == 0 {
        say word_from_int(countdown)
        countdown -= 1
    }

    -- break and continue work in every loop form
    pilot mut seen: int = 0
    repeat 10 times {
        seen += 1
        if seen == 3 { continue }
        if seen == 6 { break }
    }
    say word_from_int(seen)
}
Program output
10
3
2
1
6

repeat N times#

Illustrative snippet; not independently verified. Use the badged executable examples for tested programs.

FREAK
repeat COUNT times { body }

COUNT is any int expression, evaluated once before the loop. Add with NAME to get a counter that starts at 0: repeat COUNT times with i { }.

Illustrative snippet; not independently verified. Use the badged executable examples for tested programs.

FREAK
pilot mut i: int = 0
repeat array_len(items) times {
    say array_get(items, i)
    i += 1
}

repeat until#

Illustrative snippet; not independently verified. Use the badged executable examples for tested programs.

FREAK
repeat until CONDITION { body }

The condition is tested before each pass, so the body may run zero times. Note the sense: the loop continues while the condition is false.

training arc#

Illustrative snippet; not independently verified. Use the badged executable examples for tested programs.

FREAK
training arc until CONDITION max N sessions { body }

A loop with a compulsory iteration cap. It stops when the condition becomes true or when the cap is reached — whichever comes first — so it cannot spin forever.

examples/training_arc.fk compilesruns
-- `training arc` is a loop with a mandatory session cap.
-- It stops when the condition becomes true OR when the cap is hit,
-- so it cannot spin forever.
task main() -> void {
    pilot mut power: int = 0

    training arc until power >= 100 max 8 sessions {
        power += 20
    }
    say word_from_int(power)

    -- The cap wins when the condition is never reachable.
    pilot mut stuck: int = 0
    training arc until stuck > 1000 max 4 sessions {
        stuck += 1
    }
    say word_from_int(stuck)
}
Program output
100
4

It lowers to roughly:

int64_t sessions = 0;
while (!(CONDITION) && sessions < N) {
    body;
    sessions++;
}

This makes it genuinely useful for bounded numeric search, where you want a hard guarantee of termination:

examples/bounded_search.fk compilesruns
-- A slightly larger program: integer square root by bisection, driven by
-- a `training arc` so the loop is provably bounded.
shape Bounds {
    lo: int
    hi: int
}

task isqrt(target: int) -> int {
    if target < 2 { give back target }

    pilot mut b: Bounds = Bounds { lo: 1, hi: target }

    training arc until b.lo >= b.hi max 64 sessions {
        pilot mid: int = (b.lo + b.hi + 1) / 2
        if mid * mid > target {
            b.hi = mid - 1
        } else {
            b.lo = mid
        }
    }

    give back b.lo
}

task main() -> void {
    say word_from_int(isqrt(0))
    say word_from_int(isqrt(1))
    say word_from_int(isqrt(15))
    say word_from_int(isqrt(16))
    say word_from_int(isqrt(17))
    say word_from_int(isqrt(1000000))
}
Program output
0
1
3
4
4
1000
Not in V3

The with growth variant — which makes the compiler verify that the body actually mutates the condition's subject — is V4. Plain training arc is fully supported.

break and continue#

Both work in every loop form.

Illustrative snippet; not independently verified. Use the badged executable examples for tested programs.

FREAK
repeat 10 times {
    if should_skip { continue }
    if should_stop { break }
    process()
}

Bare blocks#

A { ... } on its own is a statement. It groups code but does not create a new scope for bindings — a pilot declared inside remains visible afterwards.

Illustrative snippet; not independently verified. Use the badged executable examples for tested programs.

FREAK
task main() -> void {
    pilot x: int = 1
    {
        say word_from_int(x)
    }
}

eventually#

eventually { ... } is the cleanup block. Its V3 behaviour differs sharply from the specification.

examples/eventually.fk compilesruns
-- `eventually { ... }` marks a cleanup block.
--
-- IMPORTANT V3 caveat: V3 emits the block INLINE at the point it is
-- written. It is not deferred to the end of scope and it does not run
-- on `give back`, `break` or `panic`. Place it where you want it to run.
task main() -> void {
    say "engaging"

    eventually {
        say "cleanup"
    }

    say "disengaged"
}
Program output
engaging
cleanup
disengaged
Careful

V3 emits the block inline, where you wrote it. It is not deferred to the end of scope, it does not run in LIFO order with other eventually blocks, and it does not run on give back, break or panic. Treat it as a labelled section, not as defer. True deferred semantics are V4.

for each, ranges and counting loops#

for each NAME in LIST { } visits each element of a list. The same form walks a range of ints: a..b excludes b, a..=b includes it, and step sets the distance between values. repeat N times with NAME { } names the counter of a counted loop, starting at 0. The C-style for (pilot i = 0; i < n; i += 1) { } is also accepted. In every form the loop variable exists only inside the body.

examples/book_for_ranges.fk compilesruns
-- Counting loops. A range a..b stops before b; a..=b includes b.
task main() {
    for each i in 1..4 {
        say "range {i}"
    }
    for each i in 1..=3 {
        say "inclusive {i}"
    }
    for each i in 0..10 step 4 {
        say "step {i}"
    }
    repeat 2 times with pass {
        say "pass {pass}"
    }
    for (pilot i = 3; i > 0; i -= 1) {
        say "countdown {i}"
    }
}
Program output
range 1
range 2
range 3
inclusive 1
inclusive 2
inclusive 3
step 0
step 4
step 8
pass 0
pass 1
countdown 3
countdown 2
countdown 1

A word is not a list: for each c in "abc" is a type error.

while#

while CONDITION { } runs as long as the condition is true, testing before each pass. repeat while CONDITION { } is the same loop. while is a reserved word.

examples/book_while.fk compilesruns
-- `while` runs as long as its condition is true: the opposite of `repeat until`.
task main() {
    pilot fuel = 3
    while fuel > 0 {
        say "fuel {fuel}"
        fuel -= 1
    }

    pilot laps = 0
    repeat while laps < 2 {
        laps += 1
    }
    say "laps {laps}"
}
Program output
fuel 3
fuel 2
fuel 1
laps 2

Summary of what is missing#

ConstructStatus
for each (i, x) in list.enumerate()V4
check over maybe / resultV4
check routeV4
when with destructuring or guardsV4
when in expression positionV4
training arc ... with growthV4
xm3 { a || b } and all squadron concurrencyV4
prob[0.3] chance { }, prob_whenV4
isekai { } bringing back { }V4
eventually if cond { }V4
True deferred eventuallyV4

Badged executable examples were compiled and run with the released freak 0.15.1 (Maverick). 84/84 examples match their reviewed expected output. Illustrative snippets are labelled separately. Regenerate with python tools/refresh.py.

V4 boxes were checked against the development snapshot 7c9a1f3c27 (2026-10-04); 46/46 V4 examples match their reviewed expectation. Regenerate with python tools/verify_v4.py --checkout <Freak-lang>.