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 | 5126c9ed83fe6169463566e74f966a4a63e57ca0 (patch) | |
| tree | 99be8b093f6736eba59c529300519985d9c1c5c6 /src/lib.rs | |
feat: initial commit of brainf interpreter
Diffstat (limited to '')
| -rw-r--r-- | src/lib.rs | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..725084a --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,154 @@ +#![allow(incomplete_features)] +#![feature(async_fn_in_trait)] +#![feature(custom_inner_attributes)] +#![feature(lint_reasons)] +#![feature(never_type)] +#![feature(once_cell)] +#![feature(test)] +#![deny(clippy::complexity)] +#![deny(clippy::nursery)] +#![deny(clippy::pedantic)] +#![deny(clippy::perf)] +#![deny(clippy::suspicious)] +#![deny(clippy::alloc_instead_of_core)] +#![deny(clippy::as_underscore)] +#![deny(clippy::clone_on_ref_ptr)] +#![deny(clippy::create_dir)] +#![warn(clippy::dbg_macro)] +#![deny(clippy::default_numeric_fallback)] +#![deny(clippy::default_union_representation)] +#![deny(clippy::deref_by_slicing)] +#![deny(clippy::empty_structs_with_brackets)] +#![deny(clippy::exit)] +#![deny(clippy::expect_used)] +#![deny(clippy::filetype_is_file)] +#![deny(clippy::fn_to_numeric_cast)] +#![deny(clippy::format_push_string)] +#![deny(clippy::get_unwrap)] +#![deny(clippy::if_then_some_else_none)] +#![allow( + clippy::implicit_return, + reason = "returns should be done implicitly, not explicitly" +)] +#![deny(clippy::indexing_slicing)] +#![deny(clippy::large_include_file)] +#![deny(clippy::let_underscore_must_use)] +#![deny(clippy::lossy_float_literal)] +#![deny(clippy::map_err_ignore)] +#![deny(clippy::mem_forget)] +#![deny(clippy::missing_docs_in_private_items)] +#![deny(clippy::missing_trait_methods)] +#![deny(clippy::mod_module_files)] +#![deny(clippy::multiple_inherent_impl)] +#![deny(clippy::mutex_atomic)] +#![deny(clippy::needless_return)] +#![deny(clippy::non_ascii_literal)] +#![deny(clippy::panic_in_result_fn)] +#![deny(clippy::pattern_type_mismatch)] +#![deny(clippy::rc_buffer)] +#![deny(clippy::rc_mutex)] +#![deny(clippy::rest_pat_in_fully_bound_structs)] +#![deny(clippy::same_name_method)] +#![deny(clippy::separated_literal_suffix)] +#![deny(clippy::str_to_string)] +#![deny(clippy::string_add)] +#![deny(clippy::string_slice)] +#![deny(clippy::string_to_string)] +#![allow( + clippy::tabs_in_doc_comments, + reason = "tabs are preferred for this project" +)] +#![deny(clippy::try_err)] +#![deny(clippy::undocumented_unsafe_blocks)] +#![deny(clippy::unnecessary_self_imports)] +#![deny(clippy::unneeded_field_pattern)] +#![deny(clippy::unwrap_in_result)] +#![deny(clippy::unwrap_used)] +#![warn(clippy::use_debug)] +#![deny(clippy::verbose_file_reads)] +#![deny(clippy::wildcard_dependencies)] +#![deny(clippy::wildcard_enum_match_arm)] +#![deny(missing_copy_implementations)] +#![deny(missing_debug_implementations)] +#![deny(missing_docs)] +#![deny(single_use_lifetimes)] +#![deny(unsafe_code)] +#![deny(unused)] + +//! Brainfuck RS +//! +//! Implementation of a Brainfuck interpreter written in Rust. + +#[cfg(test)] +extern crate test; + +mod constants; +pub mod executor; +pub mod lexer; +pub mod parser; +#[cfg(feature = "utilities")] +pub mod utility; + +pub use executor::execute; +pub use lexer::{lex, OperatorCode}; +use miette::Diagnostic; +pub use parser::{parse, Instruction}; +use thiserror::Error; + +/// Top-level error type for Brainfuck interpreter. +#[derive(Debug, Diagnostic, Error)] +pub enum Error { + /// Error occurred when reading input from a file. + #[error(transparent)] + Io(#[from] std::io::Error), + + /// An error that occurred while parsing Brainfuck code. + #[diagnostic(transparent)] + #[error(transparent)] + Parser(#[from] parser::Error), + + /// An error that occurred during runtime. + #[error(transparent)] + Runtime(#[from] executor::Error), +} + +#[cfg(test)] +mod tests { + use test::Bencher; + + use super::*; + use crate::constants::TapeInner; + + #[test] + fn hello_world() -> Result<(), Error> { + let mut tape: Vec<TapeInner> = vec![0; 1024]; + + utility::execute_from_file("./test_programs/hello_world.bf", &mut tape)?; + + Ok(()) + } + + #[bench] + fn hello_world_from_hell(b: &mut Bencher) { + b.iter(|| { + let mut tape: Vec<TapeInner> = vec![0; 1024]; + + #[allow(clippy::expect_used)] + utility::execute_from_file("./test_programs/hello_world.bf", &mut tape) + .expect("failed to run"); + }); + } + + #[test] + fn hello_world_short() -> Result<(), Error> { + let mut tape: Vec<TapeInner> = vec![0; 1024]; + + utility::execute_from_str( + "--[+++++++<---->>-->+>+>+<<<<]<.>++++[-<++++>>->--<<]>>-.>--..>+.<<<.<<-.>>+>->>.\ + +++[.<]", + &mut tape, + )?; + + Ok(()) + } +} |