diff --git a/src/loader.rs b/src/loader.rs index 531dac7..983e1b2 100644 --- a/src/loader.rs +++ b/src/loader.rs @@ -251,19 +251,25 @@ pub fn parse_block (rdr: &mut R, blocks: &mut Vec ) } let upvalue_count = parse_int (rdr).unwrap () as usize; - + let mut upvalues = Vec::with_capacity (upvalue_count); for _ in 0..upvalue_count { - // Just ignore these + let in_stack = parse_byte (rdr).unwrap () == 1; + let idx = parse_byte (rdr).unwrap (); + let kind = parse_byte (rdr).unwrap (); - for _ in 0..3 { - parse_byte (rdr).unwrap (); - } + let upvalue = crate::state::Upvalue { + in_stack, + idx, + kind, + }; + + upvalues.push (upvalue); } blocks.push (Block { constants, instructions, - upvalue_count, + upvalues, }); // Recursion diff --git a/src/state.rs b/src/state.rs index a96fcae..086142e 100644 --- a/src/state.rs +++ b/src/state.rs @@ -8,11 +8,18 @@ use crate::{ }, }; +#[derive (Debug)] +pub struct Upvalue { + pub in_stack: bool, + pub idx: u8, + pub kind: u8, +} + #[derive (Debug)] pub struct Block { pub instructions: Vec , pub constants: Vec , - pub upvalue_count: usize, + pub upvalues: Vec , } #[derive (Debug)] @@ -345,7 +352,14 @@ impl State { let b = usize::try_from (*b).unwrap (); - *self.reg_mut (*a) = upvalues [b].clone (); + let upvalue = match upvalues.get (b) { + Some (x) => x.clone (), + None => { + dbg! (chunk, &self); + panic! ("Missing upvalue"); + } + }; + *self.reg_mut (*a) = upvalue; }, Instruction::Jmp (s_j) => next_pc += s_j, Instruction::Len (a, b) => { @@ -420,7 +434,7 @@ impl State { _ => panic! ("Impossible"), }; - let upvalue_count = chunk.blocks [closure_idx].upvalue_count; + let upvalue_count = chunk.blocks [closure_idx].upvalues.len (); let start_reg = a + popped_frame.register_offset - upvalue_count; diff --git a/src/tests.rs b/src/tests.rs index 1ee7c47..b2dd596 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -93,7 +93,7 @@ fn bools () { "arg".into (), "print".into (), ], - upvalue_count: 1, + upvalues: vec! [], }, Block { instructions: vec! [ @@ -107,7 +107,7 @@ fn bools () { Inst::Return0, ], constants: vec! [], - upvalue_count: 0, + upvalues: vec! [], }, ], }; @@ -164,7 +164,7 @@ fn floats () { 0.5.into (), "print".into (), ], - upvalue_count: 1, + upvalues: vec! [], }; let chunk = Chunk { blocks: vec! [block], @@ -187,8 +187,10 @@ fn floats () { fn fma () { let bytecode = include_bytes! ("../test_vectors/fma.luac"); let mut rdr = std::io::Cursor::new (bytecode); - let file = crate::loader::parse_chunk (&mut rdr).unwrap (); - assert_eq! (file.blocks.len (), 4); + let chunk = crate::loader::parse_chunk (&mut rdr).unwrap (); + assert_eq! (chunk.blocks.len (), 4); + + assert_eq! (chunk.blocks [3].upvalues.len (), 2); for (arg, expected) in [ (vec! ["_exe_name"], vec! [122.into ()]), @@ -197,7 +199,7 @@ fn fma () { let expected: Vec = expected; let mut vm = State::default (); let upvalues = State::upvalues_from_args (arg.into_iter ().map (|s| s.to_string ())); - let actual = vm.execute_chunk (&file, &upvalues); + let actual = vm.execute_chunk (&chunk, &upvalues); assert_eq! (actual, expected); } diff --git a/test_vectors/fma.lua b/test_vectors/fma.lua index f1c8ff4..9006a99 100644 --- a/test_vectors/fma.lua +++ b/test_vectors/fma.lua @@ -1,5 +1,7 @@ -- This one fails :( I haven't implemented closures properly yet. +local ii = "bogus" + local function add (aa, bb) return aa + bb end @@ -12,6 +14,12 @@ local function fma (ee, ff, gg) return add (mul (ee, ff), gg) end -local hh = fma (10, 11, 12) -print (hh) +local function run () + local hh = fma (10, 11, 12) + print (hh) +end + +run () +print (ii) + return hh