navigation
navigation
#
The fluent navigation and cache-assignment operators bound onto Procedure.
Navigating a procedure descends its return type one step: attribute access reads a
struct field, indexing selects an array element (int) or a map entry (key), and
.keys() / .values() enumerate a map. The same operators work whether the
return type is a Path[…] (each step yields a deeper Path) or a plain value
(each step yields the child value) — [.dispatch][] is the table that decides,
so every operator here is just classify → guard → build.
Assignment caches: path |= value (skip if exists) and path &= value
(overwrite) each record a CacheProcedure wrapped in a RequiredProcedure
(so the stored value is a kept Void step) and return the CacheProcedure so
the slot reads back as its value type.
These functions are imported into the Procedure class body, so every import
here is lazy (the node and dispatch layers import Procedure back). The
recorded sequence is owned by the active
ProcedureContext,
not by any per-node bookkeeping here.
__getitem__(self, key)
#
__getitem__(
self: Procedure[Array],
key: int
| Procedure[CGType]
| JSONScalar
| bool
| float
| str,
) -> Procedure[CGType]
Index a navigable position or a value-access array / map.
On a navigated Path it selects an array element / map entry position
(another Path). On a map value a node returns it selects the entry's
value (MapKey); on the Array that a map's keys()/values()
returns it selects the element value — a key scalar, or a Path[V] to
navigate. The runtime dispatches all of these through the same navigable view.
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
__iand__(self, value)
#
path &= value — cache the value, overwriting any stored value.
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
__ior__(self, value)
#
path |= value — cache the value, skipping if already stored.
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
__setitem__(self, key, value)
#
Absorb the arr[i] |= value / map[k] &= value rebind.
arr[i] |= value desugars to arr.__setitem__(i, arr[i].__ior__(value));
the cache was already recorded by __ior__, so this swallows it — but only
when it is this exact slot's own cache (its destination is the navigation
child for key), mirroring the strict struct-field __setattr__ guard. A
plain arr[i] = value, or a cache built for a different slot, is rejected.
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
exists(self)
#
path.exists() — a Bool that is true when a value is stored here.
Reads the position from disk (LoadPath) and reports whether that read
completes (ProcedureCompleted), so a missing value yields false instead
of aborting the run. Pair it with cg.when(...) to run a block only once the
position has been written. The read goes to disk regardless of any value cached
at this slot this run, so it tests what was already present before the run.
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
keys(self)
#
A map position's keys as a read-only Array[K] value (index to select one).
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
load(self)
#
path.load() — read the value stored at this position.
Loading is explicit: an unwritten position used as a value never lowers to a disk read on its own. The read waits for a stored value (a prior run's, or one an interceptor fills); while nothing is stored it stays pending, so use [load_or][] when an absent value should produce a fallback instead. The read goes to disk regardless of any value cached at this slot this run, so it sees what was already present before the run.
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
load_or(self, default)
#
path.load_or(default) — the stored value, or default's value.
Returned when nothing is stored here. The fallback runs only on a definitive
"nothing stored" answer — never while the value is still loading — so a slow
remote read cannot be mistaken for an absent one. default is a procedure (or
raw literal) whose type matches the position's — so a typed default names the
result's type, and the compile-time validation pass enforces the match.
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
memoized_child(parent, key, factory)
#
The parent's navigation child for key, built once.
Dedup is node-local: each node remembers its own children, so repeated
navigation to the same slot returns the same node — which is what carries
_assigned_value — with no central bookkeeping. A non-empty _children
also marks a path slot a container, so saving a value there is rejected.
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
navigate(self, name)
#
Read a struct field; bound as Procedure.__getattr__.
E.g. root.reference, CapturePanorama().preview. Only missing attributes
reach here, and dunders never navigate.
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
record_cache(position, value, *, skip_if_exists)
#
Record a cache at position and return it, typed as its value T.
Builds the CacheProcedure, wraps it in a RequiredProcedure (so the
stored value is a Void step the context keeps, with the cache as its
caught child), and records the assignment on the slot for read-back. A slot
that has been navigated into (non-empty _children) is a container, and one
already assigned cannot be assigned again.
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
require_map_position(node, op)
#
Guard .keys() / .values(): both enumerate a Path[Map] position.
A captured map value supports [key] indexing only.
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
require_no_saved_value(node)
#
Guard descending into a path position.
A slot is a value or a container, not both, so a slot with a saved value has no children.
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
string_literal(key)
#
A constant string key as a plain str, or None if it can't be one.
Accepts a raw str or a String value; returns None when the key is
computed and so can't be checked statically.
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
subscript_child(node, nav, key, *, create)
#
Resolve node[key] — an array element (int) or a map entry (key value).
With create set this builds and memoizes the child; otherwise it only looks
up an already-built one (so __setitem__ can match a slot's own cache
without re-navigating an already-saved position).
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
values(self)
#
A map position's entry positions as Array[Path[V]].
Fan out, or index to select one to navigate.
Source code in capturegraph-lib/capturegraph/procedures/procedure/methods/navigation.py
warn_unknown_map_key(source, key)
#
Warn when a value-level map[key] names a key the source map provably lacks.
Only a node that advertises its keys (static_map_keys) with a literal key is
checked; a dynamic source or computed key is left alone. The access still
builds — at runtime it yields no value, and the client reports the unknown key.