Package: org.codehaus.groovy.classgen.asm

## [Java] Class StatementWriter

- org.codehaus.groovy.classgen.asm.StatementWriter

-     public class StatementWriter
      extends Object

  Generates bytecode for Groovy statements by visiting AST statement nodes and emitting corresponding JVM instructions via the WriterController. Handles control flow (loops, branches, try/catch), synchronization, assertions, and expression statements.

- - ### Field Summary

    Fields
    Modifiers | Name | Description
    --- | --- | ---
    `protected WriterController` | `controller` | The controller coordinating all bytecode writers for the current class.

  - ### Constructor Summary

    Constructors
    Constructor and description
    `StatementWriter(WriterController controller)` Creates a statement writer backed by the given controller.

  - ### Methods Summary

    Methods
    Type Params | Return Type | Name and description
    --- | --- | ---
    `` | `protected final BytecodeVariable` | `defineLoopIndexVariable(ForStatement statement)`
    `` | `protected final void` | `incrementForLoopIndexVariable(BytecodeVariable indexVariable)` Increments the for-in index variable by one.
    `` | `protected final void` | `storeForLoopVariable(BytecodeVariable variable)` Stores the top-of-stack value into a for-in loop variable slot.
    `` | `public void` | `writeAssert(AssertStatement statement)` Generates bytecode for an assert statement.
    `` | `public void` | `writeBlockStatement(BlockStatement block)` Generates bytecode for a block statement by visiting each contained statement.
    `` | `public void` | `writeBreak(BreakStatement statement)` Generates bytecode for a break statement, applying any intervening finally blocks before the jump.
    `` | `public void` | `writeContinue(ContinueStatement statement)` Generates bytecode for a continue statement, applying any intervening finally blocks before the jump.
    `` | `public void` | `writeDoWhileLoop(DoWhileStatement statement)` Generates bytecode for a do-while loop.
    `` | `public void` | `writeExpressionStatement(ExpressionStatement statement)` Generates bytecode for an expression statement.
    `` | `protected void` | `writeForInLoop(ForStatement statement)` Generates bytecode for a for-in loop by calling `iterator()` on the collection expression and delegating loop control to writeForInLoopControlAndBlock.
    `` | `protected void` | `writeForInLoopControlAndBlock(ForStatement statement)` Emits the loop-control structure and body for a for-in loop.
    `` | `protected void` | `writeForLoopWithClosureList(ForStatement statement)` Generates bytecode for a C-style `for(init; cond; incr)` loop.
    `` | `public void` | `writeForStatement(ForStatement statement)` Generates bytecode for a for statement.
    `` | `public void` | `writeIfElse(IfStatement statement)` Generates bytecode for an if/else statement.
    `` | `protected void` | `writeIteratorHasNext(org.objectweb.asm.MethodVisitor mv)` Emits the Iterator.hasNext call via the given visitor.
    `` | `protected void` | `writeIteratorNext(org.objectweb.asm.MethodVisitor mv)` Emits the Iterator.next call via the given visitor.
    `` | `protected final void` | `writeLoopBackEdge(org.objectweb.asm.Label continueLabel, boolean bodyMayReachContinue)`
    `` | `public void` | `writeReturn(ReturnStatement statement)` Generates bytecode for a return statement.
    `` | `protected void` | `writeStatementLabel(Statement statement)` Emits bytecode labels for any statement labels attached to `statement`.
    `` | `public void` | `writeSwitch(SwitchStatement statement)` Generates bytecode for a switch statement.
    `` | `public void` | `writeSynchronized(SynchronizedStatement statement)` Generates bytecode for a synchronized statement.
    `` | `public void` | `writeThrow(ThrowStatement statement)` Generates bytecode for a throw statement.
    `` | `public void` | `writeTryCatchFinally(TryCatchStatement statement)` Generates bytecode for a try/catch/finally statement.
    `` | `public void` | `writeWhileLoop(WhileStatement statement)` Generates bytecode for a while loop.

  - ### Inherited Methods Summary

    Inherited Methods
    Methods inherited from class | Name
    --- | ---
    `class Object` | `equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### protected final WriterController controller

      The controller coordinating all bytecode writers for the current class.

  - ### Constructor Detail

    - #### public StatementWriter(WriterController controller)

      Creates a statement writer backed by the given controller.

      Parameters:
        `controller` - the writer controller for the current compilation

  - ### Method Detail

    - #### protected final BytecodeVariable defineLoopIndexVariable(ForStatement statement)

    - #### protected final void incrementForLoopIndexVariable(BytecodeVariable indexVariable)

      Increments the for-in index variable by one.

      Plain (non-shared) indexes use `IINC`. Shared indexes are loaded from their Reference, unboxed, incremented, then stored via storeForLoopVariable(BytecodeVariable) so the same per-iteration capture policy applies as for value variables (GROOVY-11751, GROOVY-11792).

      Parameters:
        `indexVariable` - the for-in index variable; must not be `null`

    - #### protected final void storeForLoopVariable(BytecodeVariable variable)

      Stores the top-of-stack value into a for-in loop variable slot.

      Applies the for-in per-iteration capture policy (WriterController.isForInPerIterationCaptureEnabled, GROOVY-11792): when enabled, a shared (holder) loop variable receives a fresh Reference so deferred closures, lambdas, and anonymous inner classes observe this iteration's value. When disabled, the historical in-place `Reference#set` path is used. Non-holder variables always take the plain store path.

      Bytecode emission is delegated to CompileStack.storeVar.

      Parameters:
        `variable` - the for-in value (or similarly stored) loop variable

    - #### public void writeAssert(AssertStatement statement)

      Generates bytecode for an assert statement.

      Parameters:
        `statement` - the assert statement to compile

    - #### public void writeBlockStatement(BlockStatement block)

      Generates bytecode for a block statement by visiting each contained statement. Pushes the block's variable scope, emits the statements, and pops afterward. Named labels on the block create a breakable region so that `break label` within the block jumps to the end of it.

      Parameters:
        `block` - the block statement to compile

    - #### public void writeBreak(BreakStatement statement)

      Generates bytecode for a break statement, applying any intervening finally blocks before the jump.

      Parameters:
        `statement` - the break statement to compile

    - #### public void writeContinue(ContinueStatement statement)

      Generates bytecode for a continue statement, applying any intervening finally blocks before the jump.

      Parameters:
        `statement` - the continue statement to compile

    - #### public void writeDoWhileLoop(DoWhileStatement statement)

      Generates bytecode for a do-while loop.

      Parameters:
        `statement` - the do-while statement to compile

    - #### public void writeExpressionStatement(ExpressionStatement statement)

      Generates bytecode for an expression statement. Evaluates the expression and discards any value left on the operand stack. Marks method-call and binary expressions so that unused return values are elided rather than boxed.

      GROOVY-12242: non-declaration statements that contain an `instanceof` type pattern run in a nested CompileStack state (`pushState`/`pop`) so pattern locals defined during evaluation cannot leak past the statement.

      Parameters:
        `statement` - the expression statement to compile

    - #### protected void writeForInLoop(ForStatement statement)

      Generates bytecode for a for-in loop by calling `iterator()` on the collection expression and delegating loop control to writeForInLoopControlAndBlock.

      Parameters:
        `statement` - the for-in statement to compile

    - #### protected void writeForInLoopControlAndBlock(ForStatement statement)

      Emits the loop-control structure and body for a for-in loop. Assumes the iterator object is already on the operand stack. Declares loop variables, emits the `hasNext`/`next` check-and-advance, generates the loop body, and handles index-variable increment when present.

      Parameters:
        `statement` - the for-in statement whose control and body should be emitted

    - #### protected void writeForLoopWithClosureList(ForStatement statement)

      Generates bytecode for a C-style `for(init; cond; incr)` loop. The collection expression is a ClosureListExpression whose middle element is the boolean condition, lower elements are initializers, and upper elements are incrementors.

      Parameters:
        `statement` - the for statement with a ClosureListExpression collection

    - #### public void writeForStatement(ForStatement statement)

      Generates bytecode for a for statement. Delegates to writeForLoopWithClosureList for C-style loops (using a ClosureListExpression), or to writeForInLoop for for-in loops.

      Parameters:
        `statement` - the for statement to compile

    - #### public void writeIfElse(IfStatement statement)

      Generates bytecode for an if/else statement.

      GROOVY-7463: a labeled `if` registers a breakable frame around the then arm only (same region as before GROOVY-12242). The else arm runs after that frame is popped so labeled-break scoping for the then arm is unchanged. Named break labels remain registered for the method (CompileStack does not un-register them on pop).

      GROOVY-12242 / JEP 394: pattern slots are allocated on the outer frame during the condition (needed for short-circuit `&&` RHS). Each arm then uses CompileStack.pushState/CompileStack.hidePatternVariablesExcept/ CompileStack.pop so only path-live names are visible. Path-live names come from InstanceofFlowBindings metadata attached by VariableScopeVisitor — classgen does not re-run the flow analysis. After both arms, non-survivors are permanently hidden on the outer frame (JLS §6.3.2.2-200-C).

      Parameters:
        `statement` - the if statement to compile

    - #### protected void writeIteratorHasNext(org.objectweb.asm.MethodVisitor mv)

      Emits the Iterator.hasNext call via the given visitor. Overrideable so subclasses can substitute a specialized or inlined variant.

      Parameters:
        `mv` - the method visitor to write to

    - #### protected void writeIteratorNext(org.objectweb.asm.MethodVisitor mv)

      Emits the Iterator.next call via the given visitor. Overrideable so subclasses can substitute a specialized or inlined variant.

      Parameters:
        `mv` - the method visitor to write to

    - #### protected final void writeLoopBackEdge(org.objectweb.asm.Label continueLabel, boolean bodyMayReachContinue)

    - #### public void writeReturn(ReturnStatement statement)

      Generates bytecode for a return statement. For void methods emits `RETURN` after applying any finally blocks. For value-returning methods evaluates the expression, casts it to the declared return type, and emits the appropriate typed return instruction.

      Parameters:
        `statement` - the return statement to compile

    - #### protected void writeStatementLabel(Statement statement)

      Emits bytecode labels for any statement labels attached to `statement`. Called before emitting the body of every statement so that named labels (`break foo` / `continue foo`) resolve correctly.

      Parameters:
        `statement` - the statement whose labels should be emitted

    - #### public void writeSwitch(SwitchStatement statement)

      Generates bytecode for a switch statement. Each `case` expression is compared using Groovy's `isCase` operator, so non-integer switch expressions are supported.

      Parameters:
        `statement` - the switch statement to compile

    - #### public void writeSynchronized(SynchronizedStatement statement)

      Generates bytecode for a synchronized statement. Stores the monitor object in a local variable, emits `MONITORENTER`/`MONITOREXIT` guards, and registers a catch-all exception handler that exits the monitor before rethrowing.

      Parameters:
        `statement` - the synchronized statement to compile

    - #### public void writeThrow(ThrowStatement statement)

      Generates bytecode for a throw statement. Casts the expression to `Throwable` and emits `ATHROW`.

      Parameters:
        `statement` - the throw statement to compile

    - #### public void writeTryCatchFinally(TryCatchStatement statement)

      Generates bytecode for a try/catch/finally statement.

      A BlockRecorder is always registered for the try (and catch) regions so that:

      - a non-empty finally is inlined on every abrupt exit (`return`/`break`/`continue`);
      - exception-table ranges are closed before any enclosing finally is inlined (required when an inner try/catch without its own finally sits inside an outer try/finally — see GROOVY-8229);
      - GROOVY-9805 stack-map casts remain active for assignments in the region (CompileStack.hasBlockRecorder).
      When the finally clause is empty (plain `try`/`catch`), the catch-all identity rethrow and the empty shared-finally block are omitted so the shape matches javac more closely and stays more JIT-friendly.
      Parameters:
        `statement` - the try/catch/finally statement to compile

    - #### public void writeWhileLoop(WhileStatement statement)

      Generates bytecode for a while loop.

      Parameters:
        `statement` - the while statement to compile