Package org.codehaus.groovy.classgen.asm

# Class WriterController

java.lang.Object
org.codehaus.groovy.classgen.asm.WriterController

Direct Known Subclasses:
  `DelegatingController`

public class WriterController extends Object
Central coordinator for Groovy-to-bytecode compilation of a single class. Owns all the specialized sub-writers (statements, expressions, closures, call sites, etc.) and the shared compilation infrastructure (operand stack, compile stack, type chooser). Must be initialized with `init(org.codehaus.groovy.classgen.AsmClassGenerator, org.codehaus.groovy.classgen.GeneratorContext, org.objectweb.asm.ClassVisitor, org.codehaus.groovy.ast.ClassNode)` before use.

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `boolean`
  `optimizeForInt`
  Controls whether the bytecode generator should emit optimized fast-path code for integer operations.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `WriterController()`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `AsmClassGenerator`
  `getAcg()`
  Returns the AsmClassGenerator managing overall compilation for this class.
  `AssertionWriter`
  `getAssertionWriter()`
  Returns the AssertionWriter for compiling Groovy assert statements into bytecode that evaluates conditions and raises AssertionError.
  `BinaryExpressionHelper`
  `getBinaryExpressionHelper()`
  Returns the appropriate BinaryExpressionHelper for the current code path.
  `int`
  `getBytecodeVersion()`
  Returns the bytecode version (target JVM version) for classes being compiled.
  `CallSiteWriter`
  `getCallSiteWriter()`
  Returns the CallSiteWriter responsible for generating dynamic call site infrastructure.
  `CallSiteWriter`
  `getCallSiteWriterFor(Expression expression)`
  Returns the CallSiteWriter for a specific expression.
  `String`
  `getClassName()`
  Returns the internal (JVM) name of the class being compiled.
  `ClassNode`
  `getClassNode()`
  Returns the ClassNode representing the class currently being compiled.
  `org.objectweb.asm.ClassVisitor`
  `getClassVisitor()`
  Returns the ASM ClassVisitor for emitting class-level bytecode directives.
  `ClosureWriter`
  `getClosureWriter()`
  Returns the ClosureWriter for compiling Groovy closure literals into inner classes implementing GroovyObject and supporting variable capture.
  `CompileStack`
  `getCompileStack()`
  Returns the CompileStack managing local variable slots, scope boundaries, and control flow labels during method compilation.
  `ConstructorNode`
  `getConstructorNode()`
  Returns the ConstructorNode for the constructor currently being compiled, or null if no constructor is active or a method is being compiled instead.
  `GeneratorContext`
  `getContext()`
  Returns the GeneratorContext tracking compilation state across the entire compilation unit, including helper classes and shared resources.
  `org.objectweb.asm.ClassVisitor`
  `getCv()`
  Deprecated.
  Use `getClassVisitor()` instead for clarity
  `InterfaceHelperClassNode`
  `getInterfaceClassLoadingClass()`
  Returns the InterfaceHelperClassNode used for interface static method loading, or null if the compiled class is not an interface or needs no helper class.
  `String`
  `getInternalBaseClassName()`
  Returns the internal (JVM) name of the immediate superclass.
  `String`
  `getInternalClassName()`
  Returns the internal (JVM) name of the class being compiled.
  `InvocationWriter`
  `getInvocationWriter()`
  Returns the InvocationWriter for compiling method calls and dynamic function invocations into appropriate bytecode patterns.
  `LambdaWriter`
  `getLambdaWriter()`
  Returns the LambdaWriter for compiling Java-style lambda expressions (using the `->` operator) into functional interfaces.
  `int`
  `getLineNumber()`
  Returns the source line number currently being compiled.
  `MethodNode`
  `getMethodNode()`
  Returns the MethodNode for the method currently being compiled, or null if no method is active or a constructor is being compiled instead.
  `MethodPointerExpressionWriter`
  `getMethodPointerExpressionWriter()`
  Returns the MethodPointerExpressionWriter for compiling method pointer expressions (e.g., `String.&length`) into method reference objects.
  `MethodReferenceExpressionWriter`
  `getMethodReferenceExpressionWriter()`
  Returns the MethodReferenceExpressionWriter for compiling method reference expressions compatible with Java functional interface targets.
  `org.objectweb.asm.MethodVisitor`
  `getMethodVisitor()`
  Returns the ASM MethodVisitor for emitting bytecode instructions within the currently-active method or constructor.
  `int`
  `getNextHelperMethodIndex()`
  Returns the next sequential index for an internally-generated helper method.
  `OperandStack`
  `getOperandStack()`
  Returns the OperandStack managing the JVM operand stack, tracking stack depth and type information for bytecode verification and optimization.
  `ClassNode`
  `getOutermostClass()`
  Returns the outermost enclosing class in the nesting hierarchy.
  `ClassNode`
  `getReturnType()`
  Returns the declared return type of the current method or constructor.
  `SourceUnit`
  `getSourceUnit()`
  Returns the SourceUnit containing the source code being compiled.
  `StatementWriter`
  `getStatementWriter()`
  Returns the StatementWriter for compiling Groovy statements into bytecode.
  `List<String>`
  `getSuperMethodNames()`
  Returns the list of method names defined by the superclass.
  `SwitchExpressionWriter`
  `getSwitchExpressionWriter()`
  Returns the SwitchExpressionWriter for compiling first-class switch expressions (JEP 361).
  `ClassNode`
  `getThisType()`
  Returns the type of the 'this' reference in the current context.
  `TypeChooser`
  `getTypeChooser()`
  Returns the TypeChooser used to select appropriate type representations for expressions during compilation, supporting both dynamic and typed paths.
  `UnaryExpressionHelper`
  `getUnaryExpressionHelper()`
  Returns the appropriate UnaryExpressionHelper for the current code path.
  `void`
  `init(AsmClassGenerator asmClassGenerator, GeneratorContext gcon, org.objectweb.asm.ClassVisitor cv, ClassNode cn)`
  Initializes this controller with compilation context and ASM infrastructure.
  `boolean`
  `isConstructor()`
  Returns true if a constructor is currently being compiled.
  `boolean`
  `isFastPath()`
  Returns true if the compiler is currently in fast-path mode, emitting specialized bytecode for primitive type operations.
  `boolean`
  `isForInPerIterationCaptureEnabled()`
  Whether for-in loop variables shared with closures, lambdas, or AICs should be re-captured each iteration (language-compat flag, GROOVY-11792).
  `boolean`
  `isInGeneratedFunction()`
  Returns true if the class being compiled is a generated function wrapper (e.g., an inner class synthesized for a closure or lambda expression).
  `boolean`
  `isInGeneratedFunctionConstructor()`
  Returns true if compiling a constructor within a generated function class.
  `boolean`
  `isInScriptBody()`
  `boolean`
  `isNotClinit()`
  Returns true if the current method is NOT a static class initializer (<clinit>).
  `boolean`
  `isStaticConstructor()`
  Returns true if the current method is a static class initializer (<clinit>).
  `boolean`
  `isStaticContext()`
  Determines whether the current execution context is statically scoped.
  `boolean`
  `isStaticMethod()`
  Returns true if the current method is explicitly declared as static.
  `void`
  `resetLineNumber()`
  Resets the tracked line number to -1 (invalid).
  `void`
  `setConstructorNode(ConstructorNode constructorNode)`
  Sets the ConstructorNode for the constructor currently being compiled.
  `void`
  `setInterfaceClassLoadingClass(InterfaceHelperClassNode ihc)`
  Sets the InterfaceHelperClassNode for interface static method loading.
  `void`
  `setLineNumber(int lineNumber)`
  Updates the current source line number being compiled.
  `void`
  `setMethodNode(MethodNode methodNode)`
  Sets the MethodNode for the method currently being compiled.
  `void`
  `setMethodVisitor(org.objectweb.asm.MethodVisitor methodVisitor)`
  Sets the ASM MethodVisitor for the currently-active method or constructor.
  `boolean`
  `shouldOptimizeForInt()`
  Returns true if the bytecode generator should emit optimized fast-path code for integer operations.
  `void`
  `switchToFastPath()`
  Switches compilation to fast-path mode for specialized numeric handling.
  `void`
  `switchToSlowPath()`
  Switches compilation to slow-path mode, reverting to general-purpose bytecode generation.
  `void`
  `visitLineNumber(int lineNumber)`
  Emits a line number bytecode directive if the provided line number differs from the currently-tracked line number and is positive (valid).

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### optimizeForInt

    public boolean optimizeForInt
    Controls whether the bytecode generator should emit optimized fast-path code for integer operations. When enabled, the compiler generates specialized numeric handling paths for better performance with primitive integers. Disabled when invokedynamic is enabled, since JIT compilation provides comparable or better optimization.

