Class LoopGuardHelper

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

public final class LoopGuardHelper extends AbstractGenerator
Shared helper for guard variable evaluation in control flow constructs.

Provides reusable guard handling for:

  • WHILE and DO-WHILE loops
  • FOR-RANGE loops
  • FOR-IN loops
  • TRY statements

All constructs use the same guard pattern:

  1. Enter guard scope
  2. Guard setup (evaluates expression, assigns to variable)
  3. Guard entry check (IS_NULL + _isSet produces Boolean)
  4. IF (entry check passes) { inner_body }
  5. Exit guard scope

Supports all 4 guard operators:

  • <- (Declaration): Creates new variable, WITH guard check
  • := (Assignment): Assigns to existing variable, NO guard check
  • :=? (Assignment If Unset): Assigns if unset, WITH guard check
  • ?= (Guarded Assignment): Assigns and checks result, WITH guard check
  • Constructor Details

  • Method Details

    • evaluateGuardVariable

      public GuardVariableDetails evaluateGuardVariable(EK9Parser.PreFlowStatementContext preFlowStmt, String guardScopeId)
      Evaluate guard variable for control flow constructs. Supports all guard forms (same as IF statements):
      • <- (Declaration): while value <- getValue() then condition
      • := (Assignment): while value := getValue() then condition - NO guard check
      • :=? (Assignment If Unset): while value :=? getValue() then condition
      • ?= (Guarded Assignment): while value ?= getValue() then condition

      Guard is evaluated ONCE before the construct body executes (not on each iteration for loops). Guard variable is scoped to the entire construct and available in body.

      For loops and TRY, this also generates the guard ENTRY CHECK - the IS_NULL + _isSet() evaluation that happens ONCE at entry. If the check fails, the entire body is skipped.

      NOTE: For := (blind assignment), NO entry check is generated since the operator doesn't require guard validation - it's just an assignment before the body.

      Parameters:
      preFlowStmt - preFlowStatement context with guard (may be null)
      guardScopeId - Scope ID where guard variable lives
      Returns:
      GuardVariableDetails with guard info including entry check, or GuardVariableDetails.none() if no guard
    • wrapBodyWithGuardEntryCheck

      public List<IRInstr> wrapBodyWithGuardEntryCheck(GuardVariableDetails guardDetails, List<IRInstr> bodyInstructions, String guardScopeId, DebugInfo debugInfo)
      Wrap body instructions in an IF_ELSE_IF that checks the guard entry condition.

      Structure:

      1. SCOPE_ENTER (guard scope)
      2. Guard setup (assignment)
      3. Guard entry check (IS_NULL + _isSet)
      4. IF (entry check passes) { body }
      5. SCOPE_EXIT (guard scope)
      Parameters:
      guardDetails - Guard variable details with entry check info
      bodyInstructions - The body instructions to wrap (loop or try block)
      guardScopeId - The scope ID for the guard
      debugInfo - Debug information
      Returns:
      Instructions with guard wrapper
    • wrapChainWithGuardEntryCheck

      public List<IRInstr> wrapChainWithGuardEntryCheck(GuardVariableDetails guardDetails, ControlFlowChainDetails chainDetails, String guardScopeId, DebugInfo debugInfo)
      Wrap a ControlFlowChainDetails (loop or try) in an IF_ELSE_IF that checks the guard entry condition.

      This is a convenience method for wrapping CONTROL_FLOW_CHAIN instructions.

      Parameters:
      guardDetails - Guard variable details with entry check info
      chainDetails - The control flow chain to wrap
      guardScopeId - The scope ID for the guard
      debugInfo - Debug information
      Returns:
      Instructions with guard wrapper
    • wrapExpressionFormWithGuardEntryCheck

      public List<IRInstr> wrapExpressionFormWithGuardEntryCheck(GuardVariableDetails guardDetails, List<IRInstr> returnVariableSetup, List<IRInstr> bodyInstructionsWithoutRtn, String guardScopeId, DebugInfo debugInfo)
      Wrap body instructions in an IF_ELSE_IF for EXPRESSION FORM with return variable.

      CRITICAL: For expression forms, the return variable must be initialized OUTSIDE the IF wrapper so the variable exists on all code paths (including when guard fails). This prevents JVM VerifyError "Bad local variable type" when accessing the return variable after the IF.

      Structure:

      1. SCOPE_ENTER (guard scope)
      2. Guard setup (assignment)
      3. Guard entry check (IS_NULL + _isSet)
      4. Return variable setup (OUTSIDE IF - always executed)
      5. IF (entry check passes) { body only }
      6. SCOPE_EXIT (guard scope)
      Parameters:
      guardDetails - Guard variable details with entry check info
      returnVariableSetup - Return variable initialization instructions (expression form)
      bodyInstructionsWithoutRtn - Body instructions WITHOUT return variable setup
      guardScopeId - The scope ID for the guard
      debugInfo - Debug information
      Returns:
      Instructions with guard wrapper and properly placed return variable