ek9_query_dispatchers

Answers first: routing[] - per dispatcher method its dispatchOn type, typesWithOwnHandler, typesUsingInheritedHandler (served by a supertype's handler) and typesFallingBack (to the dispatchOn entry point's own body), with routingCovers when the lists are whole - then the full dispatcherMethods[] with resolutionTable; on a sealed type, allowedSubtypes[]. Do not read the class and simulate it.

Category: Enquiry

When to use it

How does a dispatcher method route - which subtypes have their OWN handler and which fall back to the base handler - one call with symbol:'<dispatcher class>'. No file needed; on a sealed type, its allowed subtypes.

When not to use it

Details

Auto-detected (no 'mode' parameter): routing[] is present for a dispatcher, allowedSubtypes[] for a sealed type, and a type that is neither returns dispatcher:'not_applicable' with a message (or 'not_found' when there is no enclosing type at the anchor). Dispatcher shape: dispatcherMethods[] + dispatcherMethodCount - drawn from the FULL inheritance chain, so an entry point or handler declared in a supertype is included - each method with signature, pure, dispatchType(+Fqn), allowedSubtypes[] when the dispatch parameter type is sealed, and handlers[] (handlesType and routedTypes per handler), plus top-level sealedTypeDispatched (the FQ sealed supertype handled). ROUTING (present when the workspace is compiled): resolutionTable[] has one row per concrete type that can arrive - typeName, typeGenus, category DIRECT (handler names this exact type) / INHERITED (won via a supertype, with resolvedVia and cost) / ENTRY (the dispatch type itself, when it is concrete - served by the entry point, not a gap) / FALLBACK (no handler; the entry point's own body runs) - plus totalTypes, directCount and inheritedCount. dispatchUniverse says how far to trust the gap analysis: 'sealed' (closed by the compiler, gaps provable), 'hierarchy' (a trait / abstract class / abstract function base - gaps real but a snapshot, since another implementor may be declared later), or 'open' (an Any base). For sealed and hierarchy you also get fallbackCount, unhandledTypes[] (the FALLBACK rows - routing[].typesFallingBack is the same list) and exhaustive, and routing[].routingCovers says the lists are whole. For 'open' those are DELIBERATELY ABSENT and a note explains why: an Any base admits every type in the program and every type not yet written, so 'types you did not handle' has no fixed answer and a fallbackCount of 0 would read as a false all-clear. Sealed shape: allowedSubtypes[] (simple-name strings) + subtypeCount. Note a class is reported as a dispatcher only when it has a NON-OPERATOR entry point: argument-taking operators such as '==' are marked as dispatchers internally so they resolve on the actual type, and that is not a user-level dispatcher.

Arguments

ArgumentTypeRequiredWhat it is
amongarray of stringNames to answer FOR: 'which of these ...' - the name lists shrink to these and amongUnmatched names the ones that are not in the answer. Bare names, 'mod::Type' or 'Type.member'; a MODULE name stands for every construct in it ('which in scale.m07 do not ...' = amongUnmatched).
columninteger0-based char offset of the target identifier on 'line' (an IDE cursor). OMIT it and pass symbol:'<name>' instead, or omit both and the first identifier on the line is taken (right for a declaration line). Reuse a column from ek9_inspect_symbol_at_cursor verbatim.
filestringThe EK9 source file - OPTIONAL when symbol is a construct name; required to anchor on a member or a use site.
lineinteger1-based line of the declaration or a reference - OMIT it and pass symbol:'<name>' to let the tool find the line (a model counting lines in a file miscounts); if you do count, use ek9_read_file(lineNumbers:true).
symbolstringA construct NAME alone ('Shape', 'sample.deps.core::Validator') - no file needed, the tool finds it workspace-wide; or, with file (+ line), the identifier you mean there.

Recorded calls

Real calls, recorded against small projects and checked on every build - a changed answer fails it. 3 of the 4 recorded are shown.

Not a dispatcher status

Request

{
  "symbol" : "Circle"
}

Response

{
  "fullyQualifiedName" : "probe.wire::Circle",
  "genus" : "CLASS",
  "meta" : {
    "serverMs" : "<timing>"
  },
  "note" : "Type is not sealed and not a dispatcher",
  "status" : "not-applicable",
  "type" : "Circle",
  "typeLine" : 10,
  "typeSourceFile" : "wire.ek9"
}

Dispatchers shape

Request

{
  "file" : "MyRecord.ek9",
  "line" : 5
}

Response

{
  "fullyQualifiedName" : "com.example::MyRecord",
  "genus" : "RECORD",
  "meta" : {
    "serverMs" : "<timing>"
  },
  "note" : "Type is neither a dispatcher nor a sealed type",
  "status" : "not-applicable",
  "type" : "MyRecord",
  "typeLine" : 5,
  "typeSourceFile" : "MyRecord.ek9"
}

Any base routing

Request

{
  "symbol" : "AnyRenderer"
}

Response

{
  "dispatcherMethodCount" : 1,
  "dispatcherMethods" : [ {
    "directCount" : 1,
    "dispatchType" : "Any",
    "dispatchTypeFqn" : "org.ek9.lang::Any",
    "dispatchTypeLine" : 6,
    "dispatchTypeSourceFile" : "org-ek9-lang.ek9",
    "dispatchUniverse" : "open",
    "entryLine" : 10,
    "entrySourceFile" : "anyBase.ek9",
    "handlers" : [ {
      "handlerLine" : 14,
      "handlerSourceFile" : "anyBase.ek9",
      "handlesType" : "Circle",
      "handlesTypeFqn" : "probe.anybase::Circle",
      "handlesTypeLine" : 6,
      "handlesTypeSourceFile" : "anyBase.ek9",
      "name" : "render",
      "routedTypes" : [ "Circle" ]
    } ],
    "inheritedCount" : 0,
    "method" : "render",
    "name" : "render",
...

Cut short here: 37 more lines. The whole recorded call.

See also