✅ extract unit test
parent
8c70469276
commit
eb5a1947a1
142
src/main.rs
142
src/main.rs
|
@ -2,13 +2,30 @@ use std::collections::BTreeMap;
|
||||||
|
|
||||||
enum Instruction {
|
enum Instruction {
|
||||||
VarArgPrep (i32),
|
VarArgPrep (i32),
|
||||||
|
|
||||||
|
// Get Table, Upvalue
|
||||||
GetTabUp (u8, u8, u8),
|
GetTabUp (u8, u8, u8),
|
||||||
|
|
||||||
|
// Get Immediate?
|
||||||
GetI (u8, u8, u8),
|
GetI (u8, u8, u8),
|
||||||
|
|
||||||
|
// Equals Constant?
|
||||||
EqK (u8, u8, u8),
|
EqK (u8, u8, u8),
|
||||||
|
|
||||||
|
// Jump
|
||||||
Jmp (i32),
|
Jmp (i32),
|
||||||
|
|
||||||
|
// Load Integer?
|
||||||
|
LoadI (u8, i32),
|
||||||
|
|
||||||
|
// Load Constant
|
||||||
LoadK (u8, i32),
|
LoadK (u8, i32),
|
||||||
|
|
||||||
|
|
||||||
Call (u8, u8, u8),
|
Call (u8, u8, u8),
|
||||||
Closure (u8, i32),
|
Closure (u8, i32),
|
||||||
|
|
||||||
|
// (A, B, _C) Return B - 1 registers starting with A
|
||||||
Return (u8, u8, u8),
|
Return (u8, u8, u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +35,7 @@ enum Value {
|
||||||
False,
|
False,
|
||||||
True,
|
True,
|
||||||
Float (f64),
|
Float (f64),
|
||||||
|
Integer (i64),
|
||||||
String (String),
|
String (String),
|
||||||
|
|
||||||
// These are all bogus, I haven't figured out how to implement
|
// These are all bogus, I haven't figured out how to implement
|
||||||
|
@ -46,6 +64,12 @@ impl From <&str> for Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From <i32> for Value {
|
||||||
|
fn from (x: i32) -> Self {
|
||||||
|
Self::Integer (x as i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Chunk {
|
struct Chunk {
|
||||||
instructions: Vec <Instruction>,
|
instructions: Vec <Instruction>,
|
||||||
constants: Vec <Value>,
|
constants: Vec <Value>,
|
||||||
|
@ -68,7 +92,8 @@ impl Default for VirtualMachine {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtualMachine {
|
impl VirtualMachine {
|
||||||
fn execute_chunk (&mut self, chunk: &Chunk, upvalues: &Vec <Value>) {
|
fn execute_chunk (&mut self, chunk: &Chunk, upvalues: &Vec <Value>)
|
||||||
|
-> Vec <Value> {
|
||||||
let max_iters = 2000;
|
let max_iters = 2000;
|
||||||
|
|
||||||
for _ in 0..max_iters {
|
for _ in 0..max_iters {
|
||||||
|
@ -135,21 +160,29 @@ impl VirtualMachine {
|
||||||
|
|
||||||
let table = r.get (b).unwrap ();
|
let table = r.get (b).unwrap ();
|
||||||
let value = match table {
|
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!(),
|
_ => unimplemented!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
r [a] = value;
|
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) => {
|
Instruction::LoadK (a, bx) => {
|
||||||
let a = usize::try_from (*a).unwrap ();
|
let a = usize::try_from (*a).unwrap ();
|
||||||
let bx = usize::try_from (*bx).unwrap ();
|
let bx = usize::try_from (*bx).unwrap ();
|
||||||
|
|
||||||
r [a] = k [bx].clone ();
|
r [a] = k [bx].clone ();
|
||||||
},
|
},
|
||||||
Instruction::Return (_a, _b, _c) => {
|
Instruction::Return (a, b, _c) => {
|
||||||
break;
|
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 (_) => (),
|
Instruction::VarArgPrep (_) => (),
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -157,6 +190,8 @@ impl VirtualMachine {
|
||||||
|
|
||||||
self.program_counter += 1;
|
self.program_counter += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
panic! ("Hit max iterations before chunk returned");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,17 +201,21 @@ fn main() {
|
||||||
let chunk = Chunk {
|
let chunk = Chunk {
|
||||||
instructions: vec! [
|
instructions: vec! [
|
||||||
Instruction::VarArgPrep (0),
|
Instruction::VarArgPrep (0),
|
||||||
Instruction::GetTabUp (0, 0, 0),
|
Instruction::GetTabUp (1, 0, 0),
|
||||||
Instruction::GetI (0, 0, 1),
|
Instruction::GetI (1, 1, 1),
|
||||||
Instruction::EqK (0, 1, 0),
|
Instruction::EqK (1, 1, 0),
|
||||||
Instruction::Jmp (4),
|
Instruction::Jmp (6),
|
||||||
Instruction::GetTabUp (0, 0, 2),
|
Instruction::GetTabUp (1, 0, 2),
|
||||||
Instruction::LoadK (1, 3),
|
Instruction::LoadK (2, 3),
|
||||||
Instruction::Call (0, 2, 1),
|
Instruction::Call (1, 2, 1),
|
||||||
Instruction::Jmp (3),
|
Instruction::LoadI (1, 0),
|
||||||
Instruction::GetTabUp (0, 0, 2),
|
Instruction::Return (1, 2, 1),
|
||||||
Instruction::LoadK (1, 4),
|
Instruction::Jmp (5),
|
||||||
Instruction::Call (0, 2, 1),
|
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),
|
Instruction::Return (1, 1, 1),
|
||||||
],
|
],
|
||||||
constants: vec! [
|
constants: vec! [
|
||||||
|
@ -198,5 +237,74 @@ fn main() {
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut vm = VirtualMachine::default ();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
if arg [1] == "93" then
|
|
||||||
print "it's 93"
|
|
||||||
else
|
|
||||||
print "it's not 93"
|
|
||||||
end
|
|
||||||
|
|
||||||
local function unused_fn ()
|
local function unused_fn ()
|
||||||
print "unused"
|
print "unused"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if arg [1] == "93" then
|
||||||
|
print "it's 93"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
print "it's not 93"
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in New Issue