Output of one Engine run: the final working directory, the filesystem
handle the run executed against, and the top-level script variable
bindings captured at completion.
Execution state for one script run. Public so hosts can register
functions and introspect listings; all fields stay crate-private so the
scope, recursion-budget, and task invariants cannot be broken from outside.
Introspectable metadata for one function. Single source for
DESCRIBE(name) output and the static function reference. rpn names
whether the function also runs on the compiled math path (true for
pure functions and opted-in stateful ones); everything runs on the AST
path.
The single function registry: DSL FUNC definitions, builtins, and
host extensions share one lookup table, one metadata path, and one
dispatch order. Script entries scope lexically (defined names revert on
scope exit, shadowing an outer definition restores it); native entries
persist for the run. Shared across fork() via clone; the entry maps
clone while scope frames stay per state.
One host library: functions and types registered under a single module
name. Engine::register_module stages these; runs expose them as
MODULE::NAME calls with MODULE provenance on every entry.
Output of a lazily-executed run (issue #131): the final working directory
(concretized as of return), shared ownership of the snapshot backing dir,
and the filesystem handle for post-hoc convergence (e.g. concretizing the
cwd after shell-entry materialization).
Vtable for one type: lifecycle plus operations. All hooks are plain
function pointers (never closures) so descriptors stay Copy and the
global table hands them out by value. Every hook documents the payload
domain it expects; calling one with a foreign payload is unsound, and
every call site is a single choke point reviewed with the layout.
Origin of a callable in the unified function registry. Script is an
interpreted FUNC body; HostCtx and HostPure are compiled Rust
functions (the #[oxdock_func] host export macro). Builtins and
runtime-registered hosts share the host kinds; only DESCRIBE output
shows the label, and both host kinds keep rendering as host.
One host-registered function, grouped into a HostModule and passed
to Engine::register_module. Build the entry with the #[oxdock_func]-
generated registration marker, or by hand. Pure entries run
on both the AST and the compiled RPN math paths; Stateful entries run
on the AST path with full step context.
Display text emitted by CWD while the snapshot root is selected but not
yet materialized (issue #131). Single source of truth: the cwd handler
prints this value, and the logic-test harness resolves the same value
from @SNAPSHOT_PENDING@ fixture tokens.
Fallback tree body used when a materialized snapshot cannot be described
while composing a run error (issue #131). Single source of truth for the
lazy error path.
Export hook for a DSL function, implemented by #[oxdock_func] on a
registration marker. The engine calls registration() and never names
a generated symbol.
Export hook for a DSL payload type, implemented by #[oxdock_type] on
the payload struct itself. The canonical descriptor singleton backs
every word of the type; user code never names a generated symbol.
Metadata of every builtin function, sorted by name, for static
rendering (docs-gen). Same single source as builtin_function_names:
the #[oxdock_func] annotations, never a parallel list.
Names of all compiled-in builtins plus INSPECT (a dedicated AST/RPN
node, not a registry entry). Read straight off a stock registry, so the
#[oxdock_func] annotations stay the single source of truth: adding a
builtin extends this set with no parallel list to update. Seeds
parse-time shadow validation, so the parser crate keeps zero
compile-time knowledge of builtin names.
Error enrichment for lazy runs: a materialized snapshot gets the same
filesystem-snapshot treatment as eager runs; a pending one reports that
no snapshot directory was ever created instead of describing a tree.
Chain rendering is identical to the eager path (shared composer).
Execute the DSL against a lazily-created snapshot: no temporary directory
exists until the first snapshot-targeted resolution. The snapshot handle
is shared with the resolver, so all clones observe the same directory.
Host introspection entry point: execute the DSL against a caller-provided
filesystem and return the final working directory, the filesystem handle,
and the top-level script variable bindings captured at Flow::Done.
Bindings are read from the root variable scope only, so ephemeral
variables from FUNC bodies, FOR/WHILE iterations, and ASYNC blocks
are excluded. On script failure the scope is discarded with the error and
no bindings are returned.
Same as run_steps_with_manager, plus host modules and types. Each
module’s functions become callable as MODULE::NAME with full step
context; each type descriptor becomes visible to TYPES() and valid for
LET $x: NAME declarations carrying same-named opaque payloads.
Authors should derive entries with #[oxdock_func] / #[oxdock_type]
(see oxdock-func-macro) and group them into HostModule instead of
hand-writing metadata and glue.
Canonical descriptors of the ten startup types, in a fixed order, for
seeding per-state name directories and static rendering (docs-gen).
Each entry is the payload struct’s own singleton: no table, no lock.
Stock STD module table derived from the #[oxdock_func] builtins:
the single source of truth for builtin membership and RPN eligibility.
Seeds parse-time module resolution, so the parser crate keeps zero
compile-time knowledge of builtin names.
Inline unshare: inline words hold bytes, not a heap buffer, so there
is nothing to hand out mutably. Panics: reaching this hook means
Value::read_heap_mut was called with an inline descriptor, a caller
bug (mirrors store_inline’s size assert).
Shared-heap unshare: detach on write. When the strong count is 1 the
payload is returned unchanged (in-place, no allocation); otherwise the
buffer is cloned, the word is rewritten to the private buffer, and the
other clones keep the original. Either way the returned pointer addresses
a buffer this word uniquely owns.
Payload half of a Value word: either the value’s bytes inline or a
thin pointer to an owned Box<T> (exclusive heaps) or a shared Arc<T>
(shared heaps), as the type’s descriptor dictates.
Inline and pointer domains never mix for a given TypeDescriptor.