- ## Constructor Details

  - ### WriterController

    public WriterController()

- ## Method Details

  - ### init

    public void init(AsmClassGenerator asmClassGenerator, GeneratorContext gcon, org.objectweb.asm.ClassVisitor cv, ClassNode cn)
    Initializes this controller with compilation context and ASM infrastructure. Must be called exactly once before any bytecode generation operations. Sets up all supporting writers (call site, closure, lambda, etc.) and configures optimization strategies based on compiler configuration.
    Parameters:
      `asmClassGenerator` - the class generator managing the overall compilation
      `gcon` - the compilation context tracking state across the compilation unit
      `cv` - the ASM ClassVisitor for emitting bytecode directives
      `cn` - the ClassNode being compiled

  - ### getAcg

    public AsmClassGenerator getAcg()
    Returns the AsmClassGenerator managing overall compilation for this class. Provides access to source units, compiler configuration, and other compilation-wide state.

  - ### getCv

    @Deprecated public org.objectweb.asm.ClassVisitor getCv()
    Deprecated.
    Use `getClassVisitor()` instead for clarity
    Returns the ASM ClassVisitor for emitting class-level bytecode directives.

  - ### getClassVisitor

    public org.objectweb.asm.ClassVisitor getClassVisitor()
    Returns the ASM ClassVisitor for emitting class-level bytecode directives. This is the primary interface for writing class metadata, fields, methods, and attributes to the compiled bytecode.

  - ### getMethodVisitor

    public org.objectweb.asm.MethodVisitor getMethodVisitor()
    Returns the ASM MethodVisitor for emitting bytecode instructions within the currently-active method or constructor. Null if no method is active.

  - ### setMethodVisitor

    public void setMethodVisitor(org.objectweb.asm.MethodVisitor methodVisitor)
    Sets the ASM MethodVisitor for the currently-active method or constructor. Called before each method body compilation to direct bytecode emission.
    Parameters:
      `methodVisitor` - the visitor for the current method, or null to deactivate

  - ### getContext

    public GeneratorContext getContext()
    Returns the GeneratorContext tracking compilation state across the entire compilation unit, including helper classes and shared resources.

  - ### getCompileStack

    public CompileStack getCompileStack()
    Returns the CompileStack managing local variable slots, scope boundaries, and control flow labels during method compilation.

  - ### isForInPerIterationCaptureEnabled

    public boolean isForInPerIterationCaptureEnabled()
    Whether for-in loop variables shared with closures, lambdas, or AICs should be re-captured each iteration (language-compat flag, GROOVY-11792).
    Returns:
      `true` when per-iteration capture is enabled
    See Also:
      - `CompilerConfiguration.isForInPerIterationCaptureEnabled()`

  - ### getOperandStack

    public OperandStack getOperandStack()
    Returns the OperandStack managing the JVM operand stack, tracking stack depth and type information for bytecode verification and optimization.

  - ### getSourceUnit

    public SourceUnit getSourceUnit()
    Returns the SourceUnit containing the source code being compiled. Provides access to source URLs, encoding, and error reporting infrastructure.

  - ### getTypeChooser

    public TypeChooser getTypeChooser()
    Returns the TypeChooser used to select appropriate type representations for expressions during compilation, supporting both dynamic and typed paths.

  - ### getUnaryExpressionHelper

    public UnaryExpressionHelper getUnaryExpressionHelper()
    Returns the appropriate UnaryExpressionHelper for the current code path. Selects fast-path specialized handling when `isFastPath()` is true, otherwise delegates to the general-purpose unary expression handler. Fast-path optimization is controlled by `optimizeForInt`.
    Returns:
      the unary expression writer for the active compilation mode

  - ### getBinaryExpressionHelper

    public BinaryExpressionHelper getBinaryExpressionHelper()
    Returns the appropriate BinaryExpressionHelper for the current code path. Selects fast-path specialized handling when `isFastPath()` is true, otherwise delegates to the general-purpose binary expression handler. Fast-path optimization is controlled by `optimizeForInt`.
    Returns:
      the binary expression writer for the active compilation mode

  - ### getAssertionWriter

    public AssertionWriter getAssertionWriter()
    Returns the AssertionWriter for compiling Groovy assert statements into bytecode that evaluates conditions and raises AssertionError.

  - ### getCallSiteWriter

    public CallSiteWriter getCallSiteWriter()
    Returns the CallSiteWriter responsible for generating dynamic call site infrastructure. Behavior depends on bytecode strategy: either invokedynamic for modern JVMs or traditional call-site caching for broader compatibility.

  - ### getCallSiteWriterFor

    public CallSiteWriter getCallSiteWriterFor(Expression expression)
    Returns the CallSiteWriter for a specific expression. Currently delegates to the default CallSiteWriter; reserved for future expression-specific optimization strategies.
    Parameters:
      `expression` - the expression being processed
    Returns:
      the appropriate call site writer for this expression
    Since:
      6.0.0

  - ### getClosureWriter

    public ClosureWriter getClosureWriter()
    Returns the ClosureWriter for compiling Groovy closure literals into inner classes implementing GroovyObject and supporting variable capture.

  - ### getLambdaWriter

    public LambdaWriter getLambdaWriter()
    Returns the LambdaWriter for compiling Java-style lambda expressions (using the `->` operator) into functional interfaces.

  - ### getStatementWriter

    public StatementWriter getStatementWriter()
    Returns the StatementWriter for compiling Groovy statements into bytecode. Selection depends on optimization mode: OptimizingStatementWriter for `optimizeForInt`, otherwise generic StatementWriter.

  - ### getInvocationWriter

    public InvocationWriter getInvocationWriter()
    Returns the InvocationWriter for compiling method calls and dynamic function invocations into appropriate bytecode patterns.

  - ### getMethodPointerExpressionWriter

    public MethodPointerExpressionWriter getMethodPointerExpressionWriter()
    Returns the MethodPointerExpressionWriter for compiling method pointer expressions (e.g., `String.&length`) into method reference objects.

  - ### getMethodReferenceExpressionWriter

    public MethodReferenceExpressionWriter getMethodReferenceExpressionWriter()
    Returns the MethodReferenceExpressionWriter for compiling method reference expressions compatible with Java functional interface targets.

  - ### getSwitchExpressionWriter

    public SwitchExpressionWriter getSwitchExpressionWriter()
    Returns the SwitchExpressionWriter for compiling first-class switch expressions (JEP 361).
    Since:
      6.0.0

  - ### getClassName

    public String getClassName()
    Returns the internal (JVM) name of the class being compiled. For interface types with a helper loading class, returns the helper class name; otherwise returns the standard internal class name. Format: package segments separated by '/', e.g., "java/lang/String"
    Returns:
      the fully-qualified internal class name

  - ### getClassNode

    public ClassNode getClassNode()
    Returns the ClassNode representing the class currently being compiled. Contains the complete AST structure including fields, methods, and metadata. This is immutable for the duration of the compilation process.
    Returns:
      the ClassNode for this compilation unit

  - ### getMethodNode

    public MethodNode getMethodNode()
    Returns the MethodNode for the method currently being compiled, or null if no method is active or a constructor is being compiled instead.
    Returns:
      the current MethodNode, or null if none is active

  - ### setMethodNode

    public void setMethodNode(MethodNode methodNode)
    Sets the MethodNode for the method currently being compiled. Automatically clears any active constructor node, since only one can be active. Used during compilation to track which method's bytecode is being generated.
    Parameters:
      `methodNode` - the MethodNode to compile, or null to deactivate

  - ### getConstructorNode

    public ConstructorNode getConstructorNode()
    Returns the ConstructorNode for the constructor currently being compiled, or null if no constructor is active or a method is being compiled instead.
    Returns:
      the current ConstructorNode, or null if none is active

  - ### setConstructorNode

    public void setConstructorNode(ConstructorNode constructorNode)
    Sets the ConstructorNode for the constructor currently being compiled. Automatically clears any active method node, since only one can be active. Used during compilation to track which constructor's bytecode is being generated.
    Parameters:
      `constructorNode` - the ConstructorNode to compile, or null to deactivate

  - ### getThisType

    public ClassNode getThisType()
    Returns the type of the 'this' reference in the current context. For regular methods, returns the enclosing class. For closures and lambdas (generated function wrappers), traverses the outer class chain to find the actual 'this' class, skipping intermediate generated wrapper classes.
    Returns:
      the ClassNode representing 'this' in the current context

  - ### getReturnType

    public ClassNode getReturnType()
    Returns the declared return type of the current method or constructor. The return type reflects the method signature from the source code.
    Returns:
      the return type ClassNode
    Throws:
      `GroovyBugError` - if called outside method or constructor context

  - ### getOutermostClass

    public ClassNode getOutermostClass()
    Returns the outermost enclosing class in the nesting hierarchy. For top-level classes, returns the class itself. For nested classes, traverses outward to find the top-level class.
    Returns:
      the outermost ClassNode in the nest

  - ### getInternalClassName

    public String getInternalClassName()
    Returns the internal (JVM) name of the class being compiled. The internal name format uses '/' as package separator, e.g., "org/groovy/MyClass". This corresponds to the formal name used in bytecode class descriptors.
    Returns:
      the fully-qualified internal class name

  - ### getInternalBaseClassName

    public String getInternalBaseClassName()
    Returns the internal (JVM) name of the immediate superclass. The internal name format uses '/' as package separator, e.g., "java/lang/Object". Typically "java/lang/Object" for classes without explicit superclass, or the superclass name for classes with explicit inheritance.
    Returns:
      the fully-qualified internal name of the parent class

  - ### getSuperMethodNames

    public List<String> getSuperMethodNames()
    Returns the list of method names defined by the superclass. Used during method resolution to detect method overrides, generate appropriate method-missing handlers, and verify method signature compatibility. The list is mutable; modifications affect subsequent resolution queries.
    Returns:
      a list of superclass method names

  - ### getInterfaceClassLoadingClass

    public InterfaceHelperClassNode getInterfaceClassLoadingClass()
    Returns the InterfaceHelperClassNode used for interface static method loading, or null if the compiled class is not an interface or needs no helper class. Interface helper classes bridge the gap between interface static methods and their actual implementation in Java 8+ runtime environments.
    Returns:
      the helper class node, or null if not applicable

  - ### setInterfaceClassLoadingClass

    public void setInterfaceClassLoadingClass(InterfaceHelperClassNode ihc)
    Sets the InterfaceHelperClassNode for interface static method loading. Called during interface compilation to register the synthesized helper class that provides access to static interface methods in compatible runtimes. The helper class allows proper method lookup and invocation for interface statics.
    Parameters:
      `ihc` - the helper class node, or null to deactivate

  - ### isStaticContext

    public boolean isStaticContext()
    Determines whether the current execution context is statically scoped. Returns true when compiling inside a static method or static class initializer. For instance constructors, checks whether we're in a special constructor call (e.g., super or this call) which requires static semantics.
    Returns:
      true if executing in static context, false for instance context
    Throws:
      `IllegalStateException` - if called outside valid compilation scope

  - ### isStaticMethod

    public boolean isStaticMethod()
    Returns true if the current method is explicitly declared as static. Returns false if no method is active or the method is instance-scoped.
    Returns:
      true if the current method has the static modifier

  - ### isNotClinit

    public boolean isNotClinit()
    Returns true if the current method is NOT a static class initializer (<clinit>). Equivalent to: no method is active OR the method is not a static constructor. Used to guard code that should not execute in class initialization.
    Returns:
      true if not in static initializer context

  - ### isStaticConstructor

    public boolean isStaticConstructor()
    Returns true if the current method is a static class initializer (<clinit>). The static initializer runs once when the class is loaded by the JVM. Returns false if no method is active or the method is not static.
    Returns:
      true if the current method is the static class initializer

  - ### isConstructor

    public boolean isConstructor()
    Returns true if a constructor is currently being compiled. False if a regular instance or static method is active, or if no method is active.
    Returns:
      true if in constructor compilation context

  - ### isInGeneratedFunction

    public boolean isInGeneratedFunction()
    Returns true if the class being compiled is a generated function wrapper (e.g., an inner class synthesized for a closure or lambda expression). Generated functions have an outer class and are marked as generated.
    Returns:
      true if compiling a closure or lambda's wrapper class

  - ### isInGeneratedFunctionConstructor

    public boolean isInGeneratedFunctionConstructor()
    Returns true if compiling a constructor within a generated function class. Combines two checks: that we're in constructor context AND in a generated function. This condition indicates we're initializing a closure or lambda wrapper.
    Returns:
      true if in a generated function's constructor

  - ### isInScriptBody

    public boolean isInScriptBody()
    Returns:
      true if we are in a script body, where all variables declared are no longer local variables but are properties

  - ### shouldOptimizeForInt

    public boolean shouldOptimizeForInt()
    Returns true if the bytecode generator should emit optimized fast-path code for integer operations. Corresponds to the `optimizeForInt` configuration which is disabled when invokedynamic is enabled.
    Returns:
      true if integer-optimized fast-path code generation is enabled

  - ### switchToFastPath

    public void switchToFastPath()
    Switches compilation to fast-path mode for specialized numeric handling. In fast-path mode, the compiler emits optimized bytecode for common operations on primitive integer types, bypassing dynamic method invocation overhead. Also resets line number tracking to allow proper debug attribute synchronization.

  - ### switchToSlowPath

    public void switchToSlowPath()
    Switches compilation to slow-path mode, reverting to general-purpose bytecode generation. Slow-path mode uses dynamic method dispatch for all operations, suitable when type information is insufficient for safe optimization or type specialization is not beneficial. Also resets line number tracking.

  - ### isFastPath

    public boolean isFastPath()
    Returns true if the compiler is currently in fast-path mode, emitting specialized bytecode for primitive type operations. Use this to determine whether expression helpers should apply optimizations.
    Returns:
      true if fast-path compilation mode is active

  - ### getLineNumber

    public int getLineNumber()
    Returns the source line number currently being compiled. Line numbers are tracked for debug attribute generation in the bytecode, allowing debuggers and profilers to map bytecode instructions to source lines. Returns -1 when no valid line number is active.
    Returns:
      the current source line number, or -1 if invalid/not set

  - ### resetLineNumber

    public void resetLineNumber()
    Resets the tracked line number to -1 (invalid). Called when switching compilation modes or after line number emission to avoid stale line number information in subsequent bytecode.

  - ### setLineNumber

    public void setLineNumber(int lineNumber)
    Updates the current source line number being compiled. The line number is used for debug information (LineNumberTable attribute) and must be set before emitting bytecode for the corresponding source line.
    Parameters:
      `lineNumber` - the new source line number, or -1 to reset

  - ### visitLineNumber

    public void visitLineNumber(int lineNumber)
    Emits a line number bytecode directive if the provided line number differs from the currently-tracked line number and is positive (valid). Creates an ASM label at the current instruction position and records the line number mapping, enabling debuggers to correlate bytecode with source. Only emits if a MethodVisitor is currently active.
    Parameters:
      `lineNumber` - the source line number to emit; must be positive

  - ### getBytecodeVersion

    public int getBytecodeVersion()
    Returns the bytecode version (target JVM version) for classes being compiled. Examples: V1_8 (Java 8), V11 (Java 11), V17 (Java 17), etc. Determined from compiler configuration and affects class file format and available bytecode features in generated code.
    Returns:
      the target bytecode version constant from ASM

  - ### getNextHelperMethodIndex

    public int getNextHelperMethodIndex()
    Returns the next sequential index for an internally-generated helper method. Each invocation increments the counter, ensuring unique names for synthesized methods. Used to generate unique helper method names for method references, closure bridges, type adapters, and other compiler-generated synthetic methods. Helper method names typically follow the pattern: `$static$<index>` or similar.
    Returns:
      a unique positive helper method index, auto-incremented