stak-engine 0.12.20

Stak Scheme scripting engine for Rust
Documentation
use crate::EngineError;
use any_fn::AnyFn;
use stak_dynamic::DynamicPrimitiveSet;
use stak_file::VoidFileSystem;
use stak_process_context::VoidProcessContext;
use stak_r7rs::SmallPrimitiveSet;
use stak_time::VoidClock;
use stak_vm::{Heap, Memory, PrimitiveSet};
use winter_maybe_async::{maybe_async, maybe_await};

const DYNAMIC_PRIMITIVE_OFFSET: usize = 1000;

cfg_select! {
    feature = "std" => {
        type Device = stak_device::StdioDevice;
    }
    feature = "libc" => {
        type Device = stak_device::LibcDevice;
    }
    _ => {
        type Device = stak_device::VoidDevice;
    }
}

/// A type check primitive set.
pub struct EnginePrimitiveSet<'a, 'b, H> {
    small: SmallPrimitiveSet<Device, VoidFileSystem, VoidProcessContext, VoidClock>,
    dynamic: DynamicPrimitiveSet<'a, 'b, H>,
}

impl<'a, 'b, H: Heap> EnginePrimitiveSet<'a, 'b, H> {
    /// Creates a primitive set.
    pub fn new(functions: &'a mut [(&'a str, AnyFn<'b>)]) -> Self {
        Self {
            small: SmallPrimitiveSet::new(
                Default::default(),
                Default::default(),
                Default::default(),
                Default::default(),
            ),
            dynamic: DynamicPrimitiveSet::new(functions),
        }
    }

    pub(crate) const fn dynamic_mut(&mut self) -> &mut DynamicPrimitiveSet<'a, 'b, H> {
        &mut self.dynamic
    }
}

impl<H: Heap> PrimitiveSet<H> for EnginePrimitiveSet<'_, '_, H> {
    type Error = EngineError;

    #[maybe_async]
    fn operate(&mut self, memory: &mut Memory<H>, primitive: usize) -> Result<(), Self::Error> {
        if primitive >= DYNAMIC_PRIMITIVE_OFFSET {
            maybe_await!(
                self.dynamic
                    .operate(memory, primitive - DYNAMIC_PRIMITIVE_OFFSET)
            )?
        } else {
            maybe_await!(self.small.operate(memory, primitive))?
        }

        Ok(())
    }
}