summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/engine.rs7
-rw-r--r--src/executor.rs35
-rw-r--r--src/lib.rs24
3 files changed, 61 insertions, 5 deletions
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");