♻️ refactor: extract a single step method for State

main
_ 2023-09-29 16:27:50 -05:00
parent f0d4f25cec
commit a9e14d0f47
3 changed files with 557 additions and 540 deletions

View File

@ -57,14 +57,16 @@ fn main () {
dbg! (&chunk); 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() { if std::env::var("LUA_DEBUG").is_ok() {
vm.debug_print = true; vm.debug_print = true;
} }
let upvalues = State::upvalues_from_args ([exe_name].into_iter ().chain (args));
vm.breakpoints = breakpoints; vm.breakpoints = breakpoints;
vm.execute_chunk (&chunk, &upvalues); vm.execute_chunk ();
} }

View File

@ -47,7 +47,7 @@ pub struct Breakpoint {
} }
#[derive (Debug)] #[derive (Debug)]
pub struct State { pub struct State <'a> {
registers: Vec <Value>, registers: Vec <Value>,
// Currently only used for native function calls // Currently only used for native function calls
top: usize, top: usize,
@ -56,25 +56,8 @@ pub struct State {
pub debug_print: bool, pub debug_print: bool,
pub breakpoints: Vec <Breakpoint>, pub breakpoints: Vec <Breakpoint>,
step_count: u32, step_count: u32,
} chunk: &'a Chunk,
upvalues: &'a [Value],
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,
}
}
} }
fn lw_print (l: &mut State) -> i32 { fn lw_print (l: &mut State) -> i32 {
@ -93,7 +76,30 @@ fn lw_print (l: &mut State) -> i32 {
1 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> pub fn upvalues_from_args <I: Iterator <Item = String>> (args: I) -> Vec <Value>
{ {
let arg = args.map (|s| Value::from (s)).enumerate (); let arg = args.map (|s| Value::from (s)).enumerate ();
@ -131,11 +137,8 @@ impl State {
self.top - self.stack.last ().unwrap ().register_offset self.top - self.stack.last ().unwrap ().register_offset
} }
pub fn execute_chunk (&mut self, chunk: &Chunk, upvalues: &[Value]) pub fn step (&mut self) -> Option <StepOutput> {
-> Vec <Value> { let chunk = self.chunk;
let max_iters = 2000;
for _ in 0..max_iters {
self.step_count += 1; self.step_count += 1;
let frame = self.stack.last_mut ().unwrap ().clone (); let frame = self.stack.last_mut ().unwrap ().clone ();
@ -217,7 +220,7 @@ impl State {
} }
// Skip the PC increment at the bottom of the loop // Skip the PC increment at the bottom of the loop
continue; return None;
}, },
Value::RsFunc (x) => { Value::RsFunc (x) => {
let current_frame = self.stack.last ().unwrap (); let current_frame = self.stack.last ().unwrap ();
@ -260,7 +263,7 @@ impl State {
} }
else { else {
// TODO: This isn't really correct // TODO: This isn't really correct
upvalues [usize::from (uv.idx)].clone () self.upvalues [usize::from (uv.idx)].clone ()
}; };
new_upvalues.push (val); new_upvalues.push (val);
} }
@ -346,7 +349,7 @@ impl State {
let frame = self.stack.last ().unwrap (); let frame = self.stack.last ().unwrap ();
let value = if frame.register_offset == 0 { 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 () else if let Some (cell) = self.registers [frame.register_offset - 1].as_closure ()
{ {
@ -355,7 +358,7 @@ impl State {
value.clone () value.clone ()
} }
else { else {
upvalues.get (b).unwrap ().clone () self.upvalues.get (b).unwrap ().clone ()
}; };
let table = value.as_table ().expect ("GetTabUp only works on tables").borrow (); let table = value.as_table ().expect ("GetTabUp only works on tables").borrow ();
@ -520,7 +523,7 @@ impl State {
} }
else { else {
// Return from the entire program // 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 => { Instruction::Return0 => {
@ -628,7 +631,7 @@ impl State {
frame.block_idx = closure.idx; frame.block_idx = closure.idx;
// Skip the PC increment // Skip the PC increment
continue; return None;
}, },
Instruction::Test (a, _k) => { Instruction::Test (a, _k) => {
if self.reg (*a).is_truthy() { if self.reg (*a).is_truthy() {
@ -643,6 +646,19 @@ impl State {
let frame = self.stack.last_mut ().unwrap (); let frame = self.stack.last_mut ().unwrap ();
frame.program_counter = next_pc; 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); dbg! (self);

View File

@ -23,9 +23,9 @@ fn calculate_hash<T: Hash>(t: &T) -> u64 {
/// and returns the output /// and returns the output
fn run_chunk (args: &[&str], chunk: &Chunk) -> Vec <Value> { 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 ())); 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, /// Takes arguments and Lua bytecode, loads it, runs it,
@ -118,10 +118,9 @@ fn bools () {
] { ] {
let expected: Vec <Value> = expected; 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 upvalues = State::upvalues_from_args (arg.into_iter ().map (|s| s.to_string ()));
let mut vm = State::new (&chunk, &upvalues);
let actual = vm.execute_chunk (&chunk, &upvalues); let actual = vm.execute_chunk ();
assert_eq! (actual, expected); assert_eq! (actual, expected);
} }
} }
@ -175,9 +174,9 @@ fn floats () {
(vec! ["_exe_name", " "], vec! [3.5.into ()]), (vec! ["_exe_name", " "], vec! [3.5.into ()]),
] { ] {
let expected: Vec <Value> = expected; 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 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); assert_eq! (actual, expected);
} }
@ -197,9 +196,9 @@ fn fma () {
(vec! ["_exe_name"], vec! [122.into ()]), (vec! ["_exe_name"], vec! [122.into ()]),
] { ] {
let expected: Vec <Value> = expected; 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 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); assert_eq! (actual, expected);
} }