Context Internals
The runtime data stack is:
ProcessContextSubContextSubContextView
1. ProcessContext
ProcessContext{D,Reg} holds (src/Context/StructDefs.jl):
subcontexts::D: named tuple of subcontexts plusglobals.registry::Reg: aNameSpaceRegistryused for static routing and lookup.
Access patterns (src/Context/ProcessContexts.jl):
pc[:name]orpc.nameby subcontext symbol.pc[obj]by algorithm/state value/type (resolved through registry key).
globals is a regular field in subcontexts; runtime code injects process-level values there (like process, lifetime, algo).
2. SubContext
SubContext{Name,Data} stores (src/Context/StructDefs.jl):
data::NamedTuple: local variables owned by that entity.
Initialization builds empty SubContexts for every registry key, then fills them by init.
Route/share metadata is deliberately not stored on SubContext. Plan routing is resolved into step-local StepRouting values and attached to SubContextView types while a child runs. This keeps persistent context shape independent from execution-plan wiring.
3. SubContextView
step!, init, and cleanup run against a SubContextView (src/Context/View/StructDef.jl).
A view carries:
- the full context,
- the current identifiable instance,
- optionally injected locals.
- route/share metadata for the current step, as type parameters.
Property access is generated through VarLocations (src/Context/View/Locations.jl):
- local vars,
- shared-context vars from the current step routing,
- routed vars from the current step routing,
- injected vars.
Name precedence for reads is determined by NamedTuple merge order. Later groups override earlier groups:
- injected vars
- local vars
- routed vars
- shared vars
This means local and injected names override route/share names on collisions.
4. Merging and Replacing
merge(view, namedtuple) (src/GeneratedCode/SubContextView.jl) maps return names back to concrete target subcontexts and variables.
- Existing mapped variable: update that mapped target.
- Unknown variable: added to the current local subcontext.
replace(view, (;SubKey => nt)) replaces the full subcontext and is used during init.
merge_into_subcontexts (src/Context/ProcessContexts.jl) enforces that subcontext structure remains valid.
A type-change guard in generated merge asserts the new ProcessContext type stays identical, preventing accidental type instability.