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
9pub struct Engine<'a, 'b> {
11 vm: Vm<'a, EnginePrimitiveSet<'a, 'b>>,
12}
13
14impl<'a, 'b> Engine<'a, 'b> {
15 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 pub fn run<'c>(&mut self, module: &'c impl Module<'c>) -> Result<(), EngineError> {
31 block_on!(self.run_async(module))
32 }
33
34 #[cfg_attr(not(feature = "async"), doc(hidden))]
36 #[maybe_async]
37 pub fn run_async<'c>(&mut self, module: &'c impl Module<'c>) -> Result<(), EngineError> {
38 self.vm.initialize(module.bytecode().iter().copied())?;
39 maybe_await!(self.vm.run_async())
40 }
41
42 pub fn register_type<T: SchemeValue + 'static>(&mut self) {
50 self.vm
51 .primitive_set_mut()
52 .dynamic_mut()
53 .register_type::<T>()
54 }
55}