From 48cb618d5afcd082d25fcce981d22bcbd0a8b473 Mon Sep 17 00:00:00 2001 From: 0x4261756D <–38735823+0x4261756D@users.noreply.github.com> Date: Wed, 14 Dec 2022 09:34:41 +0100 Subject: [PATCH] Add interpreter --- src/main.rs | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index da0decf..cbac1ef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -74,11 +74,13 @@ fn main() usage() } let mut debug = false; + let mut interpret = false; for arg in &args[3..] { match arg.as_str() { "-d" | "--debug" => debug = true, + "-i" | "--interpret" => interpret = true, _ => panic!("Unknown option {}", arg), } } @@ -97,11 +99,96 @@ fn main() println!("---Done validating function calls---"); typecheck(&operations, &functions, &intrinsics, debug); println!("---Done typechecking---"); + if interpret + { + println!("---Starting to interpret the program---\n\n"); + interpret_program(&operations, &mut Vec::new(), &functions, &intrinsics, debug); + } } _ => panic!("Unknown option {}", args[1]) } } +fn interpret_program(operations: &Vec, queue: &mut Vec, functions: &Vec, intrinsics: &HashMap<&str, (Vec, Vec)>, debug: bool) +{ + for operation in operations + { + if debug + { + println!("before: {:?}: {:?}", operation, queue); + } + match operation + { + Operation::Dequeue(_, _) => + { + queue.remove(0); + } + Operation::Enqueue(_, value, _, _) => + { + queue.push(value.clone()); + } + Operation::Requeue(_, _) => + { + let val = queue.remove(0); + queue.push(val); + } + Operation::FunctionCall(function_name, _, _) => + { + interpret_program(&functions.iter().find(|x| &x.name == function_name).unwrap().content, queue, functions, intrinsics, debug); + } + Operation::If(if_block, maybe_else_block, _, _) => + { + let val = queue.remove(0); + // TODO: Add bool type + if val == "0" + { + interpret_program(if_block, queue, functions, intrinsics, debug); + } + else if let Some(else_block) = maybe_else_block + { + interpret_program(else_block, queue, functions, intrinsics, debug); + } + } + Operation::Intrinsic(intrinsic_name, line, col) => + { + match intrinsic_name.as_str() + { + "print" => + { + print!("{}", queue.remove(0)); + } + "-" => + { + let minuend = queue.remove(0).parse::().unwrap(); + let subtrahend = queue.remove(0).parse::().unwrap(); + queue.push((minuend - subtrahend).to_string()); + } + _ => + { + panic!("Unexpected intrinsic '{}' at {}:{}", intrinsic_name, line, col); + } + } + } + Operation::While(while_block, _, _) => + { + loop + { + let val = queue.get(0).unwrap(); + if val == "0" + { + break; + } + interpret_program(while_block, queue, functions, intrinsics, debug); + } + } + } + if debug + { + println!("after: {:?}: {:?}", operation, queue); + } + } +} + fn typecheck(operations: &Vec, functions: &Vec, intrinsics: &HashMap<&str, (Vec, Vec)>, debug: bool) { for function in functions @@ -403,13 +490,17 @@ fn extract_functions(tokens: &mut Vec, intrinsics: &HashMap<&str, (Vec outs.push(Datatype::Any), "str" => outs.push(Datatype::String), "int" => outs.push(Datatype::Int), - "{" | "}" => panic!("Expected function name but got {} at {}:{}", word, line, col), + "{" | "}" | "deq" | "req" => panic!("Expected function name but got {} at {}:{}", word, line, col), _ => { if functions.iter().any(|x| &x.name == word) { panic!("Redeclaration of function '{}' at {}:{}", word, line, col); } + if intrinsics.contains_key(word.as_str()) + { + panic!("Function name {} at {}:{} is already an intrinsic", word, line, col); + } if debug { println!("outs: {:?}", outs);