Add interpreter
This commit is contained in:
parent
abfb3d2f3d
commit
48cb618d5a
93
src/main.rs
93
src/main.rs
@ -74,11 +74,13 @@ fn main()
|
|||||||
usage()
|
usage()
|
||||||
}
|
}
|
||||||
let mut debug = false;
|
let mut debug = false;
|
||||||
|
let mut interpret = false;
|
||||||
for arg in &args[3..]
|
for arg in &args[3..]
|
||||||
{
|
{
|
||||||
match arg.as_str()
|
match arg.as_str()
|
||||||
{
|
{
|
||||||
"-d" | "--debug" => debug = true,
|
"-d" | "--debug" => debug = true,
|
||||||
|
"-i" | "--interpret" => interpret = true,
|
||||||
_ => panic!("Unknown option {}", arg),
|
_ => panic!("Unknown option {}", arg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,11 +99,96 @@ fn main()
|
|||||||
println!("---Done validating function calls---");
|
println!("---Done validating function calls---");
|
||||||
typecheck(&operations, &functions, &intrinsics, debug);
|
typecheck(&operations, &functions, &intrinsics, debug);
|
||||||
println!("---Done typechecking---");
|
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])
|
_ => panic!("Unknown option {}", args[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn interpret_program(operations: &Vec<Operation>, queue: &mut Vec<String>, functions: &Vec<Function>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, 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::<i64>().unwrap();
|
||||||
|
let subtrahend = queue.remove(0).parse::<i64>().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<Operation>, functions: &Vec<Function>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, debug: bool)
|
fn typecheck(operations: &Vec<Operation>, functions: &Vec<Function>, intrinsics: &HashMap<&str, (Vec<Datatype>, Vec<Datatype>)>, debug: bool)
|
||||||
{
|
{
|
||||||
for function in functions
|
for function in functions
|
||||||
@ -403,13 +490,17 @@ 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),
|
||||||
"{" | "}" => 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)
|
if functions.iter().any(|x| &x.name == word)
|
||||||
{
|
{
|
||||||
panic!("Redeclaration of function '{}' at {}:{}", word, line, col);
|
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
|
if debug
|
||||||
{
|
{
|
||||||
println!("outs: {:?}", outs);
|
println!("outs: {:?}", outs);
|
||||||
|
Reference in New Issue
Block a user