♻️ refactor: extract a single step method for State
parent
f0d4f25cec
commit
a9e14d0f47
|
@ -57,14 +57,16 @@ fn main () {
|
|||
dbg! (&chunk);
|
||||
}
|
||||
|
||||
let mut vm = State::default ();
|
||||
let upvalues = State::upvalues_from_args ([exe_name].into_iter ().chain (args));
|
||||
|
||||
let mut vm = State::new (&chunk, &upvalues);
|
||||
if std::env::var("LUA_DEBUG").is_ok() {
|
||||
vm.debug_print = true;
|
||||
}
|
||||
|
||||
let upvalues = State::upvalues_from_args ([exe_name].into_iter ().chain (args));
|
||||
|
||||
|
||||
vm.breakpoints = breakpoints;
|
||||
|
||||
vm.execute_chunk (&chunk, &upvalues);
|
||||
vm.execute_chunk ();
|
||||
}
|
||||
|
|
80
src/state.rs
80
src/state.rs
|
@ -47,7 +47,7 @@ pub struct Breakpoint {
|
|||
}
|
||||
|
||||
#[derive (Debug)]
|
||||
pub struct State {
|
||||
pub struct State <'a> {
|
||||
registers: Vec <Value>,
|
||||
// Currently only used for native function calls
|
||||
top: usize,
|
||||
|
@ -56,25 +56,8 @@ pub struct State {
|
|||
pub debug_print: bool,
|
||||
pub breakpoints: Vec <Breakpoint>,
|
||||
step_count: u32,
|
||||
}
|
||||
|
||||
impl Default for State {
|
||||
fn default () -> Self {
|
||||
Self {
|
||||
registers: vec! [Value::Nil; 16],
|
||||
top: 0,
|
||||
stack: vec! [
|
||||
StackFrame {
|
||||
program_counter: 0,
|
||||
block_idx: 0,
|
||||
register_offset: 0,
|
||||
},
|
||||
],
|
||||
debug_print: false,
|
||||
breakpoints: Default::default(),
|
||||
step_count: 0,
|
||||
}
|
||||
}
|
||||
chunk: &'a Chunk,
|
||||
upvalues: &'a [Value],
|
||||
}
|
||||
|
||||
fn lw_print (l: &mut State) -> i32 {
|
||||
|
@ -93,7 +76,30 @@ fn lw_print (l: &mut State) -> i32 {
|
|||
1
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub enum StepOutput {
|
||||
ChunkReturned (Vec <Value>),
|
||||
}
|
||||
|
||||
impl <'a> State <'a> {
|
||||
pub fn new (chunk: &'a Chunk, upvalues: &'a [Value]) -> Self {
|
||||
Self {
|
||||
registers: vec! [Value::Nil; 16],
|
||||
top: 0,
|
||||
stack: vec! [
|
||||
StackFrame {
|
||||
program_counter: 0,
|
||||
block_idx: 0,
|
||||
register_offset: 0,
|
||||
},
|
||||
],
|
||||
debug_print: false,
|
||||
breakpoints: Default::default(),
|
||||
step_count: 0,
|
||||
chunk,
|
||||
upvalues,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn upvalues_from_args <I: Iterator <Item = String>> (args: I) -> Vec <Value>
|
||||
{
|
||||
let arg = args.map (|s| Value::from (s)).enumerate ();
|
||||
|
@ -131,11 +137,8 @@ impl State {
|
|||
self.top - self.stack.last ().unwrap ().register_offset
|
||||
}
|
||||
|
||||
pub fn execute_chunk (&mut self, chunk: &Chunk, upvalues: &[Value])
|
||||
-> Vec <Value> {
|
||||
let max_iters = 2000;
|
||||
|
||||
for _ in 0..max_iters {
|
||||
pub fn step (&mut self) -> Option <StepOutput> {
|
||||
let chunk = self.chunk;
|
||||
self.step_count += 1;
|
||||
|
||||
let frame = self.stack.last_mut ().unwrap ().clone ();
|
||||
|
@ -217,7 +220,7 @@ impl State {
|
|||
}
|
||||
|
||||
// Skip the PC increment at the bottom of the loop
|
||||
continue;
|
||||
return None;
|
||||
},
|
||||
Value::RsFunc (x) => {
|
||||
let current_frame = self.stack.last ().unwrap ();
|
||||
|
@ -260,7 +263,7 @@ impl State {
|
|||
}
|
||||
else {
|
||||
// TODO: This isn't really correct
|
||||
upvalues [usize::from (uv.idx)].clone ()
|
||||
self.upvalues [usize::from (uv.idx)].clone ()
|
||||
};
|
||||
new_upvalues.push (val);
|
||||
}
|
||||
|
@ -346,7 +349,7 @@ impl State {
|
|||
|
||||
let frame = self.stack.last ().unwrap ();
|
||||
let value = if frame.register_offset == 0 {
|
||||
upvalues.get (b).unwrap ().clone ()
|
||||
self.upvalues.get (b).unwrap ().clone ()
|
||||
}
|
||||
else if let Some (cell) = self.registers [frame.register_offset - 1].as_closure ()
|
||||
{
|
||||
|
@ -355,7 +358,7 @@ impl State {
|
|||
value.clone ()
|
||||
}
|
||||
else {
|
||||
upvalues.get (b).unwrap ().clone ()
|
||||
self.upvalues.get (b).unwrap ().clone ()
|
||||
};
|
||||
|
||||
let table = value.as_table ().expect ("GetTabUp only works on tables").borrow ();
|
||||
|
@ -520,7 +523,7 @@ impl State {
|
|||
}
|
||||
else {
|
||||
// Return from the entire program
|
||||
return self.registers [a..(a + b - 1)].to_vec();
|
||||
return Some (StepOutput::ChunkReturned (self.registers [a..(a + b - 1)].to_vec()));
|
||||
}
|
||||
},
|
||||
Instruction::Return0 => {
|
||||
|
@ -628,7 +631,7 @@ impl State {
|
|||
frame.block_idx = closure.idx;
|
||||
|
||||
// Skip the PC increment
|
||||
continue;
|
||||
return None;
|
||||
},
|
||||
Instruction::Test (a, _k) => {
|
||||
if self.reg (*a).is_truthy() {
|
||||
|
@ -643,6 +646,19 @@ impl State {
|
|||
let frame = self.stack.last_mut ().unwrap ();
|
||||
frame.program_counter = next_pc;
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn execute_chunk (&mut self)
|
||||
-> Vec <Value> {
|
||||
let max_iters = 2000;
|
||||
|
||||
for _ in 0..max_iters {
|
||||
match self.step () {
|
||||
None => (),
|
||||
Some (StepOutput::ChunkReturned (x)) => return x,
|
||||
}
|
||||
}
|
||||
|
||||
dbg! (self);
|
||||
|
|
17
src/tests.rs
17
src/tests.rs
|
@ -23,9 +23,9 @@ fn calculate_hash<T: Hash>(t: &T) -> u64 {
|
|||
/// and returns the output
|
||||
|
||||
fn run_chunk (args: &[&str], chunk: &Chunk) -> Vec <Value> {
|
||||
let mut vm = State::default ();
|
||||
let upvalues = State::upvalues_from_args (args.into_iter ().map (|s| s.to_string ()));
|
||||
vm.execute_chunk (chunk, &upvalues)
|
||||
let mut vm = State::new (chunk, &upvalues);
|
||||
vm.execute_chunk ()
|
||||
}
|
||||
|
||||
/// Takes arguments and Lua bytecode, loads it, runs it,
|
||||
|
@ -118,10 +118,9 @@ fn bools () {
|
|||
] {
|
||||
let expected: Vec <Value> = 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 (&chunk, &upvalues);
|
||||
let mut vm = State::new (&chunk, &upvalues);
|
||||
let actual = vm.execute_chunk ();
|
||||
assert_eq! (actual, expected);
|
||||
}
|
||||
}
|
||||
|
@ -175,9 +174,9 @@ fn floats () {
|
|||
(vec! ["_exe_name", " "], vec! [3.5.into ()]),
|
||||
] {
|
||||
let expected: Vec <Value> = 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 (&chunk, &upvalues);
|
||||
let mut vm = State::new (&chunk, &upvalues);
|
||||
let actual = vm.execute_chunk ();
|
||||
|
||||
assert_eq! (actual, expected);
|
||||
}
|
||||
|
@ -197,9 +196,9 @@ fn fma () {
|
|||
(vec! ["_exe_name"], vec! [122.into ()]),
|
||||
] {
|
||||
let expected: Vec <Value> = 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 (&chunk, &upvalues);
|
||||
let mut vm = State::new (&chunk, &upvalues);
|
||||
let actual = vm.execute_chunk ();
|
||||
|
||||
assert_eq! (actual, expected);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue