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.
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.
Value-model re-exports: the word, its payload, type descriptors, and the
export hook live in crate::value, the single representation for
every type.
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.
Export hook for a DSL function, implemented by #[oxdock_func] on a
registration marker. The engine calls registration() and never names
a generated symbol.
Value-model re-exports: the word, its payload, type descriptors, and the
export hook live in crate::value, the single representation for
every type.
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.
Build the run’s endpoint registry from CLI flags and bind every mapped
socket now: callers run this before parsing so bind conflicts fail
fast, never parse-then-fail-on-bind.
Parse a script using the production lower_command dispatcher.
The typed ParseError converts into anyhow::Error at this boundary
with no intermediate .context() wrapping, so the message survives.
Builtin function names seed the reserved set, so FUNC shadowing a
native fails here; hosts unknown at parse time fall back to the runtime
define_func guard.
Parse with a module provenance table so calls resolve statically:
qualified MODULE::NAME checks membership, bare NAME resolves through
SCRIPT definitions and IMPORTed modules. Reserved covers builtins
plus every table module, so FUNC shadowing any of them fails here;
hosts unknown at parse time fall back to the runtime define_func
guard.
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.