Compare commits

...

2 Commits

Author SHA1 Message Date
b1ek 3facaa10a2
don't throw runtime error when stdin closes 2023-08-22 22:46:18 +10:00
b1ek dce22d5719
add lint 2023-08-22 22:45:12 +10:00
2 changed files with 80 additions and 7 deletions

View File

@ -7,10 +7,6 @@ fn main() {
) )
); );
if eval.is_err() { if eval.is_err() {
let err = eval.unwrap_err(); eprintln!("Program failed: \n{}", eval.unwrap_err());
if err == "Stdin closed" {
return
}
eprintln!("Program failed: {}", err);
} }
} }

View File

@ -1,6 +1,68 @@
#![forbid(unsafe_code)] #![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<String>> {
let mut loop_stack: Vec<usize> = vec![];
let mut pos = 0 as usize;
let mut pointer = 0;
let chars = code.chars().collect::<Vec<char>>();
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> { pub fn eval_mem(bf_str: &&str, mem: &mut [u8], pointer: &mut usize) -> Result<(), String> {
@ -57,7 +119,7 @@ pub fn eval_mem(bf_str: &&str, mem: &mut [u8], pointer: &mut usize) -> Result<()
if char == ',' { if char == ',' {
let byte = stdin().bytes().next(); let byte = stdin().bytes().next();
if byte.is_none() { if byte.is_none() {
return Err("Stdin closed".into()); continue
} }
let byte = byte.unwrap(); let byte = byte.unwrap();
if byte.is_err() { if byte.is_err() {
@ -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> { 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 memory: [u8; 30000] = core::array::from_fn(|_| 0);
let mut pointer = 0 as usize; let mut pointer = 0 as usize;