🚧 wip: working on closures / upvalues

main
_ 2023-09-28 01:31:23 -05:00
parent 05b1d6e1f7
commit 4da634a2aa
4 changed files with 70 additions and 22 deletions

View File

@ -14,12 +14,24 @@ fn main () {
let mut list_bytecode = false; let mut list_bytecode = false;
let mut pipe_bytecode = false; let mut pipe_bytecode = false;
let mut script = None; let mut script = None;
let mut breakpoints = vec![];
let mut args = std::env::args (); let mut args = std::env::args ();
let exe_name = args.next ().unwrap (); let exe_name = args.next ().unwrap ();
while let Some (arg) = args.next () { while let Some (arg) = args.next () {
match arg.as_str () { match arg.as_str () {
"--break" => {
let s = args.next ().unwrap ();
let (block_idx, program_counter) = s.split_once (":").unwrap ();
let block_idx = str::parse (block_idx).unwrap ();
let program_counter = str::parse (program_counter).unwrap ();
breakpoints.push (state::Breakpoint {
block_idx,
program_counter,
});
},
"--list-bytecode" => list_bytecode = true, "--list-bytecode" => list_bytecode = true,
"--pipe-bytecode" => pipe_bytecode = true, "--pipe-bytecode" => pipe_bytecode = true,
"--script" => script = Some (args.next ().unwrap ()), "--script" => script = Some (args.next ().unwrap ()),
@ -52,10 +64,7 @@ fn main () {
let upvalues = State::upvalues_from_args ([exe_name].into_iter ().chain (args)); let upvalues = State::upvalues_from_args ([exe_name].into_iter ().chain (args));
vm.breakpoints.push (state::Breakpoint { vm.breakpoints = breakpoints;
block_idx: 3,
program_counter: 0,
});
vm.execute_chunk (&chunk, &upvalues); vm.execute_chunk (&chunk, &upvalues);
} }

View File

@ -172,7 +172,9 @@ impl State {
Value::from (v_b + v_c) Value::from (v_b + v_c)
} }
else { else {
Value::from (v_b.as_float ().unwrap () + v_c.as_float ().unwrap ()) 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) = sum; *self.reg_mut (*a) = sum;
@ -195,7 +197,7 @@ impl State {
match v_a { match v_a {
Value::BogusClosure (rc) => { Value::BogusClosure (rc) => {
let idx = rc.idx; let idx = rc.borrow ().idx;
let block_idx = frame.block_idx; let block_idx = frame.block_idx;
let target_block = idx; let target_block = idx;
@ -248,10 +250,17 @@ impl State {
Instruction::Closure (a, b) => { Instruction::Closure (a, b) => {
let b = usize::try_from (*b).unwrap (); let b = usize::try_from (*b).unwrap ();
*self.reg_mut (*a) = Value::BogusClosure (BogusClosure { let idx = b + frame.block_idx + 1;
idx: b + frame.block_idx + 1, let block = &chunk.blocks [idx];
upvalues: vec! [], let upvalues = block.upvalues.iter ().map (|uv| {
}.into ()); assert! (uv.in_stack, "off-stack upvalues not implemented");
self.reg (uv.idx).clone ()
}).collect ();
*self.reg_mut (*a) = Value::from (BogusClosure {
idx,
upvalues,
});
}, },
Instruction::EqI (a, sb, k_flag) => { Instruction::EqI (a, sb, k_flag) => {
if (self.reg (*a).as_int ().unwrap () == *sb as i64) != *k_flag if (self.reg (*a).as_int ().unwrap () == *sb as i64) != *k_flag
@ -324,7 +333,24 @@ impl State {
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 table = upvalues.get (b).unwrap ().as_table ().expect ("GetTabUp only works on tables").borrow (); // If we're inside a closure, use its upvalues
// instead of the chunk's upvalues
let frame = self.stack.last ().unwrap ();
let value = if frame.register_offset == 0 {
upvalues.get (b).unwrap ().clone ()
}
else if let Some (cell) = self.registers [frame.register_offset - 1].as_closure ()
{
let closure = cell.borrow ();
let value = closure.upvalues.get (b).unwrap ();
value.clone ()
}
else {
upvalues.get (b).unwrap ().clone ()
};
let table = value.as_table ().expect ("GetTabUp only works on tables").borrow ();
let key = match k.get (c).unwrap () { let key = match k.get (c).unwrap () {
Value::String (s) => String::from (s.as_ref()), Value::String (s) => String::from (s.as_ref()),
@ -345,14 +371,14 @@ impl State {
}, },
Instruction::GetUpVal (a, b) => { Instruction::GetUpVal (a, b) => {
let this_func = self.stack.last ().unwrap ().register_offset - 1; let this_func = self.stack.last ().unwrap ().register_offset - 1;
let upvalues = match &self.registers [this_func] { let closure = match &self.registers [this_func] {
Value::BogusClosure (rc) => &rc.upvalues, Value::BogusClosure (rc) => rc.clone (),
_ => panic! ("Can't do GetUpVal outside a closure"), _ => panic! ("Can't do GetUpVal outside a closure"),
}; };
let b = usize::try_from (*b).unwrap (); let b = usize::try_from (*b).unwrap ();
let upvalue = match upvalues.get (b) { let upvalue = match closure.borrow ().upvalues.get (b) {
Some (x) => x.clone (), Some (x) => x.clone (),
None => { None => {
dbg! (chunk, &self); dbg! (chunk, &self);
@ -430,7 +456,7 @@ impl State {
if *k { if *k {
let closure_idx = match &self.registers [popped_frame.register_offset + a] { let closure_idx = match &self.registers [popped_frame.register_offset + a] {
Value::BogusClosure (rc) => rc.idx, Value::BogusClosure (rc) => rc.borrow ().idx,
_ => panic! ("Impossible"), _ => panic! ("Impossible"),
}; };
@ -440,10 +466,10 @@ impl State {
let upvalues = self.registers [start_reg..start_reg+upvalue_count].iter ().cloned ().collect (); let upvalues = self.registers [start_reg..start_reg+upvalue_count].iter ().cloned ().collect ();
self.registers [a + popped_frame.register_offset] = Value::BogusClosure (BogusClosure { self.registers [a + popped_frame.register_offset] = Value::from (BogusClosure {
idx: closure_idx, idx: closure_idx,
upvalues, upvalues,
}.into ()); });
} }
if self.debug_print { if self.debug_print {

View File

@ -32,7 +32,7 @@ pub enum Value {
// These are all bogus, I haven't figured out how to implement // These are all bogus, I haven't figured out how to implement
// closures yet // closures yet
BogusClosure (Rc <BogusClosure>), BogusClosure (Rc <RefCell <BogusClosure>>),
} }
impl Default for Value { impl Default for Value {
@ -58,6 +58,12 @@ impl fmt::Display for Value {
} }
} }
impl From <BogusClosure> for Value {
fn from (x: BogusClosure) -> Self {
Self::BogusClosure (Rc::new (RefCell::new (x)))
}
}
impl From <bool> for Value { impl From <bool> for Value {
fn from (x: bool) -> Self { fn from (x: bool) -> Self {
Self::Boolean (x) Self::Boolean (x)
@ -156,6 +162,13 @@ impl PartialEq <i64> for Value {
} }
impl Value { impl Value {
pub fn as_closure (&self) -> Option <&Rc <RefCell <BogusClosure>>> {
match self {
Self::BogusClosure (x) => Some (x),
_ => None,
}
}
/// Coerces ints to float /// Coerces ints to float
pub fn as_float (&self) -> Option <f64> { pub fn as_float (&self) -> Option <f64> {

View File

@ -1,11 +1,11 @@
local function make_closure (x) local function make_closure (t)
print (x)
return function (y) return function (y)
return x + y return t.x + y
end end
end end
local f = make_closure (11) local f = make_closure ({ x = 11 })
local t = {}
local x = f (12) local x = f (12)
print (x) print (x)
return x return x