diff --git a/src/main.rs b/src/main.rs index 24faca9..89e3088 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,6 +64,8 @@ enum Operation FunctionCall(String, i32, i32), If(Vec, Option>, i32, i32), While(Vec, i32, i32), + Depth(i32, i32), + QueueDiagnostic(i32, i32), } fn main() @@ -71,12 +73,14 @@ fn main() let intrinsics: HashMap<&str, (Vec, Vec)> = HashMap::from( [ ("print", (Vec::from([Datatype::Any]), Vec::new())), + ("println", (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]))), ("<", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Bool]))), (">", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Bool]))), ("==", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Bool]))), ("!=", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Bool]))), + ("decrease", (Vec::from([Datatype::Int]), Vec::from([Datatype::Int]))), ]); let args: Vec = env::args().collect(); if args.len() < 2 @@ -156,12 +160,22 @@ fn interpret_program(operations: &Vec, queue: &mut Vec, funct } Operation::FunctionCall(function_name, _, _) => { - interpret_program(&functions.iter().find(|x| &x.name == function_name).unwrap().content, queue, functions, intrinsics, debug); + let function = functions.iter().find(|x| &x.name == function_name).unwrap(); + let function_context: &mut Vec = &mut Vec::new(); + for _ in 0..function.ins.len() + { + let val = queue.remove(0); + function_context.push(val); + } + interpret_program(&function.content, function_context, functions, intrinsics, debug); + for val in function_context + { + queue.push(val.to_string()); + } } Operation::If(if_block, maybe_else_block, _, _) => { let val = queue.remove(0); - // TODO: Add bool type if val == "true" { interpret_program(if_block, queue, functions, intrinsics, debug); @@ -215,6 +229,15 @@ fn interpret_program(operations: &Vec, queue: &mut Vec, funct let second = queue.remove(0).parse::().unwrap(); queue.push((first != second).to_string()); } + "decrease" => + { + let val = queue.remove(0).parse::().unwrap(); + queue.push((val - 1).to_string()); + } + "println" => + { + println!("{}", queue.remove(0)); + } _ => { panic!("Unexpected intrinsic '{}' at {}:{}", intrinsic_name, line, col); @@ -233,6 +256,15 @@ fn interpret_program(operations: &Vec, queue: &mut Vec, funct interpret_program(while_block, queue, functions, intrinsics, debug); } } + Operation::Depth(_, _) => + { + let depth = queue.len(); + queue.push(depth.to_string()); + } + Operation::QueueDiagnostic(line, col) => + { + println!("---Queue state at {}:{}---\nlength: {}\n{:?}\n------------------------------", line, col, queue.len(), queue); + } } if debug { @@ -278,6 +310,7 @@ fn typecheck_block(operations: &Vec, ins: &Vec, outs: &Vec< match operation { Operation::Enqueue(_, _, line, col) | + Operation::Dequeue(line, col) | Operation::Requeue(line, col) | Operation::Dup(line, col) | Operation::Swap(line, col) | @@ -285,7 +318,8 @@ fn typecheck_block(operations: &Vec, ins: &Vec, outs: &Vec< Operation::If(_, _, line, col) | Operation::Intrinsic(_, line, col) | Operation::While(_, line, col) | - Operation::Dequeue(line, col) => (*line, *col), + Operation::QueueDiagnostic(line, col) | + Operation::Depth(line, col) => (*line, *col), } } None => (-1, -1) @@ -443,6 +477,14 @@ fn get_return_type(operations: &Vec, ins: &Vec, functions: outs.insert(0, Datatype::Bool); typecheck_block(while_block, type_queue, &outs, functions, intrinsics, debug); } + Operation::Depth(_, _) => + { + type_queue.push(Datatype::Int); + } + Operation::QueueDiagnostic(line, col) => + { + println!("---Type queue state at {}:{}---\nlength: {}\n{:?}\n------------------------------", line, col, type_queue.len(), type_queue); + } } if debug { @@ -475,7 +517,8 @@ fn validate_function_calls_in_block(block: &Vec, functions: &Vec {}, + Operation::Depth(_, _) | Operation::QueueDiagnostic(_, _) | 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) @@ -512,7 +555,7 @@ fn extract_functions(tokens: &mut Vec, intrinsics: &HashMap<&str, (Vec = Vec::new(); loop @@ -573,8 +616,8 @@ fn extract_functions(tokens: &mut Vec, intrinsics: &HashMap<&str, (Vec outs.push(Datatype::Any), "str" => outs.push(Datatype::String), "int" => outs.push(Datatype::Int), - "bool" => ins.push(Datatype::Bool), - "{" | "}" | "deq" | "req" | "dup" | "swp" | "true" | "false" => panic!("Expected function name but got {} at {}:{}", word, line, col), + "bool" => outs.push(Datatype::Bool), + "{" | "}" | "deq" | "req" | "dup" | "swp" | "true" | "false" | "depth" | "???" => panic!("Expected function name but got {} at {}:{}", word, line, col), _ => { if functions.iter().any(|x| &x.name == word) @@ -704,6 +747,14 @@ fn parse_until_delimiter(tokens_iter: &mut Peekable>, in { operations.push(Operation::Swap(*line, *col)); } + else if word == "depth" + { + operations.push(Operation::Depth(*line, *col)); + } + else if word == "???" + { + operations.push(Operation::QueueDiagnostic(*line, *col)); + } else if Some(word.as_str()) == delimiter { return operations; diff --git a/tests/invalid_function_name_intrinsic.qbl b/tests/invalid_function_name_intrinsic.qbl index 69807a4..a6e5833 100644 --- a/tests/invalid_function_name_intrinsic.qbl +++ b/tests/invalid_function_name_intrinsic.qbl @@ -5,4 +5,4 @@ function int => print deq } -42 print \ No newline at end of file +42 print diff --git a/tests/missing_function_name.qbl b/tests/missing_function_name.qbl index b832e04..dd7c237 100644 --- a/tests/missing_function_name.qbl +++ b/tests/missing_function_name.qbl @@ -3,4 +3,6 @@ function int => { deq -} \ No newline at end of file +} + +42 print diff --git a/tests/rule110.qbl b/tests/rule110.qbl new file mode 100644 index 0000000..7f5dad1 --- /dev/null +++ b/tests/rule110.qbl @@ -0,0 +1,25 @@ + +function bool bool bool => bool rule110 +{ + if + { + if + { + if + { + false + } + else + { + true + } + } + } + else + { + if + { + deq true + } + } +}