summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSophie Forrest <git@sophieforrest.com>2024-08-30 23:35:45 +1200
committerSophie Forrest <git@sophieforrest.com>2024-08-30 23:35:45 +1200
commit17b78f8cb127817b93f7e6ced7e55d8748806a80 (patch)
tree22bccb1307c078da4fc6e0873c8a8c2d081408ab
parent13b95941183666fadd090314e4e9af33283084cd (diff)
feat: bar engines behind features, optimise release and small profiles
-rw-r--r--Cargo.toml19
-rw-r--r--src/engine.rs7
-rw-r--r--src/executor.rs35
-rw-r--r--src/lib.rs24
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");