How does EK9 enforce variable initialization order?

← Data Flow Safety · Ref: Q688

EK9 tracks variable initialization state through the control flow and rejects any reference to a variable before it has been both declared and initialized.

DECLARATION ORDER (E08010)

Variables must be declared before any reference to them. A forward reference to a variable that has not yet been declared triggers E08010.

INITIALIZATION TRACKING (E08020)

Even after declaration, a variable must be initialized before use. If a variable is declared but not assigned a value before being read, E08020 is triggered.

BRANCH ANALYSIS

The compiler tracks initialization across branches. If a variable is only initialized in one branch of an if/else, the compiler knows it may be uninitialized after the branch.

CORRECT PATTERNS

1. Declare and initialize together: name <- "value"
2. Declare with type and initializer: name as String: "value"
3. Guard-based initialization: if name <- getValue()

See Q632 for define-before-use. See Q633 for init across branches. See Q634 for guard before access.

Example

defines module qa.dataflow.initorder

  defines function

    <?-
      Correct: each variable initialized before use.
      Sequential computation with proper ordering.
    -?>
    calculateShipping() as pure
      ->
        itemWeight as Float
        distanceKm as Float
      <- shippingCost as Float: 0.0

      baseRate <- 5.0
      weightFactor <- itemWeight * 0.5
      distanceFactor <- distanceKm * 0.1

      shippingCost: baseRate + weightFactor + distanceFactor

    <?-
      Correct: guard-based initialization.
      Variable is only used inside the guard where it is guaranteed set.
    -?>
    formatWeight() as pure
      -> weightGrams as Float
      <- formatted as String: "unknown weight"

      if weightGrams > 0.0
        kilograms <- weightGrams / 1000.0
        formatted: `${kilograms} kg`

    <?-
      Correct: initialization across all branches.
      Every branch assigns before later use.
    -?>
    classifyTemperature() as pure
      -> celsius as Float
      <- classification as String: "moderate"

      freezingPoint <- 0.0
      boilingPoint <- 100.0

      if celsius < freezingPoint
        classification: "freezing"
      else if celsius > boilingPoint
        classification: "boiling"

  defines program

    VariableInitOrderDemo()
      stdout <- Stdout()

      cost <- calculateShipping(2.5, 50.0)
      stdout.println(`Shipping: ${cost}`)

      stdout.println(formatWeight(1500.0))
      stdout.println(formatWeight(0.0))

      stdout.println(classifyTemperature(-5.0))
      stdout.println(classifyTemperature(50.0))
      stdout.println(classifyTemperature(150.0))

Common mistakes

E08010 — A variable must be declared before any reference to it. Using baseRate before its declaration is a forward reference. See ek9 -h E08010 for details.

Incorrect:

shippingCost: baseRate + weightFactor + distanceFactor
      baseRate <- 5.0

Correct:

baseRate <- 5.0
      weightFactor <- itemWeight * 0.5
      distanceFactor <- distanceKm * 0.1

      shippingCost: baseRate + weightFactor + distanceFactor

E08050 — A variable must be initialized before use. If classification has no default and is only assigned in one branch, it may be uninitialized when read. See ek9 -h E08050 for details.

Incorrect:

<- classification as String?

Correct:

<- classification as String: "moderate"
Other ways to ask this
  • What is E08010 variable used before defined?
  • What is E08020 variable used before initialized?
  • Does EK9 check that variables are initialized before use?
  • What happens if I reference an uninitialized variable?

Coming from another language?

Java: definite assignment analysis, compile error for uninitialized locals. Python: NameError at runtime. JavaScript: var hoisting, undefined. C: undefined behavior. Rust: ownership prevents use of moved values. EK9: compile-time initialization tracking with E08010 and E08020.

Keywords: initialize, forward, data-flow, E08020, declaration, reference, safety, initialization, variable, E08010, order