stak_engine/
engine.rs

1use crate::{EngineError, primitive_set::EnginePrimitiveSet};
2use any_fn::AnyFn;
3use stak_dynamic::SchemeValue;
4use stak_module::Module;
5use stak_util::block_on;
6use stak_vm::{Error, Value, Vm};
7use winter_maybe_async::{maybe_async, maybe_await};
8
9/// A scripting engine.
10pub struct Engine<'a, 'b> {
11    vm: Vm<'a, EnginePrimitiveSet<'a, 'b>>,
12}
13
14impl<'a, 'b> Engine<'a, 'b> {
15    /// Creates a scripting engine.
16    pub fn new(
17        heap: &'a mut [Value],
18        functions: &'a mut [(&'a str, AnyFn<'b>)],
19    ) -> Result<Self, Error> {
20        Ok(Self {
21            vm: Vm::new(heap, EnginePrimitiveSet::new(functions))?,
22        })
23    }
24
25    /// Runs a module synchronously.
26    ///
27    /// # Panics
28    ///
29    /// Panics if asynchronous operations occur during the run.
30    pub fn run_sync<'c>(&mut self, module: &'c impl Module<'c>) -> Result<(), EngineError> {
31        block_on!(self.run(module))
32    }
33
34    /// Runs a module.
35    #[maybe_async]
36    pub fn run<'c>(&mut self, module: &'c impl Module<'c>) -> Result<(), EngineError> {
37        self.vm.initialize(module.bytecode().iter().copied())?;
38        maybe_await!(self.vm.run())
39    }
40
41    /// Registers a type compatible between Scheme and Rust.
42    ///
43    /// We register all types that this crate implements [`SchemeValue`] for to
44    /// the engines by default.
45    ///
46    /// For more information, see
47    /// [`DynamicPrimitiveSet`][stak_dynamic::DynamicPrimitiveSet].
48    pub fn register_type<T: SchemeValue + 'static>(&mut self) {
49        self.vm
50            .primitive_set_mut()
51            .dynamic_mut()
52            .register_type::<T>()
53    }
54}