🚧 wip: working on closures / upvalues
parent
05b1d6e1f7
commit
4da634a2aa
17
src/main.rs
17
src/main.rs
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
52
src/state.rs
52
src/state.rs
|
@ -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 {
|
||||||
|
|
15
src/value.rs
15
src/value.rs
|
@ -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> {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue