mod error;
mod primitive;
pub use self::{error::PrimitiveError, primitive::Primitive};
use crate::Device;
use stak_vm::{Heap, Memory, Number, PrimitiveSet};
use winter_maybe_async::{maybe_async, maybe_await};
pub struct DevicePrimitiveSet<T: Device> {
device: T,
}
impl<T: Device> DevicePrimitiveSet<T> {
pub const fn new(device: T) -> Self {
Self { device }
}
pub const fn device(&self) -> &T {
&self.device
}
pub const fn device_mut(&mut self) -> &mut T {
&mut self.device
}
}
impl<T: Device, H: Heap> PrimitiveSet<H> for DevicePrimitiveSet<T> {
type Error = PrimitiveError;
#[maybe_async]
fn operate(&mut self, memory: &mut Memory<H>, primitive: usize) -> Result<(), Self::Error> {
match primitive {
Primitive::READ => {
let byte =
maybe_await!(self.device.read()).map_err(|_| PrimitiveError::ReadInput)?;
memory.push(if let Some(byte) = byte {
Number::from_i64(byte as _).into()
} else {
memory.boolean(false)?.into()
})?;
}
Primitive::WRITE => {
let byte = memory.pop()?.assume_number().to_i64() as u8;
maybe_await!(self.device.write(byte)).map_err(|_| PrimitiveError::WriteOutput)?;
memory.push(memory.boolean(false)?.into())?;
}
Primitive::WRITE_ERROR => {
let byte = memory.pop()?.assume_number().to_i64() as u8;
maybe_await!(self.device.write_error(byte))
.map_err(|_| PrimitiveError::WriteError)?;
memory.push(memory.boolean(false)?.into())?;
}
_ => return Err(stak_vm::Error::IllegalPrimitive.into()),
}
Ok(())
}
}