From eb5a1947a14a3ddd8d24110a846946a57f43d369 Mon Sep 17 00:00:00 2001 From: _ <_@_> Date: Sun, 24 Sep 2023 16:57:12 -0500 Subject: [PATCH] :white_check_mark: extract unit test --- src/main.rs | 142 ++++++++++++++++++++++++++++++++++++----- test_vectors/is_93.lua | 14 ++-- 2 files changed, 133 insertions(+), 23 deletions(-) diff --git a/src/main.rs b/src/main.rs index eb27c9e..03d5bef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,13 +2,30 @@ use std::collections::BTreeMap; enum Instruction { VarArgPrep (i32), + + // Get Table, Upvalue GetTabUp (u8, u8, u8), + + // Get Immediate? GetI (u8, u8, u8), + + // Equals Constant? EqK (u8, u8, u8), + + // Jump Jmp (i32), + + // Load Integer? + LoadI (u8, i32), + + // Load Constant LoadK (u8, i32), + + Call (u8, u8, u8), Closure (u8, i32), + + // (A, B, _C) Return B - 1 registers starting with A Return (u8, u8, u8), } @@ -18,6 +35,7 @@ enum Value { False, True, Float (f64), + Integer (i64), String (String), // These are all bogus, I haven't figured out how to implement @@ -46,6 +64,12 @@ impl From <&str> for Value { } } +impl From for Value { + fn from (x: i32) -> Self { + Self::Integer (x as i64) + } +} + struct Chunk { instructions: Vec , constants: Vec , @@ -68,7 +92,8 @@ impl Default for VirtualMachine { } impl VirtualMachine { - fn execute_chunk (&mut self, chunk: &Chunk, upvalues: &Vec ) { + fn execute_chunk (&mut self, chunk: &Chunk, upvalues: &Vec ) + -> Vec { let max_iters = 2000; for _ in 0..max_iters { @@ -135,21 +160,29 @@ impl VirtualMachine { let table = r.get (b).unwrap (); let value = match table { - Value::BogusArg (arg) => arg.get (c).unwrap ().as_str().into (), + Value::BogusArg (arg) => arg.get (c).map (|x| x.as_str().into ()).unwrap_or_default(), _ => unimplemented!(), }; r [a] = value; }, - Instruction::Jmp (sJ) => self.program_counter += sJ, + Instruction::Jmp (s_j) => self.program_counter += s_j, + Instruction::LoadI (a, sbx) => { + let a = usize::try_from (*a).unwrap (); + + r [a] = (*sbx).into (); + }, Instruction::LoadK (a, bx) => { let a = usize::try_from (*a).unwrap (); let bx = usize::try_from (*bx).unwrap (); r [a] = k [bx].clone (); }, - Instruction::Return (_a, _b, _c) => { - break; + Instruction::Return (a, b, _c) => { + let a = usize::try_from (*a).unwrap (); + let b = usize::try_from (*b).unwrap (); + + return self.registers [a..(a + b - 1)].to_vec(); }, Instruction::VarArgPrep (_) => (), _ => (), @@ -157,6 +190,8 @@ impl VirtualMachine { self.program_counter += 1; } + + panic! ("Hit max iterations before chunk returned"); } } @@ -166,17 +201,21 @@ fn main() { let chunk = Chunk { instructions: vec! [ Instruction::VarArgPrep (0), - Instruction::GetTabUp (0, 0, 0), - Instruction::GetI (0, 0, 1), - Instruction::EqK (0, 1, 0), - Instruction::Jmp (4), - Instruction::GetTabUp (0, 0, 2), - Instruction::LoadK (1, 3), - Instruction::Call (0, 2, 1), - Instruction::Jmp (3), - Instruction::GetTabUp (0, 0, 2), - Instruction::LoadK (1, 4), - Instruction::Call (0, 2, 1), + Instruction::GetTabUp (1, 0, 0), + Instruction::GetI (1, 1, 1), + Instruction::EqK (1, 1, 0), + Instruction::Jmp (6), + Instruction::GetTabUp (1, 0, 2), + Instruction::LoadK (2, 3), + Instruction::Call (1, 2, 1), + Instruction::LoadI (1, 0), + Instruction::Return (1, 2, 1), + Instruction::Jmp (5), + Instruction::GetTabUp (1, 0, 2), + Instruction::LoadK (2, 4), + Instruction::Call (1, 2, 1), + Instruction::LoadI (1, 1), + Instruction::Return (1, 2, 1), Instruction::Return (1, 1, 1), ], constants: vec! [ @@ -198,5 +237,74 @@ fn main() { ]; let mut vm = VirtualMachine::default (); - vm.execute_chunk (&chunk, &upvalues); + println! ("Returned: {:?}", vm.execute_chunk (&chunk, &upvalues)); +} + +#[cfg (test)] +mod tests { + use super::*; + + #[test] + fn is_93 () { + /* + if arg [1] == "93" then + print "it's 93" + return 0 + else + print "it's not 93" + return 1 + end + */ + + let chunk = Chunk { + instructions: vec! [ + Instruction::VarArgPrep (0), + Instruction::GetTabUp (1, 0, 0), + Instruction::GetI (1, 1, 1), + Instruction::EqK (1, 1, 0), + Instruction::Jmp (6), + Instruction::GetTabUp (1, 0, 2), + Instruction::LoadK (2, 3), + Instruction::Call (1, 2, 1), + Instruction::LoadI (1, 0), + Instruction::Return (1, 2, 1), + Instruction::Jmp (5), + Instruction::GetTabUp (1, 0, 2), + Instruction::LoadK (2, 4), + Instruction::Call (1, 2, 1), + Instruction::LoadI (1, 1), + Instruction::Return (1, 2, 1), + Instruction::Return (1, 1, 1), + ], + constants: vec! [ + "arg", + "93", + "print", + "it's 93", + "it's not 93", + ].into_iter ().map (|s| Value::from (s)).collect (), + }; + + for (arg, expected) in [ + (vec! ["_exe_name"], vec! [1.into ()]), + (vec! ["_exe_name", "93"], vec! [0.into ()]), + (vec! ["_exe_name", "94"], vec! [1.into ()]), + ] { + let arg = arg.into_iter ().map (|s| s.to_string ()).collect (); + + let env = BTreeMap::from_iter ([ + ("arg", Value::BogusArg (arg)), + ("print", Value::BogusPrint), + ].map (|(k, v)| (k.to_string (), v)).into_iter ()); + + let upvalues = vec! [ + Value::BogusEnv (env), + ]; + + let mut vm = VirtualMachine::default (); + let actual = vm.execute_chunk (&chunk, &upvalues); + + assert_eq! (actual, expected); + } + } } diff --git a/test_vectors/is_93.lua b/test_vectors/is_93.lua index bfb84d0..4df7016 100644 --- a/test_vectors/is_93.lua +++ b/test_vectors/is_93.lua @@ -1,9 +1,11 @@ -if arg [1] == "93" then - print "it's 93" -else - print "it's not 93" -end - local function unused_fn () print "unused" end + +if arg [1] == "93" then + print "it's 93" + return 0 +else + print "it's not 93" + return 1 +end