mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'lemu/src/lib.rs')
| -rw-r--r-- | lemu/src/lib.rs | 185 |
1 files changed, 0 insertions, 185 deletions
diff --git a/lemu/src/lib.rs b/lemu/src/lib.rs deleted file mode 100644 index 25d571b..0000000 --- a/lemu/src/lib.rs +++ /dev/null @@ -1,185 +0,0 @@ -//! crate for [MLOG](https://mindustrygame.github.io/wiki/logic/0-introduction/#what-is-mindustry-logic) emulation. -#![allow(clippy::redundant_closure_call)] -// yeah so like well you see i kinda well kinda have to yes but sorta -#![allow(clippy::fn_address_comparisons)] -#![feature(generic_const_exprs, iter_array_chunks)] -#![warn( - clippy::multiple_unsafe_ops_per_block, - clippy::missing_const_for_fn, - clippy::redundant_pub_crate, - clippy::missing_safety_doc, - clippy::imprecise_flops, - unsafe_op_in_unsafe_fn, - clippy::dbg_macro, - missing_docs -)] -pub(crate) mod code; -mod debug; -mod executor; -mod instructions; -mod lexer; -mod memory; -mod parser; - -use std::io::Write; - -pub use executor::{Executor, Output}; -use executor::{ExecutorBuilderInternal, Limit}; -use fimg::Image; -pub use parser::Error; - -impl<W: Write + Default> Executor<'_, W> { - /// Create a new [`ExecutorBuilder`] - pub fn build() -> ExecutorBuilder<W> { - ExecutorBuilder::default() - } -} -impl<W: Write> Executor<'_, W> { - /// Create a new [`ExecutorBuilder`] with a output. - /// - /// Output simply must impement [`Write`], so this can be set to stdout. - /// Or simply set it to [`Vec<u8>`]. - pub fn with_output(w: W) -> ExecutorBuilder<W> { - ExecutorBuilder { - displays: Vec::new(), - output: Some(w), - instruction_limit: Limit::Unlimited, - iteration_limit: Limit::limited(1), - } - } -} - -/// Builder for a [`Executor`]. -/// ``` -/// # use lemu::Executor; -/// let mut lex = Executor::with_output(std::io::stdout()).program(r#"print "hello world""#).expect("program ok"); -/// lex.run(); -/// ``` -pub struct ExecutorBuilder<W: Write> { - output: Option<W>, - displays: Vec<Image<Vec<u8>, 4>>, - instruction_limit: Limit, - iteration_limit: Limit, -} - -impl<W: Write> Default for ExecutorBuilder<W> { - fn default() -> Self { - Self { - output: None, - displays: Vec::new(), - instruction_limit: Limit::Unlimited, - iteration_limit: Limit::limited(1), - } - } -} - -impl<W: Write> ExecutorBuilder<W> { - /// Limit the number of iterations. - pub fn limit_iterations(self, n: usize) -> Self { - Self { - iteration_limit: Limit::limited(n), - ..self - } - } - - /// Unlimit the number of iterations. - pub fn unlimit_iterations(self) -> Self { - Self { - iteration_limit: Limit::Unlimited, - ..self - } - } - - /// Unlimit the number of instructions. - /// Make sure to limit the number of the iterations, else it will possibly run forever. - pub fn unlimit_instructions(self) -> Self { - Self { - iteration_limit: Limit::Unlimited, - ..self - } - } - - /// Limit the number of processed instructions. - /// - /// Use this if you want it to *definetly finish*. - pub fn limit_instructions(self, n: usize) -> Self { - Self { - instruction_limit: Limit::limited(n), - ..self - } - } - - /// Add a small (`80x80`) logic display. - pub fn display(self) -> Self { - let mut d = self.displays; - d.push(Image::alloc(80, 80)); - Self { - displays: d, - ..self - } - } - - /// Add a large (`176x176`) logic display. - pub fn large_display(self) -> Self { - let mut d = self.displays; - d.push(Image::alloc(176, 176)); - Self { - displays: d, - ..self - } - } - - /// Build the [`Executor`] with this code. - /// - /// # Errors - /// - /// errors if the code is malformed. - pub fn program(self, program: &str) -> Result<Executor<'_, W>, Error<'_>> { - let Self { - output, - displays, - instruction_limit, - iteration_limit, - } = self; - let mut executor = ExecutorBuilderInternal::new(output, displays); - executor - .inslimit(instruction_limit) - .itrlimit(iteration_limit); - // #[cfg(debug_assertions)] - // lexer::print_stream(lexer::lex(program)); - parser::parse(lexer::lex(program), &mut executor)?; - Ok(executor.finish()) - } -} - -#[cfg(test)] -mod test { - use super::*; - - macro_rules! test { - (run $fn:ident.mlog $($times:literal times)?; - $(output = $to_be:literal $(;)?)? - $(cell[$cell_n:literal][$cell_index:literal] = $what:literal $(;)?)? - ) => { - #[test] - fn $fn() -> Result<(), Error<'static>> { - let v = vec![]; - let mut lex = Executor::with_output(v) - .unlimit_instructions() - $(.limit_iterations($times))? - .program(include_str!(concat!(stringify!($fn), ".mlog")))?; - lex.run(); - let output = lex.output(); - $(assert_eq!(output.output.unwrap(), $to_be);)? - $(assert_eq!(output.cells[$cell_n][$cell_index], $what);)? - Ok(()) - } - }; - } - - test!(run fib.mlog; output = b"12586269025"); - test!(run primes.mlog; output = b"2 | 3 | 5 | 7 | 11 | 13 | 17 | 19 | 23 | 29 | 31 | 37 | 41 | 43 | 47 | 53 | 59 | 61 | 67 | 71 | 73 | 79 | 83 | 89 | 97 | 101 | 103 | 107 | 109 | 113 | 127 | 131 | 137 | 139 | 149 | 151 | 157 | 163 | 167 | 173 | 179 | 181 | 191 | 193 | 197 | 199 | 211 | 223 | 227 | 229 | 233 | 239 | 241 | 251 | 257 | 263 | 269 | 271 | 277 | 281 | 283 | 293 | 307 | 311 | 313 | 317 | 331 | 337 | 347 | 349 | 353 | 359 | 367 | 373 | 379 | 383 | 389 | 397 | 401 | 409 | 419 | 421 | 431 | 433 | 439 | 443 | 449 | 457 | 461 | 463 | 467 | 479 | 487 | 491 | 499 | 503 | 509 | "); - test!(run numbers.mlog; output = b"121212"); - test!(run celliterate.mlog 5 times; cell[0][0] = 5.0); - test!(run hello.mlog; output = b"hello world"); -} |