✅ another test
parent
eb5a1947a1
commit
8a2807f879
|
@ -1,2 +1,3 @@
|
|||
/luac.out
|
||||
/target
|
||||
/untracked
|
||||
|
|
187
src/main.rs
187
src/main.rs
|
@ -1,7 +1,14 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
#[derive (Debug)]
|
||||
enum Instruction {
|
||||
VarArgPrep (i32),
|
||||
Add (u8, u8, u8),
|
||||
|
||||
Call (u8, u8, u8),
|
||||
Closure (u8, i32),
|
||||
|
||||
// Equals Constant?
|
||||
EqK (u8, u8, u8),
|
||||
|
||||
// Get Table, Upvalue
|
||||
GetTabUp (u8, u8, u8),
|
||||
|
@ -9,9 +16,6 @@ enum Instruction {
|
|||
// Get Immediate?
|
||||
GetI (u8, u8, u8),
|
||||
|
||||
// Equals Constant?
|
||||
EqK (u8, u8, u8),
|
||||
|
||||
// Jump
|
||||
Jmp (i32),
|
||||
|
||||
|
@ -21,12 +25,15 @@ enum Instruction {
|
|||
// Load Constant
|
||||
LoadK (u8, i32),
|
||||
|
||||
// MetaMethod, Binary
|
||||
MmBin (u8, u8, u8),
|
||||
|
||||
Call (u8, u8, u8),
|
||||
Closure (u8, i32),
|
||||
Move (u8, u8),
|
||||
|
||||
// (A, B, _C) Return B - 1 registers starting with A
|
||||
Return (u8, u8, u8),
|
||||
|
||||
VarArgPrep (i32),
|
||||
}
|
||||
|
||||
#[derive (Clone, Debug, PartialEq)]
|
||||
|
@ -35,7 +42,6 @@ enum Value {
|
|||
False,
|
||||
True,
|
||||
Float (f64),
|
||||
Integer (i64),
|
||||
String (String),
|
||||
|
||||
// These are all bogus, I haven't figured out how to implement
|
||||
|
@ -66,7 +72,22 @@ impl From <&str> for Value {
|
|||
|
||||
impl From <i32> for Value {
|
||||
fn from (x: i32) -> Self {
|
||||
Self::Integer (x as i64)
|
||||
Self::Float (f64::try_from (x).unwrap ())
|
||||
}
|
||||
}
|
||||
|
||||
impl From <f64> for Value {
|
||||
fn from (x: f64) -> Self {
|
||||
Self::Float (x)
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
fn as_float (&self) -> Option <f64> {
|
||||
match self {
|
||||
Self::Float (x) => Some (*x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,6 +113,20 @@ impl Default for VirtualMachine {
|
|||
}
|
||||
|
||||
impl VirtualMachine {
|
||||
fn upvalues_from_args <I: Iterator <Item = String>> (args: I) -> Vec <Value>
|
||||
{
|
||||
let arg = args.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 ());
|
||||
|
||||
vec! [
|
||||
Value::BogusEnv (env),
|
||||
]
|
||||
}
|
||||
|
||||
fn execute_chunk (&mut self, chunk: &Chunk, upvalues: &Vec <Value>)
|
||||
-> Vec <Value> {
|
||||
let max_iters = 2000;
|
||||
|
@ -103,6 +138,16 @@ impl VirtualMachine {
|
|||
let k = &chunk.constants;
|
||||
|
||||
match instruction {
|
||||
Instruction::Add (a, b, c) => {
|
||||
let a = usize::try_from (*a).unwrap ();
|
||||
let b = usize::try_from (*b).unwrap ();
|
||||
let c = usize::try_from (*c).unwrap ();
|
||||
|
||||
let v_b = r [b].as_float ().unwrap ();
|
||||
let v_c = r [c].as_float ().unwrap ();
|
||||
|
||||
r [a] = (v_b + v_c).into ();
|
||||
},
|
||||
Instruction::Call (a, b, c) => {
|
||||
// Take arguments from registers [a + 1, a + b)
|
||||
// Call the function in register [a]
|
||||
|
@ -112,14 +157,15 @@ impl VirtualMachine {
|
|||
//
|
||||
// e.g. CALL 0 2 1 mean "Call 0 with 1 argument, return 1 value", like for printing a constant
|
||||
|
||||
// TODO: Only implement printing constants for now
|
||||
// TODO: Only implement printing values for now
|
||||
|
||||
let a = usize::try_from (*a).unwrap ();
|
||||
|
||||
assert_eq! (r.get (a).unwrap (), &Value::BogusPrint);
|
||||
assert_eq! (*b, 2);
|
||||
assert_eq! (*c, 1);
|
||||
|
||||
println! ("{:?}", r [a + 1]);
|
||||
println! ("{:?}", r.get (a + 1).unwrap ());
|
||||
},
|
||||
Instruction::EqK (a, b, c_k) => {
|
||||
let a = usize::try_from (*a).unwrap ();
|
||||
|
@ -178,6 +224,26 @@ impl VirtualMachine {
|
|||
|
||||
r [a] = k [bx].clone ();
|
||||
},
|
||||
Instruction::MmBin (a, b, c) => {
|
||||
let a = usize::try_from (*a).unwrap ();
|
||||
let b = usize::try_from (*b).unwrap ();
|
||||
|
||||
let a = &r [a];
|
||||
let b = &r [b];
|
||||
|
||||
if a.as_float().is_some() && b.as_float().is_some () {
|
||||
// No need for metamethods
|
||||
}
|
||||
else {
|
||||
panic! ("Not sure how to implememtn OP_MMBIN for these 2 values {a:?}, {b:?}");
|
||||
}
|
||||
},
|
||||
Instruction::Move (a, b) => {
|
||||
let a = usize::try_from (*a).unwrap ();
|
||||
let b = usize::try_from (*b).unwrap ();
|
||||
|
||||
r [a] = r [b].clone ();
|
||||
},
|
||||
Instruction::Return (a, b, _c) => {
|
||||
let a = usize::try_from (*a).unwrap ();
|
||||
let b = usize::try_from (*b).unwrap ();
|
||||
|
@ -185,7 +251,7 @@ impl VirtualMachine {
|
|||
return self.registers [a..(a + b - 1)].to_vec();
|
||||
},
|
||||
Instruction::VarArgPrep (_) => (),
|
||||
_ => (),
|
||||
x => panic! ("Unimplemented instruction {x:?}"),
|
||||
}
|
||||
|
||||
self.program_counter += 1;
|
||||
|
@ -196,45 +262,26 @@ impl VirtualMachine {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let arg: Vec <_> = std::env::args ().collect ();
|
||||
|
||||
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),
|
||||
Instruction::LoadK (0, 0),
|
||||
Instruction::LoadI (1, 3),
|
||||
Instruction::Add (2, 0, 1),
|
||||
Instruction::MmBin (0, 1, 6),
|
||||
Instruction::GetTabUp (3, 0, 1),
|
||||
Instruction::Move (4, 2),
|
||||
Instruction::Call (3, 2, 1),
|
||||
Instruction::Return (2, 2, 1),
|
||||
Instruction::Return (3, 1, 1),
|
||||
],
|
||||
constants: vec! [
|
||||
"arg",
|
||||
"93",
|
||||
"print",
|
||||
"it's 93",
|
||||
"it's not 93",
|
||||
].into_iter ().map (|s| Value::from (s)).collect (),
|
||||
0.5.into (),
|
||||
"print".into (),
|
||||
],
|
||||
};
|
||||
|
||||
let env = BTreeMap::from_iter ([
|
||||
("arg", Value::BogusArg (arg.clone ())),
|
||||
("print", Value::BogusPrint),
|
||||
].map (|(k, v)| (k.to_string (), v)).into_iter ());
|
||||
|
||||
let upvalues = vec! [
|
||||
Value::BogusEnv (env),
|
||||
];
|
||||
let upvalues = VirtualMachine::upvalues_from_args (std::env::args ());
|
||||
|
||||
let mut vm = VirtualMachine::default ();
|
||||
println! ("Returned: {:?}", vm.execute_chunk (&chunk, &upvalues));
|
||||
|
@ -244,6 +291,48 @@ fn main() {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn floats () {
|
||||
/*
|
||||
local a = 0.5
|
||||
local b = 3
|
||||
|
||||
local x = a + b
|
||||
|
||||
print (x)
|
||||
return x
|
||||
*/
|
||||
|
||||
let chunk = Chunk {
|
||||
instructions: vec! [
|
||||
Instruction::VarArgPrep (0),
|
||||
Instruction::LoadK (0, 0),
|
||||
Instruction::LoadI (1, 3),
|
||||
Instruction::Add (2, 0, 1),
|
||||
Instruction::MmBin (0, 1, 6),
|
||||
Instruction::GetTabUp (3, 0, 1),
|
||||
Instruction::Move (4, 2),
|
||||
Instruction::Call (3, 2, 1),
|
||||
Instruction::Return (2, 2, 1),
|
||||
Instruction::Return (3, 1, 1),
|
||||
],
|
||||
constants: vec! [
|
||||
0.5.into (),
|
||||
"print".into (),
|
||||
],
|
||||
};
|
||||
|
||||
for (arg, expected) in [
|
||||
(vec! ["_exe_name"], vec! [3.5.into ()]),
|
||||
] {
|
||||
let mut vm = VirtualMachine::default ();
|
||||
let upvalues = VirtualMachine::upvalues_from_args (arg.into_iter ().map (|s| s.to_string ()));
|
||||
let actual = vm.execute_chunk (&chunk, &upvalues);
|
||||
|
||||
assert_eq! (actual, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_93 () {
|
||||
/*
|
||||
|
@ -290,18 +379,8 @@ mod tests {
|
|||
(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 upvalues = VirtualMachine::upvalues_from_args (arg.into_iter ().map (|s| s.to_string ()));
|
||||
let actual = vm.execute_chunk (&chunk, &upvalues);
|
||||
|
||||
assert_eq! (actual, expected);
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
local a = 0.5
|
||||
local b = 3
|
||||
|
||||
local x = a + b
|
||||
|
||||
print (x)
|
||||
return x
|
Loading…
Reference in New Issue