From bf4a08e484eb2f2cc3ec3c1f18b7939b22382747 Mon Sep 17 00:00:00 2001 From: 0x4261756D <38735823+0x4261756D@users.noreply.github.com> Date: Thu, 22 Dec 2022 00:47:41 +0100 Subject: [PATCH] Make interpret fallible, fix applications at end of file, add more checks --- src/main.rs | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/main.rs b/src/main.rs index 9f542d3..6f367d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -209,7 +209,7 @@ fn compile(file_content: &String, intrinsics: &HashMap<&str, (Vec, Vec let output = if interpret { println!("---Starting to interpret the program---"); - Some(interpret_program(&operations, &mut Vec::new(), &functions, &mut arrays, &intrinsics, debug)) + Some(interpret_program(&operations, &mut Vec::new(), &functions, &mut arrays, &intrinsics, debug)?) } else { @@ -218,7 +218,7 @@ fn compile(file_content: &String, intrinsics: &HashMap<&str, (Vec, Vec return Ok(output); } -fn interpret_program(operations: &Vec, queue: &mut Vec, functions: &Vec, arrays: &mut Vec, intrinsics: &HashMap<&str, (Vec, Vec)>, debug: bool) -> String +fn interpret_program(operations: &Vec, queue: &mut Vec, functions: &Vec, arrays: &mut Vec, intrinsics: &HashMap<&str, (Vec, Vec)>, debug: bool) -> Result { let mut output = String::new(); for operation in operations @@ -263,7 +263,7 @@ fn interpret_program(operations: &Vec, queue: &mut Vec, funct let val = queue.remove(0); function_context.push(val); } - output += interpret_program(&function.content, function_context, functions, arrays, intrinsics, debug).as_str(); + output += interpret_program(&function.content, function_context, functions, arrays, intrinsics, debug)?.as_str(); for val in function_context { queue.push(val.to_string()); @@ -274,11 +274,11 @@ fn interpret_program(operations: &Vec, queue: &mut Vec, funct let val = queue.remove(0); if val == "true" { - output += interpret_program(if_block, queue, functions, arrays, intrinsics, debug).as_str(); + output += interpret_program(if_block, queue, functions, arrays, intrinsics, debug)?.as_str(); } else if let Some(else_block) = maybe_else_block { - output += interpret_program(else_block, queue, functions, arrays, intrinsics, debug).as_str(); + output += interpret_program(else_block, queue, functions, arrays, intrinsics, debug)?.as_str(); } } Operation::Intrinsic(intrinsic_name, line, col) => @@ -336,7 +336,7 @@ fn interpret_program(operations: &Vec, queue: &mut Vec, funct } _ => { - panic!("Unexpected intrinsic '{}' at {}:{}", intrinsic_name, line, col); + return Err(format!("Unexpected intrinsic '{}' at {}:{}", intrinsic_name, line, col)); } } } @@ -350,7 +350,11 @@ fn interpret_program(operations: &Vec, queue: &mut Vec, funct let position: i64 = queue.remove(0).parse::().unwrap(); if position >= arr.length { - panic!("Attempted an out of bounds write for array {} ({} >= {}) at {}:{}", arr.name, position, arr.length, line, col); + return Err(format!("Attempted an out of bounds write for array {} ({} >= {}) at {}:{}", arr.name, position, arr.length, line, col)); + } + if position < 0 + { + return Err(format!("Attempted an out of bounds write for array {} ({} < 0) at {}:{}", arr.name, position, line, col)); } arr.data[position as usize] = queue.remove(0); } @@ -359,7 +363,11 @@ fn interpret_program(operations: &Vec, queue: &mut Vec, funct let position: i64 = queue.remove(0).parse::().unwrap(); if position >= arr.length { - panic!("Attempted an out of bounds read for array {} ({} >= {}) at {}:{}", arr.name, position, arr.length, line, col); + return Err(format!("Attempted an out of bounds read for array {} ({} >= {}) at {}:{}", arr.name, position, arr.length, line, col)); + } + if position < 0 + { + return Err(format!("Attempted an out of bounds read for array {} ({} < 0) at {}:{}", arr.name, position, line, col)); } queue.push(arr.data[position as usize].clone()); } @@ -367,7 +375,7 @@ fn interpret_program(operations: &Vec, queue: &mut Vec, funct { queue.push(arr.length.to_string()); } - _ => panic!("Unexpected application '{}' at {}:{}", word, line, col) + _ => return Err(format!("Unexpected application '{}' at {}:{}", word, line, col)) } } Operation::While(while_block, _, _) => @@ -379,7 +387,7 @@ fn interpret_program(operations: &Vec, queue: &mut Vec, funct { break; } - output += interpret_program(while_block, queue, functions, arrays, intrinsics, debug).as_str(); + output += interpret_program(while_block, queue, functions, arrays, intrinsics, debug)?.as_str(); } } Operation::Depth(_, _) => @@ -397,7 +405,7 @@ fn interpret_program(operations: &Vec, queue: &mut Vec, funct println!("after: {:?}: {:?}, '{}'", operation, queue, output); } } - return output; + return Ok(output); } fn typecheck(operations: &Vec, functions: &Vec, intrinsics: &HashMap<&str, (Vec, Vec)>, arrays: &Vec, debug: bool) -> Result<(), String> @@ -626,6 +634,10 @@ fn get_return_type(operations: &Vec, ins: &Vec, functions: return Err(format!("Expected a position for a write application at {}:{}", line, col)); } let expected_type = arrays.iter().find(|x| &x.name == name).unwrap().datatype; + if type_queue.is_empty() + { + return Err(format!("Expected data for a write application at {}:{}", line, col)); + } let actual_type = type_queue.remove(0); if actual_type != expected_type { @@ -1187,7 +1199,14 @@ fn tokenize(text: &str) -> Result, String> TokenizerState::Whitespace | TokenizerState::Comment => {}, TokenizerState::Keyword => { - tokens.push(Token::Keyword(word.clone(), line, col)); + if application_name.is_empty() + { + tokens.push(Token::Keyword(word.clone(), line, col)); + } + else + { + tokens.push(Token::Apply(application_name.clone(), word.clone(), line, col)); + } } } Ok(tokens)