diff --git a/src/loader.rs b/src/loader.rs index a761dd2..55d0cc0 100644 --- a/src/loader.rs +++ b/src/loader.rs @@ -70,8 +70,10 @@ pub fn parse_inst (buf: [u8; 4]) -> Option 0x22 => Inst::Add (a, b, c), 0x24 => Inst::Mul (a, b, c), 0x2e => Inst::MmBin (a, b, c), + 0x33 => Inst::Not (a, b), 0x3c => Inst::EqK (a, b, c), 0x38 => Inst::Jmp (s_j), + 0x42 => Inst::Test (a, k), 0x44 => Inst::Call (a, b, c), 0x45 => Inst::TailCall (a, b, c, k), 0x46 => Inst::Return (a, b, c, k), diff --git a/src/state.rs b/src/state.rs index b48e71a..2f9c713 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,4 +1,7 @@ -use std::collections::BTreeMap; +use std::{ + collections::BTreeMap, + rc::Rc, +}; #[derive (Debug, PartialEq)] pub enum Instruction { @@ -57,27 +60,30 @@ pub enum Instruction { TailCall (u8, u8, u8, bool), - Test (u8, i32), + Test (u8, bool), VarArgPrep (i32), } +#[derive (Clone, Debug, PartialEq)] +pub struct BogusClosure { + idx: usize, + upvalues: Vec , +} + #[derive (Clone, Debug, PartialEq)] pub enum Value { Nil, Boolean (bool), Float (f64), - String (String), + String (Rc ), // These are all bogus, I haven't figured out how to implement // tables and function pointers yet - BogusArg (Vec ), - BogusClosure { - idx: usize, - upvalues: Vec , - }, - BogusEnv (BTreeMap ), + BogusArg (Rc >), + BogusClosure (Rc ), + BogusEnv (Rc >), BogusPrint, } @@ -89,7 +95,7 @@ impl Default for Value { impl From for Value { fn from (x: String) -> Self { - Self::String (x) + Self::String (x.into ()) } } @@ -196,15 +202,15 @@ impl Default for State { impl State { pub fn upvalues_from_args > (args: I) -> Vec { - let arg = args.map (|s| s.to_string ()).collect (); + let arg: Vec <_> = args.map (|s| s.to_string ()).collect (); let env = BTreeMap::from_iter ([ - ("arg", Value::BogusArg (arg)), + ("arg", Value::BogusArg (arg.into ())), ("print", Value::BogusPrint), ].map (|(k, v)| (k.to_string (), v))); vec! [ - Value::BogusEnv (env), + Value::BogusEnv (env.into ()), ] } @@ -262,7 +268,7 @@ impl State { r [a] = (v_b + v_c).into (); }, - Instruction::Call (a, b, c) => { + Instruction::Call (a, _b, c) => { // Take arguments from registers [a + 1, a + b) // Call the function in register [a] // Return values in registers [a, a + c - 1) @@ -278,12 +284,11 @@ impl State { let v_a = r.get (a).unwrap (); match v_a { - Value::BogusClosure { - idx, - upvalues, - }=> { + Value::BogusClosure (rc) => { + let idx = rc.idx; + let block_idx = frame.block_idx; - let target_block = *idx; + let target_block = idx; let current_frame = self.stack.last ().unwrap (); @@ -310,7 +315,7 @@ impl State { assert_eq! (*c, 1); let value = r.get (a + 1).unwrap (); - let s = match value { + match value { Value::Nil => println! ("nil"), Value::Boolean (false) => println! ("false"), Value::Boolean (true) => println! ("true"), @@ -336,10 +341,10 @@ impl State { } let r = self.register_window_mut (); - r [a] = Value::BogusClosure { + r [a] = Value::BogusClosure (BogusClosure { idx: b + frame.block_idx + 1, upvalues: vec! [], - }; + }.into ()); }, Instruction::EqK (a, b, c_k) => { let a = usize::try_from (*a).unwrap (); @@ -365,7 +370,7 @@ impl State { }; let key = match k.get (c).unwrap () { - Value::String (s) => s, + Value::String (s) => s.as_ref (), _ => panic! ("GetTabUp only supports string keys"), }; @@ -393,7 +398,7 @@ impl State { Instruction::GetUpVal (a, b) => { let this_func = self.stack.last ().unwrap ().register_offset - 1; let upvalues = match &self.registers [this_func] { - Value::BogusClosure { idx, upvalues } => upvalues, + Value::BogusClosure (rc) => &rc.upvalues, _ => panic! ("Can't do GetUpVal outside a closure"), }; @@ -461,7 +466,7 @@ impl State { Instruction::Return (a, b, c, k) => { let a = usize::try_from (*a).unwrap (); let b = usize::try_from (*b).unwrap (); - let c = usize::try_from (*c).unwrap (); + let _c = usize::try_from (*c).unwrap (); let popped_frame = self.stack.pop ().unwrap (); @@ -469,20 +474,20 @@ impl State { if *k { let closure_idx = match &self.registers [popped_frame.register_offset + a] { - Value::BogusClosure { idx, upvalues } => idx, + Value::BogusClosure (rc) => rc.idx, _ => panic! ("Impossible"), }; - let upvalue_count = chunk.blocks [*closure_idx].upvalue_count; + let upvalue_count = chunk.blocks [closure_idx].upvalue_count; let start_reg = a + popped_frame.register_offset - upvalue_count; let upvalues = self.registers [start_reg..start_reg+upvalue_count].iter ().cloned ().collect (); - self.registers [a + popped_frame.register_offset] = Value::BogusClosure { - idx: *closure_idx, + self.registers [a + popped_frame.register_offset] = Value::BogusClosure (BogusClosure { + idx: closure_idx, upvalues, - }; + }.into ()); } if self.debug_print { diff --git a/src/tests.rs b/src/tests.rs index 9be3e9b..db2a4ca 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -56,7 +56,7 @@ fn bools () { }, Block { instructions: vec! [ - Inst::Test (0, 0), + Inst::Test (0, false), Inst::Jmp (3), Inst::LoadI (1, 99), Inst::Return1 (1), @@ -211,13 +211,18 @@ fn value_size () { assert! (size_of::> () <= 8); assert! (size_of::> () <= 8); - pub enum Value { + enum Value { Nil, Boolean (bool), Float (f64), String (Rc ), } - assert_eq! (size_of:: (), 16); - assert_eq! (size_of:: (), 16); + let sz = size_of:: (); + let expected = 16; + assert! (sz <= expected, "{sz} > {expected}"); + + let sz = size_of:: (); + let expected = 16; + assert! (sz <= expected, "{sz} > {expected}"); }