Make while swallow the input

This commit is contained in:
0x4261756D 2022-12-14 11:46:39 +01:00
parent 89a7780d10
commit c2800dfcc7
1 changed files with 66 additions and 7 deletions

View File

@ -54,7 +54,10 @@ enum Operation
{ {
Enqueue(Datatype, String, i32, i32), Enqueue(Datatype, String, i32, i32),
Dequeue(i32, i32), Dequeue(i32, i32),
// TODO: req can be implemented in terms of dup and dequeue
Requeue(i32, i32), Requeue(i32, i32),
Swap(i32, i32),
Dup(i32, i32),
Intrinsic(String, i32, i32), Intrinsic(String, i32, i32),
FunctionCall(String, i32, i32), FunctionCall(String, i32, i32),
If(Vec<Operation>, Option<Vec<Operation>>, i32, i32), If(Vec<Operation>, Option<Vec<Operation>>, i32, i32),
@ -67,6 +70,7 @@ fn main()
[ [
("print", (Vec::from([Datatype::Any]), Vec::new())), ("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]))),
("+", (Vec::from([Datatype::Int, Datatype::Int]), Vec::from([Datatype::Int]))),
]); ]);
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
if args.len() < 2 if args.len() < 2
@ -132,6 +136,18 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
let val = queue.remove(0); let val = queue.remove(0);
queue.push(val); 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, _, _) => Operation::FunctionCall(function_name, _, _) =>
{ {
interpret_program(&functions.iter().find(|x| &x.name == function_name).unwrap().content, queue, functions, intrinsics, debug); 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<Operation>, queue: &mut Vec<String>, funct
let subtrahend = queue.remove(0).parse::<i64>().unwrap(); let subtrahend = queue.remove(0).parse::<i64>().unwrap();
queue.push((minuend - subtrahend).to_string()); queue.push((minuend - subtrahend).to_string());
} }
"+" =>
{
let addend1 = queue.remove(0).parse::<i64>().unwrap();
let addend2 = queue.remove(0).parse::<i64>().unwrap();
queue.push((addend1 + addend2).to_string());
}
_ => _ =>
{ {
panic!("Unexpected intrinsic '{}' at {}:{}", intrinsic_name, line, col); panic!("Unexpected intrinsic '{}' at {}:{}", intrinsic_name, line, col);
@ -173,7 +195,7 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
{ {
loop loop
{ {
let val = queue.get(0).unwrap(); let val = queue.remove(0);
if val == "0" if val == "0"
{ {
break; break;
@ -227,6 +249,8 @@ fn typecheck_block(operations: &Vec<Operation>, ins: &Vec<Datatype>, outs: &Vec<
{ {
Operation::Enqueue(_, _, line, col) | Operation::Enqueue(_, _, line, col) |
Operation::Requeue(line, col) | Operation::Requeue(line, col) |
Operation::Dup(line, col) |
Operation::Swap(line, col) |
Operation::FunctionCall(_, line, col) | Operation::FunctionCall(_, line, col) |
Operation::If(_, _, line, col) | Operation::If(_, _, line, col) |
Operation::Intrinsic(_, line, col) | Operation::Intrinsic(_, line, col) |
@ -265,6 +289,17 @@ fn get_return_type(operations: &Vec<Operation>, ins: &Vec<Datatype>, functions:
{ {
type_queue.push(*datatype); 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) => Operation::Requeue(line, col) =>
{ {
if type_queue.is_empty() if type_queue.is_empty()
@ -274,6 +309,21 @@ fn get_return_type(operations: &Vec<Operation>, ins: &Vec<Datatype>, functions:
let typ = type_queue.remove(0); let typ = type_queue.remove(0);
type_queue.push(typ); 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) => Operation::FunctionCall(function_name, line, col) =>
{ {
let function = functions.iter().find(|x| &x.name == function_name).unwrap(); let function = functions.iter().find(|x| &x.name == function_name).unwrap();
@ -350,7 +400,7 @@ fn get_return_type(operations: &Vec<Operation>, ins: &Vec<Datatype>, functions:
{ {
panic!("Encountered while block with an empty queue at {}:{}", line, col); 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 if comparison_type != Datatype::Int
{ {
panic!("Expected an int as a while condition but got {:?} instead at {}:{}", comparison_type, line, col); 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<Operation>, ins: &Vec<Datatype>, functions:
{ {
println!("Starting to typecheck while block"); 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 if debug
@ -393,12 +445,12 @@ fn validate_function_calls_in_block(block: &Vec<Operation>, functions: &Vec<Func
{ {
match operation match operation
{ {
Operation::Intrinsic(_, _, _) | Operation::Enqueue(_, _, _, _) | Operation::Dequeue(_, _) | Operation::Requeue(_, _) => {}, Operation::Intrinsic(_, _, _) | Operation::Enqueue(_, _, _, _) | Operation::Dequeue(_, _) | Operation::Requeue(_, _) | Operation::Dup(_, _) | Operation::Swap(_, _) => {},
Operation::FunctionCall(function_name, line, col) => Operation::FunctionCall(function_name, line, col) =>
{ {
if !functions.iter().any(|x| &x.name == function_name) 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, _, _) => Operation::If(if_block, maybe_else_block, _, _) =>
@ -490,7 +542,7 @@ fn extract_functions(tokens: &mut Vec<Token>, intrinsics: &HashMap<&str, (Vec<Da
"any" => outs.push(Datatype::Any), "any" => outs.push(Datatype::Any),
"str" => outs.push(Datatype::String), "str" => outs.push(Datatype::String),
"int" => outs.push(Datatype::Int), "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) if functions.iter().any(|x| &x.name == word)
@ -606,9 +658,16 @@ fn parse_until_delimiter(tokens_iter: &mut Peekable<std::slice::Iter<Token>>, in
} }
else if word == "req" else if word == "req"
{ {
operations.push(Operation::Requeue(*line, *col)); 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 else if Some(word.as_str()) == delimiter
{ {
return operations; return operations;