implement a couple more opcodes fighting the closure issue
parent
4da634a2aa
commit
f0d4f25cec
78
src/state.rs
78
src/state.rs
|
@ -167,7 +167,7 @@ impl State {
|
||||||
let v_b = self.reg (*b);
|
let v_b = self.reg (*b);
|
||||||
let v_c = self.reg (*c);
|
let v_c = self.reg (*c);
|
||||||
|
|
||||||
let sum = if let (Some (v_b), Some (v_c)) = (v_b.as_int (), v_c.as_int ())
|
let x = if let (Some (v_b), Some (v_c)) = (v_b.as_int (), v_c.as_int ())
|
||||||
{
|
{
|
||||||
Value::from (v_b + v_c)
|
Value::from (v_b + v_c)
|
||||||
}
|
}
|
||||||
|
@ -177,7 +177,7 @@ impl State {
|
||||||
Value::from (v_b + v_c)
|
Value::from (v_b + v_c)
|
||||||
};
|
};
|
||||||
|
|
||||||
*self.reg_mut (*a) = sum;
|
*self.reg_mut (*a) = x;
|
||||||
},
|
},
|
||||||
Instruction::Call (a, b, _c) => {
|
Instruction::Call (a, b, _c) => {
|
||||||
let b = usize::from (*b);
|
let b = usize::from (*b);
|
||||||
|
@ -250,16 +250,24 @@ impl State {
|
||||||
Instruction::Closure (a, b) => {
|
Instruction::Closure (a, b) => {
|
||||||
let b = usize::try_from (*b).unwrap ();
|
let b = usize::try_from (*b).unwrap ();
|
||||||
|
|
||||||
let idx = b + frame.block_idx + 1;
|
let idx = b + 1;
|
||||||
let block = &chunk.blocks [idx];
|
let block = &chunk.blocks [idx];
|
||||||
let upvalues = block.upvalues.iter ().map (|uv| {
|
|
||||||
assert! (uv.in_stack, "off-stack upvalues not implemented");
|
let mut new_upvalues = Vec::with_capacity (block.upvalues.len ());
|
||||||
self.reg (uv.idx).clone ()
|
for uv in &block.upvalues {
|
||||||
}).collect ();
|
let val = if uv.in_stack {
|
||||||
|
self.reg (uv.idx).clone ()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO: This isn't really correct
|
||||||
|
upvalues [usize::from (uv.idx)].clone ()
|
||||||
|
};
|
||||||
|
new_upvalues.push (val);
|
||||||
|
}
|
||||||
|
|
||||||
*self.reg_mut (*a) = Value::from (BogusClosure {
|
*self.reg_mut (*a) = Value::from (BogusClosure {
|
||||||
idx,
|
idx,
|
||||||
upvalues,
|
upvalues: new_upvalues,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
Instruction::EqI (a, sb, k_flag) => {
|
Instruction::EqI (a, sb, k_flag) => {
|
||||||
|
@ -439,7 +447,22 @@ impl State {
|
||||||
Instruction::Move (a, b) => {
|
Instruction::Move (a, b) => {
|
||||||
*self.reg_mut (*a) = self.reg (*b).clone ();
|
*self.reg_mut (*a) = self.reg (*b).clone ();
|
||||||
},
|
},
|
||||||
Instruction::Mul (_a, _b, _c) => unimplemented!(),
|
Instruction::Mul (a, b, c) => {
|
||||||
|
let v_b = self.reg (*b);
|
||||||
|
let v_c = self.reg (*c);
|
||||||
|
|
||||||
|
let x = if let (Some (v_b), Some (v_c)) = (v_b.as_int (), v_c.as_int ())
|
||||||
|
{
|
||||||
|
Value::from (v_b * v_c)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let v_b = v_b.as_float ().unwrap_or_else (|| panic! ("{v_b}"));
|
||||||
|
let v_c = v_c.as_float ().unwrap_or_else (|| panic! ("{v_c}"));
|
||||||
|
Value::from (v_b * v_c)
|
||||||
|
};
|
||||||
|
|
||||||
|
*self.reg_mut (*a) = x;
|
||||||
|
},
|
||||||
Instruction::NewTable (a) => {
|
Instruction::NewTable (a) => {
|
||||||
*self.reg_mut (*a) = Value::Table (Default::default ());
|
*self.reg_mut (*a) = Value::Table (Default::default ());
|
||||||
},
|
},
|
||||||
|
@ -500,7 +523,10 @@ impl State {
|
||||||
return self.registers [a..(a + b - 1)].to_vec();
|
return self.registers [a..(a + b - 1)].to_vec();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Instruction::Return0 => unimplemented! (),
|
Instruction::Return0 => {
|
||||||
|
self.stack.pop ();
|
||||||
|
next_pc = self.stack.last ().unwrap ().program_counter;
|
||||||
|
},
|
||||||
Instruction::Return1 (a) => {
|
Instruction::Return1 (a) => {
|
||||||
let a = usize::try_from (*a).unwrap ();
|
let a = usize::try_from (*a).unwrap ();
|
||||||
let popped_frame = self.stack.pop ().unwrap ();
|
let popped_frame = self.stack.pop ().unwrap ();
|
||||||
|
@ -574,7 +600,36 @@ impl State {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Instruction::SetTabUp (_a, _b, _c) => unimplemented! (),
|
Instruction::SetTabUp (_a, _b, _c) => unimplemented! (),
|
||||||
Instruction::TailCall (_a, _b, _c, _k) => unimplemented! (),
|
Instruction::TailCall (a, b, _c, k) => {
|
||||||
|
assert! (!k, "closing over values in tail calls not implemented");
|
||||||
|
|
||||||
|
// Shift closure and inputs into place
|
||||||
|
let a = usize::from (*a);
|
||||||
|
let b = usize::from (*b);
|
||||||
|
let offset = frame.register_offset - 1;
|
||||||
|
for i in (offset)..(offset + b) {
|
||||||
|
self.registers [i] = self.registers [i + a + 1].take ();
|
||||||
|
}
|
||||||
|
|
||||||
|
let value = &self.registers [offset];
|
||||||
|
let closure = if let Some (x) = value.as_closure () {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dbg! (self);
|
||||||
|
panic! ("OP_TAILCALL only implemented for closures");
|
||||||
|
};
|
||||||
|
let closure = closure.borrow ();
|
||||||
|
|
||||||
|
// Jump into the other function
|
||||||
|
|
||||||
|
let frame = self.stack.last_mut ().unwrap ();
|
||||||
|
frame.program_counter = 0;
|
||||||
|
frame.block_idx = closure.idx;
|
||||||
|
|
||||||
|
// Skip the PC increment
|
||||||
|
continue;
|
||||||
|
},
|
||||||
Instruction::Test (a, _k) => {
|
Instruction::Test (a, _k) => {
|
||||||
if self.reg (*a).is_truthy() {
|
if self.reg (*a).is_truthy() {
|
||||||
next_pc += 1;
|
next_pc += 1;
|
||||||
|
@ -590,6 +645,7 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dbg! (self);
|
||||||
panic! ("Hit max iterations before block returned");
|
panic! ("Hit max iterations before block returned");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,10 +185,10 @@ fn floats () {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fma () {
|
fn fma () {
|
||||||
let bytecode = include_bytes! ("../test_vectors/fma.luac");
|
let source = include_bytes! ("../test_vectors/fma.lua");
|
||||||
let mut rdr = std::io::Cursor::new (bytecode);
|
let bytecode = &crate::loader::compile_bytecode_from_stdin (source.to_vec ());
|
||||||
let chunk = crate::loader::parse_chunk (&mut rdr).unwrap ();
|
let chunk = crate::loader::parse_chunk_from_bytes (bytecode).unwrap ();
|
||||||
assert_eq! (chunk.blocks.len (), 4);
|
assert_eq! (chunk.blocks.len (), 5);
|
||||||
|
|
||||||
assert_eq! (chunk.blocks [3].upvalues.len (), 2);
|
assert_eq! (chunk.blocks [3].upvalues.len (), 2);
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ impl fmt::Display for Value {
|
||||||
Value::String (s) => write! (f, "{}", s),
|
Value::String (s) => write! (f, "{}", s),
|
||||||
Value::Table (t) => write! (f, "table: {:?}", std::rc::Rc::as_ptr (t)),
|
Value::Table (t) => write! (f, "table: {:?}", std::rc::Rc::as_ptr (t)),
|
||||||
|
|
||||||
Value::BogusClosure (_) => write! (f, "BogusClosure"),
|
Value::BogusClosure (x) => write! (f, "BogusClosure: {:?}", std::rc::Rc::as_ptr (x)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue