Skip to content

Observe control-flow boundaries ​

This recipe focuses on control transfers whose behavior is easy to misread from syntax alone. Its output records when a deferred argument is captured, whether a switch case is re-tested, and which loop a labeled branch targets.

Source ​

ts
import go fmt from "fmt";

function deferredEvaluation(): void {
  let value = 1;
  defer fmt.Print(value, " ");
  value = 2;
  fmt.Print(value, " ");
}

function explicitFallthrough(value: int): void {
  switch (value) {
    case 1 {
      fmt.Print("one ");
      fallthrough;
    }
    case 2 { fmt.Print("next "); }
    default { fmt.Print("other "); }
  }
}

function countVisited(): int {
  let visited = 0;
  outer: for (let row = 0; row < 3; row++) {
    for (let column = 0; column < 3; column++) {
      if (column === 1) { continue outer; }
      visited++;
    }
  }
  return visited;
}

function dispatch(ready: boolean): string {
  if (ready) { goto readyPath; }
  return "cold";
  readyPath: return "ready";
}

function main(): void {
  deferredEvaluation();
  explicitFallthrough(1);
  fmt.Println(countVisited(), dispatch(true));
}

Run ​

sh
keika check control-flow-boundaries.km
keika run control-flow-boundaries.km

Expected output:

text
2 1 one next 3 ready

Read the output ​

  1. defer fmt.Print(value, " ") evaluates value while it is 1; changing the binding to 2 does not change the saved argument. The ordinary print runs first, then the deferred call runs at function exit.
  2. fallthrough; enters the following case body without testing whether its case 2 expression matches. It must be the last direct statement of a non-final value-switch case.
  3. continue outer; begins the next iteration of the named outer loop. Only column zero is counted for each of three rows.
  4. goto readyPath; transfers within one function. The checker allows this forward jump because it enters no nested block, crosses no exception boundary, and skips no declaration.

Prefer structured branches and loops for ordinary code. Labels and goto are narrow tools for making an otherwise awkward transfer explicit; the compiler rejects undefined or unused labels and unsafe jump shapes.

Read Control flow for the semantic model and the syntax reference for the complete statement forms.

Kinmokusei is a pre-1.0 project. Documentation describes implemented behavior.