Class AggregateManipulator

java.lang.Object
org.ek9lang.compiler.support.AggregateManipulator

public class AggregateManipulator extends Object
Support for taking one aggregate and manipulating the methods and the like to be applied to another aggregate. This is typically used in the phase 3 where we have one aggregate with a set of methods and what another aggregate to have those methods but in some cases we want to alter the return types via covariance. It also has more general uses in creating operators and methods for specific types or generic types of T. This is a factory of sorts, not in the pure OO sense; but still a factory.
  • Field Details

  • Constructor Details

    • AggregateManipulator

      public AggregateManipulator()
    • AggregateManipulator

      public AggregateManipulator(Ek9Types ek9Types)
  • Method Details

    • getEk9Types

      public Ek9Types getEk9Types()
    • addSyntheticConstructorIfRequired

      public void addSyntheticConstructorIfRequired(IAggregateSymbol aggregateSymbol)
      Add a synthetic constructor, if a constructor is not present. Also adds a constructor with all the properties as well (if not present).
    • addSyntheticConstructorIfRequired

      public void addSyntheticConstructorIfRequired(IAggregateSymbol aggregateSymbol, List<ISymbol> constructorArguments)
      Add a synthetic constructor, if a constructor is not present.

      THE extern guard lives here, so no caller can forget it (A-1, front-end rationalisation plan): an EXTERN type (Java-backed: a built-in, or a defines extern library) that declares NO constructor gets none. The compiler does not generate an extern type, so it must not promise a constructor its implementation was never declared to offer - Panic is the live case (decision 10), and an extern Sub extends Base once got a public Sub() through the sub-type route, a NoSuchMethodError at run time. An enumeration's and a constrained type's constructors are the language's own (default, copy, by name / from the base), never declared in the extern text, so they are not guarded.

    • addConstructorIfRequired

      public void addConstructorIfRequired(IAggregateSymbol aggregateSymbol, List<ISymbol> constructorArguments, boolean synthetic)
      Add a new constructor if not present, marked as synthetic.
    • superHasAccessibleNoArgConstructor

      public boolean superHasAccessibleNoArgConstructor(IAggregateSymbol aggregateSymbol)
      THE test of whether an implicit super() from this aggregate can reach its super: true when there is no real super (none, or the implicit Any), or the super has a no-argument constructor that is not private. False when the super's no-arg is private OR there is none (front-end audit FE39: "absent" used to be missed, because every type always had a generated one). Used to withhold a generated no-arg constructor and, in phase 3 (SuperConstructorAccessOrError), to reject a developer constructor relying on the implicit super().

      Only meaningful once supers are linked and the super's own generated constructors exist - which is why a sub-type's generated no-arg is decided supers-first, after every source has been through phase 2.

    • addConstructor

      public MethodSymbol addConstructor(IAggregateSymbol t)
      Create a new constructor for the aggregate with no params.
      Parameters:
      t - The aggregate type to add the constructor to.
    • addConstructor

      public void addConstructor(IAggregateSymbol aggregateSymbol, List<ISymbol> constructorArguments, boolean synthetic, boolean markedPure)
    • addConstructor

      public MethodSymbol addConstructor(AggregateSymbol t, Optional<ISymbol> s)
      Add another constructor to type t, but passing in an s as the value in the construction.
      Parameters:
      t - The aggregate type to add the constructor to.
      s - The argument - arg with a symbol type to be passed in as a construction parameter.
    • addConstructor

      public MethodSymbol addConstructor(AggregateSymbol t, ISymbol s)
      Add a constructor to the type aggregate with a particular parameter.
    • createGenericT

      public AggregateSymbol createGenericT(String name, String genericParent, IScope scope)
      Create a generic parameter of specific name. We use the name createGenericT, so it is obvious what we are doing here. These are used in generic classes/functions, and we provide a number of operators that a developer would reasonably expect. So our generic types and functions will compile and all will look OK. But when it comes to use with a concrete type we have to check the actual operators that are supported by those concrete types - this is done in the IR phase. Where are the generic type/functions get checked in the resolve phase.

      A 'T' IS an Any from the moment it is created (Steve, 2026-10-08, G2 and ANY AT CREATION): whatever type argument it is given, that type is an Any, so inside the generic body a 'T' may be passed or assigned wherever an Any is accepted - by the ordinary assignability cost (Any is the costliest match), not by any special case. A constrained 'T' has that super replaced by its constraining type in phase 2 (updateToConstrainBy(IAggregateSymbol, IAggregateSymbol)), and reaches Any through that type's chain. "Has a super" therefore never means "constrained" - ask TypeParameterConstraint.of(IAggregateSymbol). Substitution re-checks the concrete type, so this only removes a false template error; a 'List of T' is still NOT a 'List of Any' (parameterised types stay invariant).

      'T' remains CONCEPTUAL (isConceptualTypeParameter()); every super-chain walker that must not treat it as a real type checks that, never the super.

      Parameters:
      name - - The name of the generic type parameter
      genericParent - - The fully qualified name of the generic function or class this 'T' is defined for.
      scope - - The scope it should go in.
    • resolveAny

      public static Optional<ISymbol> resolveAny(IScope scope)
      THE search for the built-in Any through a scope: the fully qualified name, of category ANY - a category only AnyTypeSymbol has, so nothing a user declares can answer it. Use it wherever Any must be found WITHOUT the built-in type cache: building that cache (phase1/BuiltInTypeCacheResolver), the bootstrap module while it is still being defined, and a parameterised type created in SYMBOL_DEFINITION. Everyone else asks the cache (Ek9Types.ek9Any()). Never write the search out again (front-end rationalisation F13/A-12: there were four spellings, one of them an unqualified "Any").
      Returns:
      the Any, or empty for a scope that cannot reach the built-in module
    • updateToConstrainBy

      public void updateToConstrainBy(IAggregateSymbol t, IAggregateSymbol constrainingType)
      This is the idea where a 'T' is constrained to only be a type or a subtype of that type. The constraining type replaces nothing else: it reaches Any through its own chain.
    • addConstrainingTypeConstructors

      public void addConstrainingTypeConstructors(IAggregateSymbol t, IAggregateSymbol constrainingType)
      Clone the constraining type's constructors onto a constrained 'T', so T can be constructed with the same arguments (implemented as a call to the super). Called once every constructor exists - see ConstrainedTypesPopulator.
    • getAllPossibleDefaultOperators

      public List<MethodSymbol> getAllPossibleDefaultOperators(IAggregateSymbol aggregate)
      Provides all the possible default operators. Does not add them to the aggregate, but does create them with the aggregate as the enclosing scope.
    • getDefaultOperator

      public Optional<MethodSymbol> getDefaultOperator(IAggregateSymbol aggregate, String operator)
      If the operator provided can be defaulted then a Method symbol with the correct signature will be returned. Otherwise, the return Optional will be empty (normally indicating an error).
    • addAllSyntheticOperators

      public void addAllSyntheticOperators(IAggregateSymbol t)
      Add all possible synthetic operators to the aggregate. This is useful for creation conceptual types like 'T'. Because the semantics of the operators is fixed and known it means it is possible to write code in a generic class that uses these operator. Only when the generic type is parameterized with types are the operators on those types checked for existence. If not present then errors of emitted.
    • addPublicMethod

      public MethodSymbol addPublicMethod(AggregateSymbol aggregate, String methodName, List<ISymbol> methodParameters, Optional<ISymbol> returnType)
      Just add a method to an aggregate with the name and parameters and return type. The methodParameters can be empty if there are none.
    • addEnumerationMethods

      public void addEnumerationMethods(AggregateSymbol enumerationSymbol)
      Adds all the appropriate methods for a type that is an 'Enumeration'. This allows a developer to use built-in methods on the 'Enumeration' type.
    • addPurePublicReturnSameTypeMethod

      public void addPurePublicReturnSameTypeMethod(IAggregateSymbol aggregate, String methodName)
    • createPurePublicReturnSameTypeMethod

      public MethodSymbol createPurePublicReturnSameTypeMethod(IAggregateSymbol aggregateSymbol, String methodName)
    • addMutatingVoidOperator

      public void addMutatingVoidOperator(IAggregateSymbol aggregate, String operatorName)
      Creates a public mutating operator that takes no arguments and returns void. Used for operators like ++ and -- that mutate the object in place.
    • createMutatingVoidOperator

      public MethodSymbol createMutatingVoidOperator(IAggregateSymbol aggregateSymbol, String operatorName)
      Creates a mutating void operator with no parameters.
    • addComparatorOperator

      public void addComparatorOperator(IAggregateSymbol aggregateSymbol, IAggregateSymbol arg0, String comparatorType, Optional<ISymbol> returnType)
      Adds a form of a comparison operator.
    • addComparatorOperator

      public MethodSymbol addComparatorOperator(IAggregateSymbol aggregateSymbol, String comparatorType, Optional<ISymbol> returnType)
      Adds a form of a comparison operator.
    • createPureAcceptSameTypeOperatorAndReturnType

      public MethodSymbol createPureAcceptSameTypeOperatorAndReturnType(IAggregateSymbol aggregateSymbol, String comparatorType, Optional<ISymbol> returnType)
      Creates a pure method with an argument the same as the main type.
    • createPureArgumentOperatorAndReturnType

      public MethodSymbol createPureArgumentOperatorAndReturnType(IAggregateSymbol aggregateSymbol, IAggregateSymbol arg0, String comparatorType, Optional<ISymbol> returnType)
      Creates a pure method with an argument of a different type as the main type.
    • addPurePublicSimpleOperator

      public MethodSymbol addPurePublicSimpleOperator(IAggregateSymbol aggregateSymbol, String methodName, Optional<ISymbol> returnType)
      Adds a simple operator, that is 'pure' (no side effects) and accepts no parameters, but just returns a value.
    • createPurePublicSimpleOperator

      public MethodSymbol createPurePublicSimpleOperator(IAggregateSymbol aggregateSymbol, String methodName, Optional<ISymbol> returnType)
      Just creates a public operator with the name specified.
    • createOperator

      public MethodSymbol createOperator(IAggregateSymbol aggregateSymbol, String operatorType, boolean isPure)
      Create an operator of the name supplied. The accepts a single argument of the same type as the aggregateSymbol It also returns a value that is the same as the aggregateSymbol.
    • createMutatorOperatorReturnVoid

      public MethodSymbol createMutatorOperatorReturnVoid(IAggregateSymbol aggregateSymbol, String operatorType)
      Create an operator of the name supplied. The accepts a single argument of the same type as the aggregateSymbol But it returns Void -i.e. has no return value.
    • createMutatorOperator

      public MethodSymbol createMutatorOperator(IAggregateSymbol aggregateSymbol, String operatorType)
      Create an operator of the name supplied. The accepts a single argument of the same type as the aggregateSymbol It also returns a value that is the same as the aggregateSymbol.
    • resolveVoid

      public Optional<ISymbol> resolveVoid(IScope scope)
      Resolve Void from cached ek9 types of full scope hierarchy resolution.
    • resolveBoolean

      public Optional<ISymbol> resolveBoolean(IScope scope)
      Resolve Boolean from cached ek9 types of full scope hierarchy resolution.
    • resolveInteger

      public Optional<ISymbol> resolveInteger(IScope scope)
      Resolve Integer from cached ek9 types of full scope hierarchy resolution.
    • resolveString

      public Optional<ISymbol> resolveString(IScope scope)
      Resolve String from cached ek9 types of full scope hierarchy resolution.
    • resolveJson

      public Optional<ISymbol> resolveJson(IScope scope)
      Resolve JSON from cached ek9 types of full scope hierarchy resolution.
    • resolveBits

      public Optional<ISymbol> resolveBits(IScope scope)
      Resolve Bits from cached ek9 types or full scope hierarchy resolution. Used for _fieldSetStatus() which returns a Bits value representing field set status.