pub trait ScriptHost:
Send
+ Sync
+ 'static {
type Closure: Clone + Send + Sync + 'static;
const FILLS_COMPONENTS: bool = false;
Show 22 methods
// Required methods
fn compile_check(&self, source: &str, uri: &str) -> Result<(), ScriptError>;
fn load(&mut self, source: &str, uri: &str) -> Result<(), ScriptError>;
fn replace(&mut self, source: &str, uri: &str) -> Result<(), ScriptError>;
fn reset(&mut self);
fn call(
&mut self,
fn_name: &str,
args: &[ScriptValue],
) -> Result<CallOutcome, CallFailure>;
fn call_closure(
&mut self,
closure: &Self::Closure,
args: &[ScriptValue],
) -> Result<ScriptValue, ScriptError>;
fn register_script_fn(&mut self, f: &ScriptFn) -> Result<(), ScriptError>;
fn lang(&self) -> &'static str;
// Provided methods
fn eval_derivation(
&mut self,
closure: &Self::Closure,
deps: &[String],
name: &str,
) -> Result<String, ScriptError> { ... }
fn drain_commands(&mut self) -> Vec<ScriptCommand> { ... }
fn push_commands(&mut self, cmds: Vec<ScriptCommand>) { ... }
fn mirror_get(&self, name: &str) -> Option<ScriptValue> { ... }
fn mirror_set(&mut self, name: &str, value: ScriptValue) { ... }
fn mirror_sync_str(&mut self, name: &str, value: &str) { ... }
fn handler_for(&self, event: &str, key: &str) -> Option<String> { ... }
fn derivations_matching(
&self,
dirty: &HashSet<&str>,
pending: &HashSet<String>,
) -> Vec<(String, Vec<String>, Self::Closure)> { ... }
fn pending_initial(&self) -> HashSet<String> { ... }
fn clear_pending(&mut self, evaluated: &[String]) { ... }
fn dispatch_event_handler(
&mut self,
token: u64,
) -> Result<bool, ScriptError> { ... }
fn drop_event_handler(&mut self, token: u64) { ... }
fn add_prelude(&mut self, ns: &str, source: &str) { ... }
fn builtins(&self) -> &'static [BuiltinFn] { ... }
}Expand description
Backend that compiles + executes scripts and exposes the host-neutral
registries the generic runtime (lumen-script) drives: the
command sink, the rich-typed signal mirror, the per-id handler
registry, and the derivation registry.
Send + Sync bound: hosts sit in a plain bevy Resource and
participate in parallel scheduling. A host that cannot be Send needs a
NonSend variant of the install path.
One script-side callable the generic runtime can re-invoke is modeled
by Self::Closure - Rhai: FnPtr; candela: a function handle once its
embedding API lands.
Provided Associated Constants§
Sourceconst FILLS_COMPONENTS: bool = false
const FILLS_COMPONENTS: bool = false
Whether this host is the one a component marker in the tree names a function in.
A marker is what the build leaves where a component has to run, and markup blocks are one language’s macro, so exactly one host answers for them. Every other host leaves a marker alone rather than reporting a function it was never going to have.
Required Associated Types§
Required Methods§
Sourcefn compile_check(&self, source: &str, uri: &str) -> Result<(), ScriptError>
fn compile_check(&self, source: &str, uri: &str) -> Result<(), ScriptError>
Compile-only, side-effect free, with the exact engine settings
Self::load uses - lumenc check and run must agree on what
parses. uri seeds ScriptError::Compile::uri.
Sourcefn load(&mut self, source: &str, uri: &str) -> Result<(), ScriptError>
fn load(&mut self, source: &str, uri: &str) -> Result<(), ScriptError>
Compile + evaluate the top level into persistent state. Fresh-start load; replaces any previously loaded program.
Sourcefn replace(&mut self, source: &str, uri: &str) -> Result<(), ScriptError>
fn replace(&mut self, source: &str, uri: &str) -> Result<(), ScriptError>
Hot reload: compile first (no state touched on a parse error), then swap atomically. Snapshot the registries, clear them, re-evaluate the top level into the existing persistent scope, and roll the snapshot back in full if that evaluation fails. Persistent across the swap: engine registrations, scope bindings, the signal mirror, and the in-flight command sink.
On success the snapshot is merged back under whatever the new top
level registered, via carry_forward. Lifecycle callbacks do not
re-fire on reload, so a handler an app bound from on_start has no
second chance to register itself; without the merge every such handler
would go quiet after the first reload.
Sourcefn reset(&mut self)
fn reset(&mut self)
Drop the loaded program and all persistent state. Genuine
restart; hot reload should use Self::replace.
Sourcefn call(
&mut self,
fn_name: &str,
args: &[ScriptValue],
) -> Result<CallOutcome, CallFailure>
fn call( &mut self, fn_name: &str, args: &[ScriptValue], ) -> Result<CallOutcome, CallFailure>
Call a script function by name. A missing function is silent
success (found: false); see CallOutcome. A function that raises
returns CallFailure, which still carries the commands it queued
before the error.
Sourcefn call_closure(
&mut self,
closure: &Self::Closure,
args: &[ScriptValue],
) -> Result<ScriptValue, ScriptError>
fn call_closure( &mut self, closure: &Self::Closure, args: &[ScriptValue], ) -> Result<ScriptValue, ScriptError>
Re-entrant closure invocation. Must be callable while the generic runtime holds NO host locks (snapshot-then-call pattern): the closure body may re-enter builtins that touch the sink / mirror.
Sourcefn register_script_fn(&mut self, f: &ScriptFn) -> Result<(), ScriptError>
fn register_script_fn(&mut self, f: &ScriptFn) -> Result<(), ScriptError>
Bind one ScriptFn so the script can call it.
The host maps ScriptNs onto its own name space, binds the
signature’s arity range, and retains f in a ScriptFnStore so
Self::reset can put it back. A host’s own engine accessors
remain available for anything this shape cannot express.
§Errors
The host could not bind the function: its binding window has closed (candela binds host declarations when the artifact loads) or the engine rejected the registration.
Provided Methods§
Sourcefn eval_derivation(
&mut self,
closure: &Self::Closure,
deps: &[String],
name: &str,
) -> Result<String, ScriptError>
fn eval_derivation( &mut self, closure: &Self::Closure, deps: &[String], name: &str, ) -> Result<String, ScriptError>
Evaluate one derivation: read the dep values, invoke closure,
store the rich result into the mirror under name, and return
the host-canonical stringification for the ECS property store.
Deviation from the original v2 sketch (documented in the design
doc section 1.9): the default impl composes mirror_get -> call_closure
-> mirror_set -> ScriptValue::stringify, but hosts should
override with a native path - round-tripping dep values through
ScriptValue loses fidelity for host-native structured values,
and stringification is host-canonical (Rhai renders 1.0 where
Rust’s f64 Display renders 1; store strings feed bind-text
and the parse-back policy, so the host must own the format).
Sourcefn drain_commands(&mut self) -> Vec<ScriptCommand>
fn drain_commands(&mut self) -> Vec<ScriptCommand>
Drain commands queued by builtins since the last drain. Default: a host with no command sink has nothing to drain.
Sourcefn push_commands(&mut self, cmds: Vec<ScriptCommand>)
fn push_commands(&mut self, cmds: Vec<ScriptCommand>)
Put commands back into the sink so they flow through the next
tick’s normal drain (the on_start re-stash). Default: dropped.
Sourcefn mirror_get(&self, name: &str) -> Option<ScriptValue>
fn mirror_get(&self, name: &str) -> Option<ScriptValue>
Read a mirror entry. None => never written. Default: no mirror.
Sourcefn mirror_set(&mut self, name: &str, value: ScriptValue)
fn mirror_set(&mut self, name: &str, value: ScriptValue)
Write a mirror entry (host-native conversion of value). Default:
no mirror, so the write is dropped.
Sourcefn mirror_sync_str(&mut self, name: &str, value: &str)
fn mirror_sync_str(&mut self, name: &str, value: &str)
section 1.3 type-preserving parse-back of a store string. The trait pins the POLICY: a mirror entry currently holding a scalar (bool / int / float) parses the string back into that SAME type; structured mirror values (arrays, maps) stay authoritative and ignore the string; unparseable strings leave the mirror untouched; absent / string entries take the store string verbatim. Default: no mirror.
Sourcefn handler_for(&self, event: &str, key: &str) -> Option<String>
fn handler_for(&self, event: &str, key: &str) -> Option<String>
Per-id handler lookup (on(event, id, fn)), including the
template-suffix fallback: a handler registered for save also
matches user-card:save via the last-: suffix. Default: no
handler registry.
Sourcefn derivations_matching(
&self,
dirty: &HashSet<&str>,
pending: &HashSet<String>,
) -> Vec<(String, Vec<String>, Self::Closure)>
fn derivations_matching( &self, dirty: &HashSet<&str>, pending: &HashSet<String>, ) -> Vec<(String, Vec<String>, Self::Closure)>
Snapshot of derivations matching dirty plus pending
(name, deps, closure) - taken OUTSIDE any host lock so the
driver can invoke closures re-entrantly. Default: no derivation
registry.
Sourcefn pending_initial(&self) -> HashSet<String>
fn pending_initial(&self) -> HashSet<String>
Names of derivations registered but never successfully evaluated; they all run on the next derivation pass regardless of dirt. Default: none.
Sourcefn clear_pending(&mut self, evaluated: &[String])
fn clear_pending(&mut self, evaluated: &[String])
Remove successfully-evaluated names from the pending-initial set. Erroring derivations stay pending and retry next tick. Default: no-op.
Sourcefn dispatch_event_handler(&mut self, token: u64) -> Result<bool, ScriptError>
fn dispatch_event_handler(&mut self, token: u64) -> Result<bool, ScriptError>
Invoke the event-handler closure the host registered under token
(via its on(node, type, handler) builtin). The host builds its
native event object, which reads the process-global current-event
cell (crate::event); commands the handler queues are drained via
Self::drain_commands afterwards by the caller. Returns whether a
closure was found and run.
Default: not supported (no closure registry) -> Ok(false). Hosts
that expose on(...) with real closures override this.
Sourcefn drop_event_handler(&mut self, token: u64)
fn drop_event_handler(&mut self, token: u64)
Drop the event-handler closure registered under token (the host
side of off() / UnbindEvent). Default: no-op.
Sourcefn add_prelude(&mut self, ns: &str, source: &str)
fn add_prelude(&mut self, ns: &str, source: &str)
Take source a plugin ships alongside the functions it registered under
ns, to be compiled ahead of the app’s own program.
This is how a plugin offers sugar over its functions: a struct and an
impl block in this host’s own language, so a script calls
pin(21).level() instead of the free function. The registry hands a
host only the sources written in its language.
A host that cannot stage source says so rather than dropping it, which is what the default does.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.