diff --git a/lunar_wave_vm/src/state.rs b/lunar_wave_vm/src/state.rs index 6998ee7..2850dd4 100644 --- a/lunar_wave_vm/src/state.rs +++ b/lunar_wave_vm/src/state.rs @@ -55,8 +55,10 @@ pub struct State { pub debug_print: bool, step_count: u32, chunk: Chunk, - upvalues: Vec , + pub upvalues: Vec , pub si: Interner, + register_offset: usize, + block_idx: usize, } fn lw_io_write (l: &mut State, num_args: usize) -> usize { @@ -194,6 +196,8 @@ impl State { chunk, upvalues, si: Default::default (), + register_offset: 0, + block_idx: 0, } } @@ -213,6 +217,8 @@ impl State { chunk, upvalues, si, + register_offset: 0, + block_idx: 0, } } @@ -221,7 +227,7 @@ impl State { frame.block_idx == bp.block_idx && frame.program_counter == bp.program_counter } - fn upvalues_from_args > (si: &mut Interner, args: I) -> Vec + pub fn upvalues_from_args > (si: &mut Interner, args: I) -> Vec { let arg = args.map (|s| si.intern (&s)).enumerate (); let arg = Value::from_iter (arg.map (|(i, v)| (Value::from (i), Value::String (v)))); @@ -266,13 +272,11 @@ impl State { /// Short form to get access to a register within our window pub fn reg (&self, i: u8) -> &Value { - let frame = self.stack.last ().unwrap (); - &self.registers [frame.register_offset + i as usize] + &self.registers [self.register_offset + i as usize] } pub fn reg_mut (&mut self, i: u8) -> &mut Value { - let frame = self.stack.last ().unwrap (); - &mut self.registers [frame.register_offset + i as usize] + &mut self.registers [self.register_offset + i as usize] } // For native functions to check how many args they got @@ -289,18 +293,120 @@ impl State { } } + fn op_add (&mut self, a: u8, b: u8, c: u8) -> bool { + let v_b = self.reg (b); + let v_c = self.reg (c); + + *self.reg_mut (a) = match (v_b, v_c) { + (Value::Float (b), Value::Float (c)) => Value::from (b + c), + (Value::Integer (b), Value::Integer (c)) => Value::from (b + c), + (Value::Integer (b), Value::Float (c)) => Value::from (*b as f64 + c), + (Value::Float (b), Value::Integer (c)) => Value::from (b + *c as f64), + _ => return false, + }; + + true + } + + fn op_get_field (&mut self, a: u8, b: u8, c: u8) { + let block = self.chunk.blocks.get (self.block_idx).unwrap (); + let constants = &block.constants; + + let key = match &constants [usize::from (c)] { + Value::String (s) => s, + _ => panic! ("K[C] must be a string"), + }; + + let val = match &self.registers [self.register_offset + usize::from (b)] { + Value::Nil => panic! ("R[B] must not be nil"), + Value::Table (t) => t.borrow ().get_str (*key).clone (), + _ => panic! ("R[B] must be a table"), + }; + + *self.reg_mut (a) = val; + } + + fn op_get_table (&mut self, a: u8, b: u8, c: u8) { + let t = match self.reg (b) { + Value::Table (t) => t, + _ => panic! ("R[B] must be a table"), + }; + + let key = self.reg (c); + + let val = t.borrow ().get (key.clone ()).clone (); + + *self.reg_mut (a) = val; + } + + fn op_mmbin (&mut self, a: u8, b: u8, _c: u8) { + let a = self.reg (a); + let b = self.reg (b); + + if a.as_float().is_some() && b.as_float().is_some () { + // No need for metamethods + } + else { + panic! ("Not sure how to implement OP_MMBIN for these 2 values {a:?}, {b:?}"); + } + } + + fn op_mul (&mut self, a: u8, b: u8, c: u8) -> bool { + let v_b = self.reg (b); + let v_c = self.reg (c); + + *self.reg_mut (a) = match (v_b, v_c) { + (Value::Float (b), Value::Float (c)) => Value::from (b * c), + (Value::Integer (b), Value::Integer (c)) => Value::from (b * c), + (Value::Integer (b), Value::Float (c)) => Value::from (*b as f64 * c), + (Value::Float (b), Value::Integer (c)) => Value::from (b * *c as f64), + _ => return false, + }; + + true + } + + fn op_set_field (&mut self, a: u8, b: u8, c: u8, k: bool) { + let frame = self.stack.last ().unwrap (); + let block = self.chunk.blocks.get (frame.block_idx).unwrap (); + let constants = &block.constants; + + let value = if k { + &constants [usize::from (c)] + } + else { + self.reg (c) + } + .clone (); + + let b = usize::try_from (b).unwrap (); + + let key = match constants.get (b).unwrap () { + Value::String (s) => *s, + _ => panic! ("SetField only supports string keys"), + }; + + let mut dst = self.reg (a).as_table () + .expect ("SetField only works on tables").borrow_mut (); + + dst.insert_str (key, value); + } + pub fn step (&mut self) -> Result