Class RangeIterationHelper
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.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescription(package private) static final recordParameters for case constructor (AscendingCase or DescendingCase).(package private) static final recordHelper record to pass initialization data between methods. -
Field Summary
Fields inherited from class AbstractGenerator
debugInfoCreator, instructionBuilder, MAX_MESSAGE_LENGTH, stackContext, typeNameOrException -
Constructor Summary
ConstructorsConstructorDescriptionRangeIterationHelper(IRGenerationContext stackContext, GeneratorSet generators) -
Method Summary
Modifier and TypeMethodDescriptiongenerateBodySetup(String loopVariableName, String currentTemp, ISymbol rangeType, DebugInfo debugInfo) Generate body setup: loopVariable becomes a FRESH per-iteration value copied from the counter.(package private) ForRangePolymorphicInstr.DispatchCasesgenerateDispatchCases(RangeIterationHelper.InitializationData initData, String loopVariableName, DebugInfo debugInfo) Generate dispatch cases with explicit IR for all three directions.(package private) RangeIterationHelper.InitializationDatagenerateInitialization(EK9Parser.ForRangeContext forRangeCtx, DebugInfo debugInfo) Generate initialization instructions for the loop.(package private) ForRangePolymorphicInstr.LoopMetadatagenerateLoopMetadata(RangeIterationHelper.InitializationData initData, String loopVariableName) Generate loop metadata containing variable names and types.
-
Constructor Details
-
RangeIterationHelper
RangeIterationHelper(IRGenerationContext stackContext, GeneratorSet generators)
-
-
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
ForRangePolymorphicInstr.LoopMetadata generateLoopMetadata(RangeIterationHelper.InitializationData initData, String loopVariableName) 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 oldSTORE 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: default-construct it, then populate it from the counter via:=:(_copy). 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 fromiterator.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>()(fresh default object into the loop variable) +_copy(currentTemp)(snapshot the counter's value) + RETAIN. Variable already registered to loop scope at declaration. Seedocs/ir-and-codegen/EK9_LOOP_VARIABLE_PER_ITERATION_SEMANTICS.md.
-