Class IRGenerationContext
This context provides stack-based scope management that eliminates parameter threading throughout the IR generation process. It manages the transient stack of scope contexts, provides debug information management, and handles instruction building coordination.
Like SymbolsAndScopes, this class provides the shared state management that allows focused helpers to work together cleanly without complex parameter passing.
-
Constructor Summary
ConstructorsConstructorDescriptionIRGenerationContext(IRContext irContext, CoverageProbePlacer sharedProbePlacer) Create a new IR generation context with optional shared CoverageProbePlacer. -
Method Summary
Modifier and TypeMethodDescriptionvoidaddInstruction(IRInstr instruction) Add instruction to current instruction list.voidaddInstructions(List<IRInstr> instructions) Add multiple instructions to current instruction list.createDebugInfo(org.antlr.v4.runtime.Token token) Create debug info from an ANTLR token.createDebugInfo(org.antlr.v4.runtime.tree.ParseTree ctx) Create debug info from a parse context.createDebugInfo(Ek9Token token) Create debug info from a token.createDebugInfo(IToken token) Create debug info from an EK9 IToken (null-safe: a null token has no location).createDebugInfoAlways(org.antlr.v4.runtime.Token token) Create debug info ALWAYS, regardless of debug mode flag.createDebugInfoAlways(org.antlr.v4.runtime.tree.ParseTree ctx) Create debug info ALWAYS from a parse context, regardless of debug mode flag.createDebugInfoAlways(IToken token) Create debug info ALWAYS from an EK9 token, regardless of debug mode flag.Get current debug info from the stack.Get current scope ID from the stack.voidenterMethodScope(String scopeId, DebugInfo debugInfo, IRFrameType frameType) Enter a method/function scope with fresh IRContext for counter isolation.voidenterScope(String scopeId, DebugInfo debugInfo, IRFrameType frameType) Enter a new IR scope context.voidExit the current IR scope.Get current instruction list and clear it.generateBlockLabel(String prefix) Generate a unique block label.generateLabelName(String prefix) Generate a unique label name.generateScopeId(String prefix) Generate a unique scope identifier.Generate a unique compiler-made slot name - seeIRContext.generateSlotName().Generate a unique temporary variable name.Get the compiler flags from IRContext.Get the coverage probe placer for inserting coverage instrumentation.Get current IRContext from stack frame (traverses up to find method-level IRContext).Get the parsed module from IRContext.voidinMethodFrame(String frameName, DebugInfo debugInfo, Runnable work) THE method frame (IR tidy W3.4, INFRA-8): a freshIRContext- its own temp, label and scope counters - for the work, then popped.booleanCheck if coverage instrumentation is enabled.methodBody(String frameName, DebugInfo debugInfo, Consumer<IRInstructionBuilder> body) THE method body (IR tidy W3.4, INFRA-8): in a method frame (inMethodFrame(String, DebugInfo, Runnable)), one builder, the body, then the entry block labelled on the frame's own counter - the operation's body.THE Scenario-3 monomorphisation of this context - its mapping (Monomorphisation.within(PositionalConceptualLookupMapping.Mapping, Supplier)), the dynamic-construct copies and their continuation into a nested context.resolveScopeTypeName(IScope scope) resolveTypeName(ISymbol)for an owning SCOPE that is usually - but not always - a symbol (a method's parent scope, giving the type the method is emitted on).resolveType(ISymbol typeSymbol) The SYMBOL form ofresolveTypeName(ISymbol)- the concrete type a (possibly conceptual) type resolves to under the current generic substitution.resolveTypeByIrName(String fullyQualifiedName) THE recovery of a type symbol from the IR type NAME a phase-7 site already emitted - only for where the name is all that survived (aCallInstrcarries its return type as a name).resolveTypeName(ISymbol typeSymbol) THE "what concrete type name does this (possibly conceptual) type have inside the current Scenario-3 monomorphisation?" step - use this, and never re-derive a variant.
-
Constructor Details
-
IRGenerationContext
Create a new IR generation context with optional shared CoverageProbePlacer. This allows multiple constructs in a module to share probe ID numbering.- Parameters:
irContext- The IR context for this generation scopesharedProbePlacer- Optional shared probe placer; if null, a new one is created
-
-
Method Details
-
enterScope
Enter a new IR scope context. -
enterMethodScope
Enter a method/function scope with fresh IRContext for counter isolation. Creates new IRContext via copy constructor to ensure fresh temp var and label counters. -
exitScope
public void exitScope()Exit the current IR scope. -
inMethodFrame
THE method frame (IR tidy W3.4, INFRA-8): a freshIRContext- its own temp, label and scope counters - for the work, then popped. For work that sets its own operation body;methodBody(String, DebugInfo, Consumer)is the frame with one builder and the entry block. Use these, never a hand-writtenenterMethodScope/exitScopepair.- Parameters:
frameName- the frame's scope id (an operation's name,_call,constructor, ...)
-
methodBody
public BasicBlockInstr methodBody(String frameName, DebugInfo debugInfo, Consumer<IRInstructionBuilder> body) THE method body (IR tidy W3.4, INFRA-8): in a method frame (inMethodFrame(String, DebugInfo, Runnable)), one builder, the body, then the entry block labelled on the frame's own counter - the operation's body. -
currentScopeId
Get current scope ID from the stack. -
currentDebugInfo
-
createDebugInfo
Create debug info from a parse context. -
createDebugInfo
-
createDebugInfo
Create debug info from an ANTLR token. -
createDebugInfo
-
createDebugInfoAlways
Create debug info ALWAYS, regardless of debug mode flag. Used for require/assert statements where source location is essential for error reporting in production, not just debugging. -
createDebugInfoAlways
-
createDebugInfoAlways
Create debug info ALWAYS from a parse context, regardless of debug mode flag. Used for require/assert statements where source location is essential for error reporting in production, not just debugging. -
getCurrentIRContext
Get current IRContext from stack frame (traverses up to find method-level IRContext). Always creates a fresh IRContext for proper counter isolation if none exists. -
generateTempName
Generate a unique temporary variable name. -
generateSlotName
Generate a unique compiler-made slot name - seeIRContext.generateSlotName(). -
generateScopeId
-
generateBlockLabel
-
generateLabelName
-
addInstruction
Add instruction to current instruction list. -
addInstructions
-
extractInstructions
-
getParsedModule
Get the parsed module from IRContext. -
getCompilerFlags
Get the compiler flags from IRContext. -
getCoverageProbePlacer
Get the coverage probe placer for inserting coverage instrumentation.The placer is always available, but only inserts probes when coverage is enabled in compiler flags. This allows generator code to unconditionally call probe methods without checking coverage state.
-
isCoverageEnabled
public boolean isCoverageEnabled()Check if coverage instrumentation is enabled. -
monomorphisation
THE Scenario-3 monomorphisation of this context - its mapping (Monomorphisation.within(PositionalConceptualLookupMapping.Mapping, Supplier)), the dynamic-construct copies and their continuation into a nested context. Emitted types go throughresolveType(ISymbol), never around it. -
resolveTypeName
THE "what concrete type name does this (possibly conceptual) type have inside the current Scenario-3 monomorphisation?" step - use this, and never re-derive a variant.Scenario 3 generates a parameterized type's method BODIES by walking the GENERIC type's AST (there is only one AST, shared by every parameterization), so every symbol recorded against that AST carries TEMPLATE types - a bare
T, or a dependent parameterisation such asList of Tand theIterator of Tthat itsiterator()returns. Each must be re-pointed at its concrete counterpart before it is emitted. Signatures and fields need none of this: those come from the parameterized symbol itself, already substituted by phase 6.This MUST take the type SYMBOL, never its name. A parameterised type's fully qualified name is a one-way SHA-256 digest (
_List_<hash over Box::T>), so a template name cannot be decomposed - a name-to-name lookup silently returns the TEMPLATE name and leaks a class that is never generated into the emitted IR (NoClassDefFoundError, or NoSuchMethodError where it leaks into a call's return type).ConceptualTypeReplacementdoes the substitution structurally (inMonomorphisation), from symbols.- Parameters:
typeSymbol- The (possibly conceptual) type symbol- Returns:
- The concrete type FQN to emit
-
resolveType
The SYMBOL form ofresolveTypeName(ISymbol)- the concrete type a (possibly conceptual) type resolves to under the current generic substitution. Needed where a decision depends on the concrete type's PROPERTIES (e.g. its genus, to decideisTraitCall) rather than just its name: a generic type-parameterconstrain bya trait resolves here to that trait, whereas the raw parameter's own genus isCLASS. Outside a generic (no mapping) the symbol is returned unchanged.- Parameters:
typeSymbol- The (possibly conceptual) type symbol- Returns:
- The concrete type symbol to reason about
-
resolveScopeTypeName
resolveTypeName(ISymbol)for an owning SCOPE that is usually - but not always - a symbol (a method's parent scope, giving the type the method is emitted on). Kept here rather than repeated at each call site so the symbol form, and hence the structural substitution, is never skipped.- Parameters:
scope- The scope naming the owning type- Returns:
- The concrete type FQN to emit
-
resolveTypeByIrName
THE recovery of a type symbol from the IR type NAME a phase-7 site already emitted - only for where the name is all that survived (aCallInstrcarries its return type as a name). Prefer carrying the symbol.A plain type resolves by a type search from this module. A PARAMETERISED type does not: its name is a digest (
module::_Pool_<digest>) and a name search cannot find it (the search's placeholder is not assignable to a parameterised type), so it is matched by its simple name over the scopes of the module the name is in; the digest makes it unique.
-