♻️ refactor: trying to fix OP_RETURN so it can close over values

main
_ 2023-09-24 22:49:00 -05:00
parent 44d065d6dd
commit 543dab360b
1 changed files with 89 additions and 39 deletions

View File

@ -66,7 +66,10 @@ pub enum Value {
// tables and function pointers yet // tables and function pointers yet
BogusArg (Vec <String>), BogusArg (Vec <String>),
BogusClosure (usize), BogusClosure {
idx: usize,
upvalues: Vec <Value>,
},
BogusEnv (BTreeMap <String, Value>), BogusEnv (BTreeMap <String, Value>),
BogusPrint, BogusPrint,
} }
@ -131,7 +134,7 @@ pub struct Chunk {
pub blocks: Vec <Block>, pub blocks: Vec <Block>,
} }
#[derive (Debug)] #[derive (Clone, Debug)]
struct StackFrame { struct StackFrame {
// i32 makes it a little easier to implement jumps // i32 makes it a little easier to implement jumps
// Starts at 0 right after OP_CALL // Starts at 0 right after OP_CALL
@ -146,6 +149,7 @@ struct StackFrame {
pub struct State { pub struct State {
registers: Vec <Value>, registers: Vec <Value>,
stack: Vec <StackFrame>,
pub debug_print: bool, pub debug_print: bool,
} }
@ -153,6 +157,13 @@ impl Default for State {
fn default () -> Self { fn default () -> Self {
Self { Self {
registers: vec! [Value::Nil; 256], registers: vec! [Value::Nil; 256],
stack: vec! [
StackFrame {
program_counter: 0,
block_idx: 0,
register_offset: 0,
},
],
debug_print: false, debug_print: false,
} }
} }
@ -173,21 +184,22 @@ impl State {
] ]
} }
fn register_window (&self) -> &[Value] {
let frame = self.stack.last ().unwrap ();
&self.registers [frame.register_offset..]
}
fn register_window_mut (&mut self) -> &mut [Value] {
let frame = self.stack.last_mut ().unwrap ();
&mut self.registers [frame.register_offset..]
}
pub fn execute_chunk (&mut self, chunk: &Chunk, upvalues: &[Value]) pub fn execute_chunk (&mut self, chunk: &Chunk, upvalues: &[Value])
-> Vec <Value> { -> Vec <Value> {
let max_iters = 2000; let max_iters = 2000;
let mut stack = vec! [
StackFrame {
program_counter: 0,
block_idx: 0,
register_offset: 0,
},
];
for _ in 0..max_iters { for _ in 0..max_iters {
let stack_idx = stack.len () - 1; let frame = self.stack.last_mut ().unwrap ().clone ();
let frame = stack.get_mut (stack_idx).unwrap ();
let block = chunk.blocks.get (frame.block_idx).unwrap (); let block = chunk.blocks.get (frame.block_idx).unwrap ();
let mut next_pc = frame.program_counter; let mut next_pc = frame.program_counter;
@ -196,16 +208,18 @@ impl State {
let instruction = match block.instructions.get (pc) { let instruction = match block.instructions.get (pc) {
Some (x) => x, Some (x) => x,
None => { None => {
dbg! (&stack); dbg! (&self.stack);
panic! ("program_counter went out of bounds"); panic! ("program_counter went out of bounds");
} }
}; };
let r = &mut self.registers [frame.register_offset..]; // let r = &mut self.registers [frame.register_offset..];
let k = &block.constants; let k = &block.constants;
match instruction { match instruction {
Instruction::Add (a, b, c) => { Instruction::Add (a, b, c) => {
let r = self.register_window_mut ();
let a = usize::try_from (*a).unwrap (); let a = usize::try_from (*a).unwrap ();
let b = usize::try_from (*b).unwrap (); let b = usize::try_from (*b).unwrap ();
let c = usize::try_from (*c).unwrap (); let c = usize::try_from (*c).unwrap ();
@ -227,16 +241,20 @@ impl State {
// TODO: Only implement printing values for now // TODO: Only implement printing values for now
let a = usize::try_from (*a).unwrap (); let a = usize::try_from (*a).unwrap ();
let r = self.register_window ();
let v_a = r.get (a).unwrap (); let v_a = r.get (a).unwrap ();
match v_a { match v_a {
Value::BogusClosure (idx) => { Value::BogusClosure {
idx,
upvalues,
}=> {
let block_idx = frame.block_idx; let block_idx = frame.block_idx;
let target_block = *idx; let target_block = *idx;
let current_frame = &stack [stack.len () - 1]; let current_frame = self.stack.last ().unwrap ();
stack.push (StackFrame { self.stack.push (StackFrame {
program_counter: 0, program_counter: 0,
block_idx: target_block, block_idx: target_block,
register_offset: current_frame.register_offset + a + 1, register_offset: current_frame.register_offset + a + 1,
@ -244,7 +262,7 @@ impl State {
if self.debug_print { if self.debug_print {
println! ("Inst {block_idx}:{pc} calls {target_block}:0"); println! ("Inst {block_idx}:{pc} calls {target_block}:0");
let stack_depth = stack.len (); let stack_depth = self.stack.len ();
println! ("stack_depth: {stack_depth}"); println! ("stack_depth: {stack_depth}");
} }
@ -260,18 +278,26 @@ impl State {
println! ("{:?}", r.get (a + 1).unwrap ()); println! ("{:?}", r.get (a + 1).unwrap ());
}, },
_ => panic! ("Cannot call value {a:?}. backtrace: {stack:?}"), _ => {
let stack = &self.stack;
panic! ("Cannot call value {a:?}. backtrace: {stack:?}");
},
} }
}, },
Instruction::Closure (a, b) => { Instruction::Closure (a, b) => {
let a = usize::try_from (*a).unwrap (); let a = usize::try_from (*a).unwrap ();
let b = usize::try_from (*b).unwrap (); let b = usize::try_from (*b).unwrap ();
let r = self.register_window_mut ();
r [a] = Value::BogusClosure (b + frame.block_idx + 1); r [a] = Value::BogusClosure {
idx: b + frame.block_idx + 1,
upvalues: vec! [],
};
}, },
Instruction::EqK (a, b, c_k) => { Instruction::EqK (a, b, c_k) => {
let a = usize::try_from (*a).unwrap (); let a = usize::try_from (*a).unwrap ();
let b = usize::try_from (*b).unwrap (); let b = usize::try_from (*b).unwrap ();
let r = self.register_window ();
let equal = r [a] == k [b]; let equal = r [a] == k [b];
@ -299,13 +325,16 @@ impl State {
let value = env.get (key).unwrap (); let value = env.get (key).unwrap ();
r [a] = value.clone ();
self.register_window_mut() [a] = value.clone ();
}, },
Instruction::GetI (a, b, c) => { Instruction::GetI (a, b, c) => {
let a = usize::try_from (*a).unwrap (); let a = usize::try_from (*a).unwrap ();
let b = usize::try_from (*b).unwrap (); let b = usize::try_from (*b).unwrap ();
let c = usize::try_from (*c).unwrap (); let c = usize::try_from (*c).unwrap ();
let r = self.register_window_mut ();
let table = r.get (b).unwrap (); let table = r.get (b).unwrap ();
let value = match table { let value = match table {
Value::BogusArg (arg) => arg.get (c).map (|x| x.as_str().into ()).unwrap_or_default(), Value::BogusArg (arg) => arg.get (c).map (|x| x.as_str().into ()).unwrap_or_default(),
@ -317,27 +346,28 @@ impl State {
Instruction::Jmp (s_j) => next_pc += s_j, Instruction::Jmp (s_j) => next_pc += s_j,
Instruction::LoadFalse (a) => { Instruction::LoadFalse (a) => {
let a = usize::try_from (*a).unwrap (); let a = usize::try_from (*a).unwrap ();
r [a] = Value::Boolean (false); self.register_window_mut ()[a] = Value::Boolean (false);
}, },
Instruction::LoadI (a, sbx) => { Instruction::LoadI (a, sbx) => {
let a = usize::try_from (*a).unwrap (); let a = usize::try_from (*a).unwrap ();
r [a] = (*sbx).into (); self.register_window_mut ()[a] = (*sbx).into ();
}, },
Instruction::LoadK (a, bx) => { Instruction::LoadK (a, bx) => {
let a = usize::try_from (*a).unwrap (); let a = usize::try_from (*a).unwrap ();
let bx = usize::try_from (*bx).unwrap (); let bx = usize::try_from (*bx).unwrap ();
r [a] = k [bx].clone (); self.register_window_mut ()[a] = k [bx].clone ();
}, },
Instruction::LoadTrue (a) => { Instruction::LoadTrue (a) => {
let a = usize::try_from (*a).unwrap (); let a = usize::try_from (*a).unwrap ();
r [a] = Value::Boolean (true); self.register_window_mut ()[a] = Value::Boolean (true);
}, },
Instruction::MmBin (a, b, _c) => { Instruction::MmBin (a, b, _c) => {
let a = usize::try_from (*a).unwrap (); let a = usize::try_from (*a).unwrap ();
let b = usize::try_from (*b).unwrap (); let b = usize::try_from (*b).unwrap ();
let r = self.register_window();
let a = &r [a]; let a = &r [a];
let b = &r [b]; let b = &r [b];
@ -352,43 +382,64 @@ impl State {
let a = usize::try_from (*a).unwrap (); let a = usize::try_from (*a).unwrap ();
let b = usize::try_from (*b).unwrap (); let b = usize::try_from (*b).unwrap ();
let r = self.register_window_mut();
r [a] = r [b].clone (); r [a] = r [b].clone ();
}, },
Instruction::Not (a, b) => { Instruction::Not (a, b) => {
let a = usize::try_from (*a).unwrap (); let a = usize::try_from (*a).unwrap ();
let b = usize::try_from (*b).unwrap (); let b = usize::try_from (*b).unwrap ();
let r = self.register_window_mut();
r [a] = Value::Boolean (! r [b].is_truthy()); r [a] = Value::Boolean (! r [b].is_truthy());
} }
Instruction::Return (a, b, _c, _k) => { Instruction::Return (a, b, _c, k) => {
let a = usize::try_from (*a).unwrap (); let a = usize::try_from (*a).unwrap ();
let b = usize::try_from (*b).unwrap (); let b = usize::try_from (*b).unwrap ();
let popped_frame = stack.pop ().unwrap (); let popped_frame = self.stack.pop ().unwrap ();
// Build closure if needed
if *k {
let closure_idx = match &self.register_window ()[a] {
Value::BogusClosure { idx, upvalues } => idx,
_ => panic! ("Impossible"),
};
let upvalue_count = chunk.blocks [*closure_idx].upvalue_count;
let start_reg = a + popped_frame.register_offset - upvalue_count;
let upvalues = self.registers [start_reg..start_reg+upvalue_count].iter ().cloned ().collect ();
self.registers [a + popped_frame.register_offset] = Value::BogusClosure {
idx: *closure_idx,
upvalues,
};
}
if self.debug_print { if self.debug_print {
let old_block = popped_frame.block_idx; let old_block = popped_frame.block_idx;
let old_pc = popped_frame.program_counter; let old_pc = popped_frame.program_counter;
println! ("Inst {old_block}:{old_pc} returns"); println! ("Inst {old_block}:{old_pc} returns");
let stack_depth = stack.len (); let stack_depth = self.stack.len ();
println! ("stack_depth: {stack_depth}"); println! ("stack_depth: {stack_depth}");
} }
if let Some (new_frame) = stack.last() { if let Some (new_frame) = self.stack.last() {
next_pc = new_frame.program_counter; next_pc = new_frame.program_counter;
} }
else { else {
return r [a..(a + b - 1)].to_vec(); return self.register_window ()[a..(a + b - 1)].to_vec();
} }
}, },
Instruction::Return1 (a) => { Instruction::Return1 (a) => {
let a = usize::try_from (*a).unwrap (); let a = usize::try_from (*a).unwrap ();
let popped_frame = stack.pop ().unwrap (); let popped_frame = self.stack.pop ().unwrap ();
self.registers [popped_frame.register_offset - 1] = r [a].clone ();
let stack_idx = stack.len () - 1; self.registers [popped_frame.register_offset - 1] = self.register_window ()[a].clone ();
let frame = stack.get (stack_idx).unwrap ();
let frame = self.stack.last ().unwrap ();
let new_block = frame.block_idx; let new_block = frame.block_idx;
next_pc = frame.program_counter; next_pc = frame.program_counter;
@ -396,14 +447,14 @@ impl State {
let old_block = popped_frame.block_idx; let old_block = popped_frame.block_idx;
let old_pc = popped_frame.program_counter; let old_pc = popped_frame.program_counter;
println! ("Inst {old_block}:{old_pc} returns to inst {new_block}:{next_pc}"); println! ("Inst {old_block}:{old_pc} returns to inst {new_block}:{next_pc}");
let stack_depth = stack.len (); let stack_depth = self.stack.len ();
println! ("stack_depth: {stack_depth}"); println! ("stack_depth: {stack_depth}");
} }
}, },
Instruction::Test (a, _k) => { Instruction::Test (a, _k) => {
let a = usize::try_from (*a).unwrap (); let a = usize::try_from (*a).unwrap ();
let a = r.get (a).unwrap (); let a = self.register_window ().get (a).unwrap ();
if self.debug_print { if self.debug_print {
println! ("Test {a:?}"); println! ("Test {a:?}");
@ -419,8 +470,7 @@ impl State {
next_pc += 1; next_pc += 1;
{ {
let stack_idx = stack.len () - 1; let frame = self.stack.last_mut ().unwrap ();
let frame = stack.get_mut (stack_idx).unwrap ();
frame.program_counter = next_pc; frame.program_counter = next_pc;
} }
} }