From c2800dfcc72dd7ca009b966723b3b2df8653b114 Mon Sep 17 00:00:00 2001 From: 0x4261756D <–38735823+0x4261756D@users.noreply.github.com> Date: Wed, 14 Dec 2022 11:46:39 +0100 Subject: [PATCH] Make while swallow the input --- src/main.rs | 73 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 7 deletions(-) diff --git a/src/main.rs b/src/main.rs index cbac1ef..a7d87f6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -54,7 +54,10 @@ enum Operation { Enqueue(Datatype, String, i32, i32), Dequeue(i32, i32), + // TODO: req can be implemented in terms of dup and dequeue Requeue(i32, i32), + Swap(i32, i32), + Dup(i32, i32), Intrinsic(String, i32, i32), FunctionCall(String, i32, i32), If(Vec, Option>, i32, i32), @@ -67,6 +70,7 @@ fn main() [ ("print", (Vec::from([Datatype::Any]), Vec::new())), ("-", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Int]))), + ("+", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Int]))), ]); let args: Vec = env::args().collect(); if args.len() < 2 @@ -132,6 +136,18 @@ fn interpret_program(operations: &Vec, queue: &mut Vec, funct let val = queue.remove(0); queue.push(val); } + Operation::Dup(_, _) => + { + let val = queue.get(0).unwrap(); + queue.push(val.clone()); + } + Operation::Swap(_, _) => + { + let first = queue.remove(0); + let second = queue.remove(0); + queue.push(second); + queue.push(first); + } Operation::FunctionCall(function_name, _, _) => { interpret_program(&functions.iter().find(|x| &x.name == function_name).unwrap().content, queue, functions, intrinsics, debug); @@ -163,6 +179,12 @@ fn interpret_program(operations: &Vec, queue: &mut Vec, funct let subtrahend = queue.remove(0).parse::().unwrap(); queue.push((minuend - subtrahend).to_string()); } + "+" => + { + let addend1 = queue.remove(0).parse::().unwrap(); + let addend2 = queue.remove(0).parse::().unwrap(); + queue.push((addend1 + addend2).to_string()); + } _ => { panic!("Unexpected intrinsic '{}' at {}:{}", intrinsic_name, line, col); @@ -173,7 +195,7 @@ fn interpret_program(operations: &Vec, queue: &mut Vec, funct { loop { - let val = queue.get(0).unwrap(); + let val = queue.remove(0); if val == "0" { break; @@ -227,6 +249,8 @@ fn typecheck_block(operations: &Vec, ins: &Vec, outs: &Vec< { Operation::Enqueue(_, _, line, col) | Operation::Requeue(line, col) | + Operation::Dup(line, col) | + Operation::Swap(line, col) | Operation::FunctionCall(_, line, col) | Operation::If(_, _, line, col) | Operation::Intrinsic(_, line, col) | @@ -265,6 +289,17 @@ fn get_return_type(operations: &Vec, ins: &Vec, functions: { type_queue.push(*datatype); } + Operation::Dup(line, col) => + { + if let Some(typ) = type_queue.get(0) + { + type_queue.push(typ.clone()); + } + else + { + panic!("Attempted to dup an element while the queue was empty at {}:{}", line, col); + } + } Operation::Requeue(line, col) => { if type_queue.is_empty() @@ -274,6 +309,21 @@ fn get_return_type(operations: &Vec, ins: &Vec, functions: let typ = type_queue.remove(0); type_queue.push(typ); } + Operation::Swap(line, col) => + { + if type_queue.is_empty() + { + panic!("Attempted to get the first element for a swap while the queue was empty at {}:{}", line, col); + } + let first_typ = type_queue.remove(0); + if type_queue.is_empty() + { + panic!("Attempted to get the second element for a swap while the queue was empty at {}:{}", line, col); + } + let second_typ = type_queue.remove(0); + type_queue.push(second_typ); + type_queue.push(first_typ); + } Operation::FunctionCall(function_name, line, col) => { let function = functions.iter().find(|x| &x.name == function_name).unwrap(); @@ -350,7 +400,7 @@ fn get_return_type(operations: &Vec, ins: &Vec, functions: { panic!("Encountered while block with an empty queue at {}:{}", line, col); } - let &comparison_type = type_queue.get(0).unwrap(); + let comparison_type = type_queue.remove(0); if comparison_type != Datatype::Int { panic!("Expected an int as a while condition but got {:?} instead at {}:{}", comparison_type, line, col); @@ -359,7 +409,9 @@ fn get_return_type(operations: &Vec, ins: &Vec, functions: { println!("Starting to typecheck while block"); } - typecheck_block(while_block, type_queue, type_queue, functions, intrinsics, debug); + let mut outs = type_queue.clone(); + outs.insert(0, Datatype::Int); + typecheck_block(while_block, type_queue, &outs, functions, intrinsics, debug); } } if debug @@ -393,12 +445,12 @@ fn validate_function_calls_in_block(block: &Vec, functions: &Vec {}, + Operation::Intrinsic(_, _, _) | Operation::Enqueue(_, _, _, _) | Operation::Dequeue(_, _) | Operation::Requeue(_, _) | Operation::Dup(_, _) | Operation::Swap(_, _) => {}, Operation::FunctionCall(function_name, line, col) => { if !functions.iter().any(|x| &x.name == function_name) { - panic!("Call to unknown function {} at {}:{}", function_name, line, col); + panic!("Call to unknown function '{}' at {}:{}", function_name, line, col); } } Operation::If(if_block, maybe_else_block, _, _) => @@ -490,7 +542,7 @@ fn extract_functions(tokens: &mut Vec, intrinsics: &HashMap<&str, (Vec outs.push(Datatype::Any), "str" => outs.push(Datatype::String), "int" => outs.push(Datatype::Int), - "{" | "}" | "deq" | "req" => panic!("Expected function name but got {} at {}:{}", word, line, col), + "{" | "}" | "deq" | "req" | "dup" | "swp" => panic!("Expected function name but got {} at {}:{}", word, line, col), _ => { if functions.iter().any(|x| &x.name == word) @@ -606,9 +658,16 @@ fn parse_until_delimiter(tokens_iter: &mut Peekable>, in } else if word == "req" { - operations.push(Operation::Requeue(*line, *col)); } + else if word == "dup" + { + operations.push(Operation::Dup(*line, *col)); + } + else if word == "swp" + { + operations.push(Operation::Swap(*line, *col)); + } else if Some(word.as_str()) == delimiter { return operations;