diff options
| -rw-r--r-- | Cargo.toml | 19 | ||||
| -rw-r--r-- | src/engine.rs | 7 | ||||
| -rw-r--r-- | src/executor.rs | 35 | ||||
| -rw-r--r-- | src/lib.rs | 24 |
4 files changed, 80 insertions, 5 deletions
diff --git a/Cargo.toml b/Cargo.toml index b3403d7..f817db1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,3 +19,22 @@ bigint-engine = ["dep:byteorder", "dep:widestring"] engine-u16 = ["bigint-engine"] engine-u32 = ["bigint-engine"] utilities = [] + +[profile.release] +codegen-units = 1 +debug = 0 +incremental = false +lto = true +opt-level = 3 +panic = "abort" +strip = "symbols" + +[profile.small] +inherits = "release" +codegen-units = 1 +debug = 0 +incremental = false +lto = true +opt-level = "z" +panic = "abort" +strip = "symbols" diff --git a/src/engine.rs b/src/engine.rs index 6c69bc1..3269dff 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -2,8 +2,11 @@ //! //! This predominantly allows implementation of a [`u16`] executor. -use std::io::{Cursor, Read}; +#[cfg(feature = "bigint-engine")] +use std::io::Cursor; +use std::io::Read; +#[cfg(feature = "bigint-engine")] use byteorder::{BigEndian, ReadBytesExt}; use num_traits::{One, Unsigned, WrappingAdd, WrappingSub, Zero}; use thiserror::Error; @@ -66,6 +69,7 @@ impl Engine for executor::U8 { } } +#[cfg(feature = "engine-u16")] impl Engine for executor::U16 { type TapeInner = u16; @@ -89,6 +93,7 @@ impl Engine for executor::U16 { } } +#[cfg(feature = "engine-u32")] impl Engine for executor::U32 { type TapeInner = u32; diff --git a/src/executor.rs b/src/executor.rs index da7d676..c5fff93 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -25,13 +25,46 @@ 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; -/// Executes the provided instruction set, utilising the provided tape.. +/// 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 /// diff --git a/src/lib.rs b/src/lib.rs index 2c40797..71c5a99 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,6 +88,7 @@ pub mod parser; #[cfg(feature = "utilities")] pub mod utility; +pub use executor::{U16 as ExecutorU16, U32 as ExecutorU32, U8 as ExecutorU8}; pub use lexer::{lex, OperatorCode}; use miette::Diagnostic; pub use parser::{parse, Instruction}; @@ -152,8 +153,11 @@ mod tests { let mut tape: Vec<u8> = vec![0; 1024]; #[allow(clippy::expect_used)] - utility::execute_from_file::<executor::U8>("./test_programs/hello_world.bf", &mut tape) - .expect("failed to run"); + utility::execute_from_file::<executor::U8>( + "./test_programs/hello_world_from_hell.bf", + &mut tape, + ) + .expect("failed to run"); }); } @@ -164,7 +168,21 @@ mod tests { #[allow(clippy::expect_used)] utility::execute_from_file::<executor::U16>( - "./test_programs/hello_world.bf", + "./test_programs/hello_world_from_hell.bf", + &mut tape, + ) + .expect("failed to run"); + }); + } + + #[bench] + fn hello_world_from_hell_bench_u32(b: &mut Bencher) { + b.iter(|| { + let mut tape: Vec<u32> = vec![0; 1024]; + + #[allow(clippy::expect_used)] + utility::execute_from_file::<executor::U32>( + "./test_programs/hello_world_from_hell.bf", &mut tape, ) .expect("failed to run"); |