Class MethodContext

java.lang.Object
org.ek9lang.compiler.backend.jvm.support.MethodContext

public final class MethodContext extends Object
Shared context for a method that must be coordinated across all generators.

This context tracks:

  • Variable to slot mappings
  • Temp variable source tracking
  • IR labels to JVM labels
  • Local variable debug metadata
  • Scope boundaries
  • Field type descriptors
  • Constructor Details

    • MethodContext

      public MethodContext()
  • Method Details

    • getVariableMap

      public Map<String,Integer> getVariableMap()
      Get the variable to slot mapping.
    • getTempSourceMap

      public Map<String, TempVariableSource> getTempSourceMap()
      Get the temp variable source tracking map.
    • getLabelMap

      public Map<String, org.objectweb.asm.Label> getLabelMap()
      Get the IR label to JVM label mapping.
    • declareLocal

      public void declareLocal(LocalVariableInfo declaration)
      THE record of a local's declaration for the LocalVariableTable: every declaration gets its own entry.

      A name's slot is shared by all its declarations in one method (see declaresAgain(String)), but each declaration is a different variable - sibling if/else blocks, sequential loops and tries may each declare value, even of different types. Keyed by name, only the LAST declaration reached the table and a debugger standing in an earlier block could not see its local. Each declaration is now appended and becomes the name's CURRENT declaration, which later SCOPE_REGISTER / SCOPE_EXIT apply to; the earlier one keeps the end it was given by its own scope's exit, so the ranges do not overlap.

      The one exception is a parameter pre-registered by registerParameter(LocalVariableInfo): the IR's own declaration of it replaces that registration in place.

    • registerParameter

      public void registerParameter(LocalVariableInfo parameter)
      Pre-register a parameter for the LocalVariableTable (before any instruction is processed).
    • currentDeclaration

      public LocalVariableInfo currentDeclaration(String variableName)
      The declaration a name currently refers to, or null if it has none.
    • endDeclarationsIn

      public void endDeclarationsIn(String scopeId, org.objectweb.asm.Label endLabel)
      Record a SCOPE_EXIT: every current declaration registered in that scope ends here. A declaration a later one of the same name has replaced is not current, so it keeps its own (earlier) end.
    • getLocalVariableDeclarations

      public List<LocalVariableInfo> getLocalVariableDeclarations()
      Every declaration of a local (parameters included), in declaration order.
    • getScopeMap

      public Map<String, ScopeInfo> getScopeMap()
      Get the scope boundaries map.
    • getFieldDescriptorMap

      public Map<String,String> getFieldDescriptorMap()
      Get the field descriptor map (maps "this.fieldName" to JVM descriptor).
    • getVariableTypeMap

      public Map<String,String> getVariableTypeMap()
      Get the variable type map (maps variable name to primitive type or null for objects). Used to track whether a variable contains a primitive value (int, boolean) so the correct load/store opcode can be used.
    • declaresAgain

      public boolean declaresAgain(String variableName)
      THE rule for whether a REFERENCE (a local's declaration) must null-initialise the local's slot.

      A local's slot is keyed by its NAME, so every declaration of the same name in one method - a later sequential scope, a sibling if/else block, another loop body, a body the back end emits more than once (a for-range's three direction copies) - shares one slot. Each declaration is a NEW variable and must define the slot again: skipping it leaves whatever the slot held on the incoming paths ('top' after a join where one path never stored it, or the earlier declaration's type), and anything that reads the slot before the new declaration's first store - the generated close of a try resource on its handler path, a returning variable after a finally merge - fails JVM verification (VerifyError).

      The only names that must NOT be null-initialised are those whose value is bound BEFORE their declaration: a parameter (pre-registered in the variable map, never declared here) and a catch handler's exception variable (stored by the handler, see boundBeforeDeclaration(String)).

      Returns:
      true if the declaration must null-initialise the slot (recording that it did)
    • boundBeforeDeclaration

      public void boundBeforeDeclaration(String variableName)
      Record that a local's value has just been bound before its declaration (a catch handler storing the caught exception), so the declaration that follows must keep it rather than null-initialise it.
    • allocateNextSlot

      public int allocateNextSlot()
      Allocate the next variable slot and increment the counter.
    • markOperationScopeIfAbsent

      public void markOperationScopeIfAbsent(String scopeId)
      Record the operation-level (method-wide) scope on the FIRST SCOPE_ENTER — the outermost scope, which spans the whole method and is where parameters are live from. Later (nested control-flow) SCOPE_ENTERs do not overwrite it. B.1: lets DebugInfoGenerator pick the real method-wide scope for parameters instead of an arbitrary findFirst() over the scope map.
    • getOperationScopeId

      public String getOperationScopeId()
      The operation-level (method-wide) scope id, or null if none was recorded.
    • getThisTypeDescriptor

      public String getThisTypeDescriptor()
      The receiver ('this') descriptor for an instance method (e.g. "Lfoo/Bar;"), or null for a static method. When set, DebugInfoGenerator emits the slot-0 this LocalVariableTable entry.
    • setThisTypeDescriptor

      public void setThisTypeDescriptor(String descriptor)
      Record the receiver descriptor for an instance method — enables the slot-0 this LocalVariableTable entry. Leave unset (null) for static methods.