Class CallDetailsFactory

java.lang.Object
org.ek9lang.compiler.phase7.support.CallDetailsFactory

public final class CallDetailsFactory extends Object
Static factories for the recurring CallDetails shapes in IR generation.

CallDetails is a ten-argument record; the overwhelming majority of call sites build a non-virtual, non-trait, non-explicit-trait-default call (the trailing false, false, false). Constructor calls additionally repeat the type name three times (target object, target type and return type are all the constructed type) with the IRConstants.INIT_METHOD method. These factories single-source those shapes so the boolean tail and the type-name repetition are written once.

Sites that genuinely need a virtual / trait / explicit-trait-default call keep the explicit new CallDetails(...) so the non-default flags stay visible at the call site.

  • Method Details

    • call

      public static CallDetails call(String targetObject, String targetTypeName, String methodName, List<String> parameterTypes, String returnTypeName, List<String> arguments, CallMetaDataDetails metaData)
      A non-virtual, non-trait call to methodName on targetObject.
      Parameters:
      targetObject - the receiver variable (or null for a static/free call)
      targetTypeName - the type that defines the method
      methodName - the (mangled) method name
      parameterTypes - the declared parameter types
      returnTypeName - the declared return type
      arguments - the argument variables
      metaData - purity / complexity / side-effect metadata, or null for a plumbing callee. Metadata supplied for a callee that CompilerPlumbingCalls identifies as plumbing is DROPPED - see below.
    • functionCall

      public static CallDetails functionCall(String functionInstanceVar, String functionTypeName, List<String> parameterTypes, String returnTypeName, List<String> arguments, CallMetaDataDetails metaData, boolean isDelegateCall)
      THE shared shape for invoking a function through its _call method - use this rather than deciding the dispatch flag at each of the three sites that emit one.

      Dispatch here is NOT a question about the function type's openness. A concrete function type is closed, yet a DELEGATE invocation is polymorphic: the variable can hold any function of that signature, including a dynamic function, so the body is only known at run time. A NAMED function call is the opposite - it reaches a singleton whose body is statically known, and must be direct. The dispatch criterion is therefore a DISJUNCTION, and this is its second disjunct: (shape AND not-private AND targetOpen) OR isDelegateCall.

      isDelegateCall is not re-derived here - it is the DELEGATE_CALL marker phase 3 squirrelled onto the CallSymbol, which every caller has already read to decide whether to LOAD a variable or materialise a function singleton. Passing that same boolean keeps the receiver and the flag answering from one source.

      Parameters:
      isDelegateCall - the phase-3 DELEGATE_CALL marker: true for a delegate/chained invocation, false for a named singleton call
    • call

      public static CallDetails call(String targetObject, ISymbol targetType, String methodName, List<String> parameterTypes, String returnTypeName, List<String> arguments, CallMetaDataDetails metaData)
      The same call, but taking the target type as a SYMBOL so BOTH the emitted type name and the virtual-dispatch flag derive from it - they then cannot disagree.

      The String overload hard-codes isVirtualCall = false, on the reasoning that a site "genuinely needing" a virtual call would build its own CallDetails. That framing is the root of a real defect: virtual dispatch is not a choice a call site makes, it is a PROPERTY of the target type (CallTargetResolution.isOpenAggregate). Treating it as a choice let the same type render both ways - Integer._eq appeared as virtual=true 83 times and without it 23 times. Prefer this overload wherever the caller holds the symbol; the flag is then derived once, from the same place the type name comes from.

      DO NOT migrate constructor or super-call sites onto this overload. It sees the target type but NOT the call-site shape, and dispatch is a function of both. An explicit super.m() or a <init> must be a DIRECT call; deriving from openness alone would make them virtual (a type must be as open to be extended at all), which on the LLVM back-end vtable-dispatches super.m() back to the override - infinite recursion. The two shapes it can see are vetoed below; callee privateness it cannot see at all, because CallDetails carries no access modifier. See docs/ir-and-codegen/EK9_IR_DERIVED_FACTS_REVIEW.md before using this more widely - the criterion is under review and this overload is deliberately NOT yet the answer.

      Parameters:
      targetType - the type that defines the method, as a resolved symbol
    • constructorCall

      public static CallDetails constructorCall(String typeName, List<String> parameterTypes, List<String> arguments, CallMetaDataDetails metaData)
      A constructor call on typeName: target object, target type and return type are all typeName and the method is IRConstants.INIT_METHOD.
    • defaultConstructorCall

      public static CallDetails defaultConstructorCall(String typeName, CallMetaDataDetails metaData)
      The no-argument default constructor call on typeName.