use super::*;
fn exec(instrs: &[Instruction]) -> VM {
let mut vm = VM::new();
vm.execute(&instrs);
vm
}
#[test]
fn simple_numeric_declaration() {
let instrs = vec![
Instruction::Push(RlValue::Num(7)),
Instruction::Push(RlValue::Num(9)),
Instruction::Push(RlValue::Num(3)),
Instruction::Mul,
Instruction::Sub,
Instruction::Declare("num".into()),
];
let vm = exec(&instrs);
assert_eq!(-20, vm.lookup_num("num").unwrap());
}
#[test]
fn string_declaration() {
let instrs = vec![
Instruction::Push(RlValue::Str("some string".into())),
Instruction::Declare("s".into()),
];
let vm = exec(&instrs);
assert_eq!(String::from("some string"), vm.lookup_str("s").unwrap());
}
#[test]
fn range_declaration() {
let instrs = vec![
Instruction::Push(RlValue::Num(5)),
Instruction::Push(RlValue::Num(11)),
Instruction::Push(RlValue::Num(9)),
Instruction::Mul,
Instruction::MakeRange,
Instruction::Declare("xs".into()),
];
let vm = exec(&instrs);
assert_eq!(
(5..=99).collect::<Vec<i32>>(),
vm.lookup_list("xs").unwrap()
);
}
#[test]
fn parameterless_function_declaration_and_invocation() {
let instrs = vec![
Instruction::Push(RlValue::Function(3, 0)),
Instruction::Push(RlValue::Addr(7)),
Instruction::Jump,
Instruction::Push(RlValue::Num(1)),
Instruction::Push(RlValue::Num(4)),
Instruction::Add,
Instruction::Ret,
Instruction::Declare("five".into()),
Instruction::Call("five".into()),
Instruction::Declare("x".into()),
];
let vm = exec(&instrs);
assert_eq!(5, vm.lookup_num("x").unwrap());
}
#[test]
fn function_declaration_and_invocation() {
let instrs = vec![
Instruction::Push(RlValue::Function(3, 3)),
Instruction::Push(RlValue::Addr(14)),
Instruction::Jump,
Instruction::Declare("z".into()),
Instruction::Declare("y".into()),
Instruction::Declare("x".into()),
Instruction::PushLocal("x".into()),
Instruction::PushLocal("z".into()),
Instruction::Add,
Instruction::Declare("mid_way".into()),
Instruction::PushLocal("mid_way".into()),
Instruction::PushLocal("y".into()),
Instruction::Add,
Instruction::Ret,
Instruction::Declare("sum".into()),
Instruction::Push(RlValue::Num(9)),
Instruction::Push(RlValue::Num(8)),
Instruction::Mul,
Instruction::Push(RlValue::Num(8)),
Instruction::Push(RlValue::Num(2)),
Instruction::Sub,
Instruction::Push(RlValue::Num(15)),
Instruction::Mul,
Instruction::Push(RlValue::Num(4)),
Instruction::Push(RlValue::Num(1)),
Instruction::Push(RlValue::Num(3)),
Instruction::Mul,
Instruction::Sub,
Instruction::Call("sum".into()),
Instruction::Declare("res".into()),
];
let vm = exec(&instrs);
assert_eq!(163, vm.lookup_num("res").unwrap());
}