🐛 bug: shrank the Value size to 16 bytes

This is a little pre-mature, since it's still in the "make it work"
phase of "make it work, make it fast, make it pretty".

But it was bugging me, and I'd have to ditch the raw strings and vecs
some day to add a GC anyway.
main
_ 2023-09-26 14:10:57 -05:00
parent f29eaac1d0
commit e87265373c
3 changed files with 46 additions and 34 deletions

View File

@ -70,8 +70,10 @@ pub fn parse_inst (buf: [u8; 4]) -> Option <Inst>
0x22 => Inst::Add (a, b, c),
0x24 => Inst::Mul (a, b, c),
0x2e => Inst::MmBin (a, b, c),
0x33 => Inst::Not (a, b),
0x3c => Inst::EqK (a, b, c),
0x38 => Inst::Jmp (s_j),
0x42 => Inst::Test (a, k),
0x44 => Inst::Call (a, b, c),
0x45 => Inst::TailCall (a, b, c, k),
0x46 => Inst::Return (a, b, c, k),

View File

@ -1,4 +1,7 @@
use std::collections::BTreeMap;
use std::{
collections::BTreeMap,
rc::Rc,
};
#[derive (Debug, PartialEq)]
pub enum Instruction {
@ -57,27 +60,30 @@ pub enum Instruction {
TailCall (u8, u8, u8, bool),
Test (u8, i32),
Test (u8, bool),
VarArgPrep (i32),
}
#[derive (Clone, Debug, PartialEq)]
pub struct BogusClosure {
idx: usize,
upvalues: Vec <Value>,
}
#[derive (Clone, Debug, PartialEq)]
pub enum Value {
Nil,
Boolean (bool),
Float (f64),
String (String),
String (Rc <String>),
// These are all bogus, I haven't figured out how to implement
// tables and function pointers yet
BogusArg (Vec <String>),
BogusClosure {
idx: usize,
upvalues: Vec <Value>,
},
BogusEnv (BTreeMap <String, Value>),
BogusArg (Rc <Vec <String>>),
BogusClosure (Rc <BogusClosure>),
BogusEnv (Rc <BTreeMap <String, Value>>),
BogusPrint,
}
@ -89,7 +95,7 @@ impl Default for Value {
impl From <String> for Value {
fn from (x: String) -> Self {
Self::String (x)
Self::String (x.into ())
}
}
@ -196,15 +202,15 @@ impl Default for State {
impl State {
pub fn upvalues_from_args <I: Iterator <Item = String>> (args: I) -> Vec <Value>
{
let arg = args.map (|s| s.to_string ()).collect ();
let arg: Vec <_> = args.map (|s| s.to_string ()).collect ();
let env = BTreeMap::from_iter ([
("arg", Value::BogusArg (arg)),
("arg", Value::BogusArg (arg.into ())),
("print", Value::BogusPrint),
].map (|(k, v)| (k.to_string (), v)));
vec! [
Value::BogusEnv (env),
Value::BogusEnv (env.into ()),
]
}
@ -262,7 +268,7 @@ impl State {
r [a] = (v_b + v_c).into ();
},
Instruction::Call (a, b, c) => {
Instruction::Call (a, _b, c) => {
// Take arguments from registers [a + 1, a + b)
// Call the function in register [a]
// Return values in registers [a, a + c - 1)
@ -278,12 +284,11 @@ impl State {
let v_a = r.get (a).unwrap ();
match v_a {
Value::BogusClosure {
idx,
upvalues,
}=> {
Value::BogusClosure (rc) => {
let idx = rc.idx;
let block_idx = frame.block_idx;
let target_block = *idx;
let target_block = idx;
let current_frame = self.stack.last ().unwrap ();
@ -310,7 +315,7 @@ impl State {
assert_eq! (*c, 1);
let value = r.get (a + 1).unwrap ();
let s = match value {
match value {
Value::Nil => println! ("nil"),
Value::Boolean (false) => println! ("false"),
Value::Boolean (true) => println! ("true"),
@ -336,10 +341,10 @@ impl State {
}
let r = self.register_window_mut ();
r [a] = Value::BogusClosure {
r [a] = Value::BogusClosure (BogusClosure {
idx: b + frame.block_idx + 1,
upvalues: vec! [],
};
}.into ());
},
Instruction::EqK (a, b, c_k) => {
let a = usize::try_from (*a).unwrap ();
@ -365,7 +370,7 @@ impl State {
};
let key = match k.get (c).unwrap () {
Value::String (s) => s,
Value::String (s) => s.as_ref (),
_ => panic! ("GetTabUp only supports string keys"),
};
@ -393,7 +398,7 @@ impl State {
Instruction::GetUpVal (a, b) => {
let this_func = self.stack.last ().unwrap ().register_offset - 1;
let upvalues = match &self.registers [this_func] {
Value::BogusClosure { idx, upvalues } => upvalues,
Value::BogusClosure (rc) => &rc.upvalues,
_ => panic! ("Can't do GetUpVal outside a closure"),
};
@ -461,7 +466,7 @@ impl State {
Instruction::Return (a, b, c, k) => {
let a = usize::try_from (*a).unwrap ();
let b = usize::try_from (*b).unwrap ();
let c = usize::try_from (*c).unwrap ();
let _c = usize::try_from (*c).unwrap ();
let popped_frame = self.stack.pop ().unwrap ();
@ -469,20 +474,20 @@ impl State {
if *k {
let closure_idx = match &self.registers [popped_frame.register_offset + a] {
Value::BogusClosure { idx, upvalues } => idx,
Value::BogusClosure (rc) => rc.idx,
_ => panic! ("Impossible"),
};
let upvalue_count = chunk.blocks [*closure_idx].upvalue_count;
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,
self.registers [a + popped_frame.register_offset] = Value::BogusClosure (BogusClosure {
idx: closure_idx,
upvalues,
};
}.into ());
}
if self.debug_print {

View File

@ -56,7 +56,7 @@ fn bools () {
},
Block {
instructions: vec! [
Inst::Test (0, 0),
Inst::Test (0, false),
Inst::Jmp (3),
Inst::LoadI (1, 99),
Inst::Return1 (1),
@ -211,13 +211,18 @@ fn value_size () {
assert! (size_of::<Box <()>> () <= 8);
assert! (size_of::<std::rc::Rc <()>> () <= 8);
pub enum Value {
enum Value {
Nil,
Boolean (bool),
Float (f64),
String (Rc <String>),
}
assert_eq! (size_of::<Value> (), 16);
assert_eq! (size_of::<crate::state::Value> (), 16);
let sz = size_of::<Value> ();
let expected = 16;
assert! (sz <= expected, "{sz} > {expected}");
let sz = size_of::<crate::state::Value> ();
let expected = 16;
assert! (sz <= expected, "{sz} > {expected}");
}