diff --git a/src/lib.rs b/src/lib.rs index 22c73ba..527d9fa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,68 @@ #![forbid(unsafe_code)] -use std::io::{stdout, Write, Read, stdin}; +use std::{io::{stdout, Write, Read, stdin}, fmt::format}; + +/** + * Check code for syntax errors + */ +pub fn lint_code(code: &&str) -> Result<(), Vec> { + + let mut loop_stack: Vec = vec![]; + let mut pos = 0 as usize; + let mut pointer = 0; + + let chars = code.chars().collect::>(); + let size = code.len(); + + let mut errors = vec![]; + + loop { + if pos == size { + break + } + + let char = chars[pos]; + pos += 1; + + if char == '<' { + if pointer == 0 { + errors.push(format!("ERR: Reducing pointer to less than 0 is not allowed ({})", pos)); + continue + } + pointer -= 1; + } + if char == '>' { + if pointer == 29999 { + errors.push(format!("ERR: Increasing pointer to more than 29999 is not allowed ({})", pos)); + continue + } + pointer += 1; + } + if char == '[' { + loop_stack.push(pos); + continue + } + if char == ']' { + if loop_stack.len() == 0 { + errors.push(format!("ERR: Unmatched ']' ({})", pos)); + continue + } + loop_stack.pop(); + } + } + + if loop_stack.len() != 0 { + for lup in loop_stack.iter() { + errors.push(format!("Unmatched '[' ({})", *lup)); + } + } + + if errors.len() != 0 { + return Err(errors) + } + + Ok(()) +} pub fn eval_mem(bf_str: &&str, mem: &mut [u8], pointer: &mut usize) -> Result<(), String> { @@ -94,6 +156,21 @@ pub fn eval_mem(bf_str: &&str, mem: &mut [u8], pointer: &mut usize) -> Result<() } pub fn eval(bf_str: &&str) -> Result<[u8; 30000], String> { + + // first check the code + + let lint = lint_code(bf_str); + if lint.is_err() { + return Err( + format!( + "Code linting failed: \n\n{}", + lint.unwrap_err().join("\n") + ) + ) + } + + // then actually run it + let mut memory: [u8; 30000] = core::array::from_fn(|_| 0); let mut pointer = 0 as usize;