Class IRInstructionBuilder

java.lang.Object
org.ek9lang.compiler.phase7.generation.IRInstructionBuilder

public class IRInstructionBuilder extends Object
Stateful instruction builder that uses the IR generation context automatically.

This builder eliminates the need for manual BasicDetails construction and scope/debug info management by using the current stack context from IRGenerationContext automatically.

All instruction creation methods use the current scope and debug information from the stack, ensuring consistency and eliminating parameter threading.

  • Constructor Details

    • IRInstructionBuilder

      public IRInstructionBuilder(IRGenerationContext context)
      Create a new instruction builder with stack-based context access. This enables generators to access the current IRContext without parameter threading.
  • Method Details

    • createDebugInfo

      public DebugInfo createDebugInfo(org.antlr.v4.runtime.tree.ParseTree ctx)
    • createDebugInfo

      public DebugInfo createDebugInfo(Ek9Token token)
      Create debug info from a token.
    • createDebugInfo

      public DebugInfo createDebugInfo(org.antlr.v4.runtime.Token token)
      Create debug info from an ANTLR token.
    • createDebugInfo

      public DebugInfo createDebugInfo(IToken token)
      Create debug info from an EK9 IToken.
    • createTempVariable

      public String createTempVariable()
      Create a temporary variable name.
    • loadLiteral

      public void loadLiteral(String variableName, String literalValue, String literalType)
      Load literal instruction using current context.
    • callWithTarget

      public void callWithTarget(String targetVariable, CallDetails callDetails)
      Create a call instruction with target variable using current context. Handles void vs non-void returns automatically.
    • callStatic

      public void callStatic(String targetVariable, CallDetails callDetails)
      Create a static call instruction using current context.
    • superConstructorCall

      public CallInstr superConstructorCall(ISymbol superType, DebugInfo debugInfo)
      THE implicit super-constructor call (super.<init>()) of a constructor, synthetic or written (IR tidy W3.4, OPS-2/MONO-14) - use this, never a hand-built CallDetails. Named through IRGenerationContext.resolveTypeName(ISymbol) (the identity outside a monomorphisation), metadata of the super's no-argument constructor from SynthesisedCallMetaData, the result into the fixed IRConstants.TEMP_SUPER_INIT. debugInfo null means the current frame's.
    • callSuperConstructor

      public void callSuperConstructor(ISymbol superType)
      Add superConstructorCall(ISymbol, DebugInfo) with the current frame's debug info.
    • instanceInitCall

      public CallInstr instanceInitCall(ISymbol constructType, DebugInfo debugInfo)
      THE call of a construct's own _i_init - its field initialisers - from a constructor, synthetic or written (IR tidy W3.4, OPS-2/MONO-14); use this, never a hand-built CallDetails. _i_init returns nothing, so nothing receives the result. debugInfo null means the current frame's.
    • callInstanceInit

      public void callInstanceInit(ISymbol constructType, DebugInfo debugInfo)
    • callSuperClassInit

      public void callSuperClassInit(ISymbol superType)
      THE call of a super type's _c_init (class initialisation) from a construct's own, into the fixed IRConstants.TEMP_C_INIT, with the current frame's debug info.
    • createBasicBlock

      public BasicBlockInstr createBasicBlock(String labelPrefix)
      Create a BasicBlock with given label and current instructions.
    • retainAndRegister

      public void retainAndRegister(String variableName)
      Create a memory retain and scope register for memory management using current context. Standard ARC pattern: RETAIN (increment refcount) + SCOPE_REGISTER (register for cleanup at scope exit).
    • scopeRegister

      public void scopeRegister(String variableName)
      Create a scope register only (NO retain) for a +1 producer temp. A producer result (CALL / constructor / factory / LOAD_LITERAL) is already handed back at +1, so it only needs SCOPE_REGISTER — the scope-exit release balances that +1 and frees it. Use this, NOT retainAndRegister(String), for producer temps: an extra RETAIN leaves the object at +1 after the release, which is the B1-class generated-body ARC leak (no-op on the JVM). Reserve retainAndRegister for BORROWED values (e.g. LOAD_FIELD) the scope must keep alive.
    • retain

      public void retain(String variableName)
      Create a memory retain only (no scope register). Used for ownership transfer: the variable's refcount is incremented but not registered for scope-based cleanup because ownership transfers to an external entity (e.g., static field on _Application, return value to caller).
    • getContext

      public IRGenerationContext getContext()
      Get the IRGenerationContext for scope and debug management. This allows helpers to access the stack-based context when needed.
    • returnVoid

      public void returnVoid()
    • returnValue

      public void returnValue(String variableName, DebugInfo debugInfo)
    • returnValue

      public void returnValue(String variableName)
      Return a value using current context debug info.
    • initializeEnumConstant

      public void initializeEnumConstant(ISymbol enumType, String constantName, int ordinal)
      Initialize an enum constant static field.

      Creates a new enum instance, sets its _ordinal, _name, and _isEnumSet fields, then stores it to the static field on the enum class.

      Parameters:
      enumType - The enum type SYMBOL - names the target and supplies the constructor metadata
      constantName - The constant field name (e.g., "Red")
      ordinal - The ordinal value (0-based position)
    • addInstruction

      public void addInstruction(IRInstr instruction)
      Add a raw instruction to the current context.
    • inNewScope

      public void inNewScope(DebugInfo debugInfo, Consumer<String> body)
      THE scoped body for code built through this builder (INFRA-1): a fresh scope id, pushed on the stack, SCOPE_ENTER, whatever body adds (it is handed the scope id), SCOPE_EXIT, popped. Exactly the hand-rolled sequence, so anything the body generates (scope ids, temps, labels) is numbered after the scope's own id as it always was. The list-returning twin is ScopedInstructionExecutor.executeWithScopeId.
    • addInstructions

      public void addInstructions(List<IRInstr> instructions)
      Add multiple raw instructions to the current context.
    • extractInstructions

      public List<IRInstr> extractInstructions()
      Extract all built instructions and clear the builder.