diff options
| author | Sophie Forrest <git@sophieforrest.com> | 2024-08-30 23:35:45 +1200 |
|---|---|---|
| committer | Sophie Forrest <git@sophieforrest.com> | 2024-08-30 23:35:45 +1200 |
| commit | 3c163eabc78ddbd26bb250ef5ad6da28cd61adc6 (patch) | |
| tree | 58e17534e1db18813554d4fb6e67020f898b655d /src/executor.rs | |
| parent | 17b78f8cb127817b93f7e6ced7e55d8748806a80 (diff) | |
feat: split engine into crates
Diffstat (limited to 'src/executor.rs')
| -rw-r--r-- | src/executor.rs | 131 |
1 files changed, 0 insertions, 131 deletions
diff --git a/src/executor.rs b/src/executor.rs deleted file mode 100644 index c5fff93..0000000 --- a/src/executor.rs +++ /dev/null @@ -1,131 +0,0 @@ -//! Executor implementation for Brainfuck. - -use miette::Diagnostic; -use num_traits::{One, WrappingAdd, WrappingSub, Zero}; -use thiserror::Error; - -use crate::{engine::Engine, parser::Instruction}; - -/// Runtime errors that can occur in brainfuck executor. -#[derive(Debug, Diagnostic, Error)] -pub enum Error { - /// Brainfuck engine ran into an error at runtime. - #[error(transparent)] - Engine(#[from] crate::engine::Error), - - /// Brainfuck code performed an out of bounds index on the tape during - /// runtime. - #[error("tape indexed out of bounds, attempted index at `{0}`")] - IndexOutOfBounds(usize), -} - -/// Struct for executor implementation, allows u8 Engine to be implemented. -#[derive(Clone, Copy, Debug)] -pub struct U8; - -/// Struct for executor implementation, allows u16 Engine to be implemented. -#[derive(Clone, Copy, Debug)] -#[cfg(feature = "engine-u16")] -pub struct U16; - -/// Struct for executor implementation, allows u32 Engine to be implemented. -#[derive(Clone, Copy, Debug)] -#[cfg(feature = "engine-u32")] -pub struct U32; - -/// Trait that must be implemented by all executors. -pub trait Executor<E: Engine> { - /// Executes the provided instruction set, utilising the provided tape. - /// - /// # Errors - /// - /// This function will return an error if the Brainfuck code indexes out of - /// bounds of the tape, or if the executor cannot read an input byte from - /// stdin. - fn execute( - instructions: &[Instruction], - tape: &mut [E::TapeInner], - data_pointer: &mut usize, - ) -> Result<(), Error>; -} - -impl<E> Executor<E> for E -where - E: Engine, -{ - #[inline] - fn execute( - instructions: &[Instruction], - tape: &mut [<E as Engine>::TapeInner], - data_pointer: &mut usize, - ) -> Result<(), Error> { - execute::<E>(instructions, tape, data_pointer) - } -} - -/// Executes the provided instruction set, utilising the provided tape. This -/// function allows specifying the Brainfuck engine implementation per call. -/// -/// # Errors -/// -/// This function will return an error if the Brainfuck code indexes out of -/// bounds of the tape, or if the executor cannot read an input byte from -/// stdin. -pub fn execute<E: Engine>( - instructions: &[Instruction], - tape: &mut [E::TapeInner], - data_pointer: &mut usize, -) -> Result<(), Error> { - for instruction in instructions { - match *instruction { - Instruction::IncrementPointer => { - let tape_len: usize = tape.len() - 1; - - if *data_pointer == tape_len { - *data_pointer = 0; - } else { - *data_pointer += 1; - } - } - Instruction::DecrementPointer => { - *data_pointer = match *data_pointer { - 0 => tape.len() - 1, - _ => *data_pointer - 1, - }; - } - Instruction::IncrementByte => match tape.get_mut(*data_pointer) { - Some(value) => *value = value.wrapping_add(&E::TapeInner::one()), - None => return Err(Error::IndexOutOfBounds(*data_pointer)), - }, - Instruction::DecrementByte => match tape.get_mut(*data_pointer) { - Some(value) => *value = value.wrapping_sub(&E::TapeInner::one()), - None => return Err(Error::IndexOutOfBounds(*data_pointer)), - }, - Instruction::OutputByte => { - E::write_byte(match tape.get(*data_pointer) { - Some(value) => *value, - None => return Err(Error::IndexOutOfBounds(*data_pointer)), - })?; - } - Instruction::InputByte => { - let input = E::read_byte()?; - - match tape.get_mut(*data_pointer) { - Some(value) => *value = input, - None => return Err(Error::IndexOutOfBounds(*data_pointer)), - }; - } - Instruction::Loop(ref instructions) => { - while match tape.get(*data_pointer) { - Some(value) => value, - None => return Err(Error::IndexOutOfBounds(*data_pointer)), - } != &E::TapeInner::zero() - { - execute::<E>(instructions, tape, data_pointer)?; - } - } - } - } - - Ok(()) -} |