summaryrefslogtreecommitdiff
path: root/src
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
commit13b95941183666fadd090314e4e9af33283084cd (patch)
tree2831968068a77b7a37a37d1356e9673d4dcc3275 /src
parentf5f789540ad7d3f7f4f855c9db69d65cfc190ee0 (diff)
feat(engine)!: implement u32 engine
Diffstat (limited to '')
-rw-r--r--src/engine.rs54
-rw-r--r--src/executor.rs12
-rw-r--r--src/lib.rs1
-rw-r--r--src/main.rs1
-rw-r--r--src/utility.rs5
5 files changed, 58 insertions, 15 deletions
diff --git a/src/engine.rs b/src/engine.rs
index 8cf2726..6c69bc1 100644
--- a/src/engine.rs
+++ b/src/engine.rs
@@ -2,11 +2,29 @@
//!
//! This predominantly allows implementation of a [`u16`] executor.
-use std::io::Read;
+use std::io::{Cursor, Read};
+use byteorder::{BigEndian, ReadBytesExt};
use num_traits::{One, Unsigned, WrappingAdd, WrappingSub, Zero};
+use thiserror::Error;
-use crate::executor::{self, Error};
+use crate::executor;
+
+/// Error type for engine errors
+#[derive(Debug, Error)]
+pub enum Error {
+ /// Engine ran into an io Error
+ #[error(transparent)]
+ Io(#[from] std::io::Error),
+
+ /// Utf16 error from widestring
+ #[error("could not convert byte to Utf16Str")]
+ Utf16,
+
+ /// Utf32 error from widestring
+ #[error("could not convert byte to Utf32Str")]
+ Utf32,
+}
/// Generic engine implementation for the Brainfuck interpreter.
pub trait Engine {
@@ -56,13 +74,39 @@ impl Engine for executor::U16 {
std::io::stdin().read_exact(&mut input)?;
- let number = ((u16::from(input[0])) << 8i32) | u16::from(input[1]);
+ let mut reader = Cursor::new(input);
- Ok(number)
+ Ok(reader.read_u16::<BigEndian>()?)
}
fn write_byte(byte: u16) -> Result<(), Error> {
- print!("{}", String::from_utf16_lossy(&[byte]));
+ print!(
+ "{}",
+ widestring::Utf16Str::from_slice(&[byte]).map_err(|_err| Error::Utf16)?
+ );
+
+ Ok(())
+ }
+}
+
+impl Engine for executor::U32 {
+ type TapeInner = u32;
+
+ fn read_byte() -> Result<u32, Error> {
+ let mut input: [u8; 4] = [0; 4];
+
+ std::io::stdin().read_exact(&mut input)?;
+
+ let mut reader = Cursor::new(input);
+
+ Ok(reader.read_u32::<BigEndian>()?)
+ }
+
+ fn write_byte(byte: u32) -> Result<(), Error> {
+ print!(
+ "{}",
+ widestring::Utf32Str::from_slice(&[byte]).map_err(|_err| Error::Utf32)?
+ );
Ok(())
}
diff --git a/src/executor.rs b/src/executor.rs
index eddf443..da7d676 100644
--- a/src/executor.rs
+++ b/src/executor.rs
@@ -9,14 +9,14 @@ 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),
-
- /// Executor was unable to read an input byte from stdin.
- #[error("could not read input from stdin")]
- ReadInput(#[from] std::io::Error),
}
/// Struct for executor implementation, allows u8 Engine to be implemented.
@@ -27,6 +27,10 @@ pub struct U8;
#[derive(Clone, Copy, Debug)]
pub struct U16;
+/// Struct for executor implementation, allows u32 Engine to be implemented.
+#[derive(Clone, Copy, Debug)]
+pub struct U32;
+
/// Executes the provided instruction set, utilising the provided tape..
///
/// # Errors
diff --git a/src/lib.rs b/src/lib.rs
index b806b4c..2c40797 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,7 +3,6 @@
#![feature(custom_inner_attributes)]
#![feature(lint_reasons)]
#![feature(never_type)]
-#![feature(once_cell)]
#![feature(test)]
#![deny(clippy::complexity)]
#![deny(clippy::nursery)]
diff --git a/src/main.rs b/src/main.rs
index f5c4740..13868a6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,7 +3,6 @@
#![feature(custom_inner_attributes)]
#![feature(lint_reasons)]
#![feature(never_type)]
-#![feature(once_cell)]
#![deny(clippy::complexity)]
#![deny(clippy::nursery)]
#![deny(clippy::pedantic)]
diff --git a/src/utility.rs b/src/utility.rs
index 4eba853..514343c 100644
--- a/src/utility.rs
+++ b/src/utility.rs
@@ -37,10 +37,7 @@ pub fn execute_from_file<E: Engine>(
/// This function will return an error if parsing or
/// execution fails. See documentation for [`crate::parser::parse`] and
/// [`crate::executor::execute`].
-pub fn execute_from_str<E: Engine<TapeInner = u8>>(
- input: &str,
- tape: &mut [E::TapeInner],
-) -> Result<(), Error> {
+pub fn execute_from_str<E: Engine>(input: &str, tape: &mut [E::TapeInner]) -> Result<(), Error> {
let operator_codes = lex(input);
let instructions = parse(input, &operator_codes)?;