Skip to content

Wintermute 0.3.2 — control flow

Choose a tag to compare

@bsmr bsmr released this 13 Jul 04:57

Second step of the 0.3.x transpiler-language line: control flow. The flat
function body becomes a value-yielding tree, and recursion becomes useful.

  • Operators — the full set beyond +: arithmetic - *, /div,
    %rem; comparison ===:=, !==/=, < > >=, <==<
    (exact term equality, no coercion); boolean &&andalso, ||orelse,
    unary !not. A binary operand that is itself a binary expression is
    parenthesized, so Go's grouping survives regardless of Erlang precedence.
  • if → Erlang case — both the if/else form and the bare-if-plus-
    continuation base case:
    func Fact(N int) int {
        if N == 0 { return 1 }
        return N * Fact(N-1)
    }
    fact(N) -> case N =:= 0 of true -> 1; false -> N * fact(N - 1) end.
    Each case branch is emitted in its own binding scope (bound is
    snapshotted and restored), so sibling clauses may reuse a name freshly while
    a collision with an outer binding — a parameter, a :=, or a receive-pattern
    field — is still rejected. A bare-if whose then-branch would fall through to
    the continuation is rejected rather than silently mis-transpiled.

Correctness is proven end-to-end by a real-toolchain rung: a recursive
factorial fixture transpiles, compiles with erlc, and runs to a checked
result (fact(5) = 120) — the base-case loop actually closes.

Deliberately deferred to 0.3.3+ (all still error): switch, else if chains,
side-effect-only if, guards, multi-value return, cross-module plain calls.

Built subagent-driven and TDD: four tasks (fresh implementer + two-stage review
each), a whole-branch opus review returning "ready to merge" after independently
tracing the receive-field × branch-binding intersection — the exact class the
0.3.1 Copilot gate caught — and confirming it is rejected, not silently emitted.