Class RangeIterationHelper

java.lang.Object
org.ek9lang.compiler.phase7.generator.AbstractGenerator
org.ek9lang.compiler.phase7.generator.RangeIterationHelper

final class RangeIterationHelper extends AbstractGenerator
Shared helper for range iteration logic used by both for-range loops and stream for-range sources.

Extracts the body-independent parts of range iteration from ForRangeGenerator: initialization (start/end/by evaluation, assertions, direction detection), dispatch case generation (ascending/descending/equal), loop condition evaluation, increment operations, and body setup (loop variable assignment).

Both ForRangeGenerator and StreamStatementGenerator delegate to this helper, each providing their own body instructions. This eliminates ~500 lines of duplication between for-range loops and stream for-range sources.

  • Constructor Details

  • Method Details

    • generateInitialization

      RangeIterationHelper.InitializationData generateInitialization(EK9Parser.ForRangeContext forRangeCtx, DebugInfo debugInfo)
      Generate initialization instructions for the loop. This includes: evaluating start/end/by, asserting they're set, direction detection.
    • generateDispatchCases

      ForRangePolymorphicInstr.DispatchCases generateDispatchCases(RangeIterationHelper.InitializationData initData, String loopVariableName, DebugInfo debugInfo)
      Generate dispatch cases with explicit IR for all three directions.
    • generateLoopMetadata

      Generate loop metadata containing variable names and types.
    • generateBodySetup

      List<IRInstr> generateBodySetup(String loopVariableName, String currentTemp, ISymbol rangeType, DebugInfo debugInfo)
      Generate body setup: loopVariable becomes a FRESH per-iteration value copied from the counter.

      Per-iteration value semantics (FOR-RANGE only). The internal counter (currentTemp) is a single object advanced in place by _inc()/_dec(). If the user-visible loop variable merely aliased that counter (the old STORE loopVariable, currentTemp), any capture / alias / escape of the loop variable would track the moving counter and read the FINAL value — the classic "closure captures the loop variable" footgun. Instead we give the loop variable a fresh object each iteration: a copy of the counter made by the range type's copy constructor, T(counter). Once decoupled, captures hold the value the developer expects with no escape analysis required for correctness (a dead copy is later elided by a Phase 12 pass).

      Contrast FOR-IN (ForInGenerator): its loop variable is a reference to a REAL collection element from iterator.next(), so it must NOT be copied — see that generator. The asymmetry is principled: FOR-RANGE variable = a loop-owned synthesised value (copy it); FOR-IN variable = a reference to a real element (leave it).

      Pattern: RELEASE (drop previous iteration's object, NULL-safe on first iteration) + <init>(currentTemp) (the copy constructor: a new object holding the counter's value). Variable already registered to loop scope at declaration. See docs/ir-and-codegen/EK9_LOOP_VARIABLE_PER_ITERATION_SEMANTICS.md.