Add new operations and intrinsics

This commit is contained in:
0x4261756D 2022-12-15 20:34:56 +01:00
parent d1883ff3ab
commit 0de0838284
4 changed files with 87 additions and 9 deletions

View File

@ -64,6 +64,8 @@ enum Operation
FunctionCall(String, i32, i32), FunctionCall(String, i32, i32),
If(Vec<Operation>, Option<Vec<Operation>>, i32, i32), If(Vec<Operation>, Option<Vec<Operation>>, i32, i32),
While(Vec<Operation>, i32, i32), While(Vec<Operation>, i32, i32),
Depth(i32, i32),
QueueDiagnostic(i32, i32),
} }
fn main() fn main()
@ -71,12 +73,14 @@ fn main()
let intrinsics: HashMap<&str, (Vec<Datatype>, Vec<Datatype>)> = HashMap::from( let intrinsics: HashMap<&str, (Vec<Datatype>, Vec<Datatype>)> = HashMap::from(
[ [
("print", (Vec::from([Datatype::Any]), Vec::new())), ("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::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]))),
("==", (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<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
if args.len() < 2 if args.len() < 2
@ -156,12 +160,22 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
} }
Operation::FunctionCall(function_name, _, _) => 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<String> = &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, _, _) => Operation::If(if_block, maybe_else_block, _, _) =>
{ {
let val = queue.remove(0); let val = queue.remove(0);
// TODO: Add bool type
if val == "true" if val == "true"
{ {
interpret_program(if_block, queue, functions, intrinsics, debug); interpret_program(if_block, queue, functions, intrinsics, debug);
@ -215,6 +229,15 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
let second = queue.remove(0).parse::<i64>().unwrap(); let second = queue.remove(0).parse::<i64>().unwrap();
queue.push((first != second).to_string()); queue.push((first != second).to_string());
} }
"decrease" =>
{
let val = queue.remove(0).parse::<i64>().unwrap();
queue.push((val - 1).to_string());
}
"println" =>
{
println!("{}", queue.remove(0));
}
_ => _ =>
{ {
panic!("Unexpected intrinsic '{}' at {}:{}", intrinsic_name, line, col); panic!("Unexpected intrinsic '{}' at {}:{}", intrinsic_name, line, col);
@ -233,6 +256,15 @@ fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, funct
interpret_program(while_block, queue, functions, intrinsics, debug); 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 if debug
{ {
@ -278,6 +310,7 @@ fn typecheck_block(operations: &Vec<Operation>, ins: &Vec<Datatype>, outs: &Vec<
match operation match operation
{ {
Operation::Enqueue(_, _, line, col) | Operation::Enqueue(_, _, line, col) |
Operation::Dequeue(line, col) |
Operation::Requeue(line, col) | Operation::Requeue(line, col) |
Operation::Dup(line, col) | Operation::Dup(line, col) |
Operation::Swap(line, col) | Operation::Swap(line, col) |
@ -285,7 +318,8 @@ fn typecheck_block(operations: &Vec<Operation>, ins: &Vec<Datatype>, outs: &Vec<
Operation::If(_, _, line, col) | Operation::If(_, _, line, col) |
Operation::Intrinsic(_, line, col) | Operation::Intrinsic(_, line, col) |
Operation::While(_, 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) None => (-1, -1)
@ -443,6 +477,14 @@ fn get_return_type(operations: &Vec<Operation>, ins: &Vec<Datatype>, functions:
outs.insert(0, Datatype::Bool); outs.insert(0, Datatype::Bool);
typecheck_block(while_block, type_queue, &outs, functions, intrinsics, debug); 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 if debug
{ {
@ -475,7 +517,8 @@ 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::Dup(_, _) | Operation::Swap(_, _) => {}, Operation::Depth(_, _) | Operation::QueueDiagnostic(_, _) | 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)
@ -512,7 +555,7 @@ fn extract_functions(tokens: &mut Vec<Token>, intrinsics: &HashMap<&str, (Vec<Da
{ {
if debug if debug
{ {
print!("Found a function at {}:{}", line, col); println!("Found a function at {}:{}", line, col);
} }
let mut ins: Vec<Datatype> = Vec::new(); let mut ins: Vec<Datatype> = Vec::new();
loop loop
@ -573,8 +616,8 @@ 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),
"bool" => ins.push(Datatype::Bool), "bool" => outs.push(Datatype::Bool),
"{" | "}" | "deq" | "req" | "dup" | "swp" | "true" | "false" => panic!("Expected function name but got {} at {}:{}", word, line, col), "{" | "}" | "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) if functions.iter().any(|x| &x.name == word)
@ -704,6 +747,14 @@ fn parse_until_delimiter(tokens_iter: &mut Peekable<std::slice::Iter<Token>>, in
{ {
operations.push(Operation::Swap(*line, *col)); 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 else if Some(word.as_str()) == delimiter
{ {
return operations; return operations;

View File

@ -5,4 +5,4 @@ function int => print
deq deq
} }
42 print 42 print

View File

@ -3,4 +3,6 @@
function int => function int =>
{ {
deq deq
} }
42 print

25
tests/rule110.qbl Normal file
View File

@ -0,0 +1,25 @@
function bool bool bool => bool rule110
{
if
{
if
{
if
{
false
}
else
{
true
}
}
}
else
{
if
{
deq true
}
}
}