Class InheritedDispatcher

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

public final class InheritedDispatcher extends Object
THE rule for a sub-type that adds handlers to a dispatcher it inherits (front-end rationalisation D2, Steve 2026-10-02: "we have little choice but to do 'A'").

A base declares the single entry point render() as dispatcher -> shape as Shape and is open by design; a sub-type adds render() -> triangle as Triangle. That is the least a person or an AI should have to write, and the intent is plain: Triangles go to the new handler, whatever the static type of the receiver. So the sub-type is given a SYNTHESISED override of the entry point, marked as a dispatcher: phase 7 gives it a dispatch table over the handlers of the whole chain (DispatcherHandlers.collectFor(IAggregateSymbol, MethodSymbol)) and a body that calls the super's entry point - which dispatches over its own handlers and, at the top, runs the fallback the author wrote. Every phase-3 and phase-5 dispatcher check then runs on the sub-type too (a handler outside the hierarchy, an unreachable one).

Before this the sub-type's handler compiled, was checked by nothing, and was never dispatched to: the base's table covered only the base's handlers, so a Triangle reached the base's fallback.

Only for a NEW handler - a signature no super has. A sub-type that only overrides an existing handler needs nothing: the base's table calls that handler virtually, so the override is reached. A sub-type that overrides the entry point itself (override render() as dispatcher) supplies its own fallback, and is left alone.

  • Method Details

    • isSynthesised

      public static boolean isSynthesised(MethodSymbol method)
      True if this entry point was synthesised by completeFor(AggregateSymbol).
    • overriddenEntryPoint

      public static Optional<MethodSymbol> overriddenEntryPoint(IAggregateSymbol aggregate, MethodSymbol entryPoint)
      The super's entry point that a sub-type's entry point overrides: the super's effective dispatcher method with exactly the same signature.
    • completeFor

      public static void completeFor(AggregateSymbol aggregate)
      Give the aggregate a synthesised override of each inherited entry point it adds a new handler for. Its supers must already have been completed, so an entry point synthesised on a middle type is inherited by the types below it.

      DEFENSIVE: this runs at the end of EXPLICIT_TYPE_SYMBOL_DEFINITION, BEFORE TYPE_HIERARCHY_CHECKS reports a hierarchy loop - and every getAll...Methods() recurses up the hierarchy unguarded. So a cheap guarded pre-check runs first (does this type declare a candidate handler, and does a super declare a dispatcher of that name?), which is also what keeps the cost near zero for the great majority of types; and the hierarchy must be loop-free before anything walks it. An unresolved super or parameter type simply finds nothing to do.