🐛 bug: switch to RefCell so some more of the tables tests will pass

main
_ 2023-09-26 21:43:02 -05:00
parent 0d5e1098bc
commit fcfd9397ff
4 changed files with 77 additions and 24 deletions

View File

@ -7,7 +7,6 @@ use crate::{
instruction::Instruction, instruction::Instruction,
value::{ value::{
BogusClosure, BogusClosure,
Table,
Value, Value,
}, },
}; };
@ -226,7 +225,9 @@ impl State {
_ => panic! ("K[C] must be a string"), _ => panic! ("K[C] must be a string"),
}; };
*self.reg_mut (*a) = t.get (Value::String (Rc::clone (key))); let val = t.borrow ().get (Value::String (Rc::clone (key)));
*self.reg_mut (*a) = val;
}, },
Instruction::GetTable (a, b, c) => { Instruction::GetTable (a, b, c) => {
let t = match self.reg (*b) { let t = match self.reg (*b) {
@ -236,7 +237,7 @@ impl State {
let key = self.reg (*c); let key = self.reg (*c);
let val = t.get (key.clone ()); let val = t.borrow ().get (key.clone ());
*self.reg_mut (*a) = val; *self.reg_mut (*a) = val;
}, },
@ -265,7 +266,7 @@ impl State {
Value::BogusArg (arg) => arg.get (key).map (|x| x.as_str().into ()).unwrap_or_default(), Value::BogusArg (arg) => arg.get (key).map (|x| x.as_str().into ()).unwrap_or_default(),
Value::Table (t) => { Value::Table (t) => {
let key = Value::from (i64::try_from (key).unwrap ()); let key = Value::from (i64::try_from (key).unwrap ());
t.get (key) t.borrow ().get (key)
}, },
_ => unimplemented! (), _ => unimplemented! (),
}; };
@ -419,10 +420,10 @@ impl State {
_ => panic! ("GetTabUp only supports string keys"), _ => panic! ("GetTabUp only supports string keys"),
}; };
let dst = self.reg_mut (*a).as_table_mut () let mut dst = self.reg (*a).as_table ()
.expect ("SetField only works on tables"); .expect ("SetField only works on tables").borrow_mut ();
Rc::get_mut (dst).expect ("shrug").insert (Value::from (key.as_str ()), value); dst.insert (Value::from (key.as_str ()), value);
}, },
Instruction::SetI (a, b, c, k_flag) => { Instruction::SetI (a, b, c, k_flag) => {
let value = if *k_flag { let value = if *k_flag {
@ -433,10 +434,9 @@ impl State {
} }
.clone (); .clone ();
let dst = self.reg_mut (*a).as_table_mut () let mut dst = self.reg_mut (*a).as_table ().expect ("SetI only works on tables").borrow_mut ();
.expect ("SetI only works on tables");
Rc::get_mut (dst).expect ("shrug").insert (i64::from (*b), value); dst.insert (i64::from (*b), value);
}, },
Instruction::SetList (a, b, c, k) => { Instruction::SetList (a, b, c, k) => {
if *b == 0 { if *b == 0 {
@ -446,18 +446,12 @@ impl State {
panic! ("SetList with k = true not implemented"); panic! ("SetList with k = true not implemented");
} }
// Temporarily move the table out let mut dst = self.reg (*a).as_table ().expect ("SetList only works on tables").borrow_mut ();
let mut dst = Rc::into_inner (std::mem::replace (self.reg_mut (*a).as_table_mut ().expect ("SetList only works on tables"), Default::default ())).unwrap ();
for i in 1..=*b { for i in 1..=*b {
let src = self.reg (*a + i); let src = self.reg (*a + i);
dst.insert (Value::from (i64::from (*c + i)), src.clone ()); dst.insert (Value::from (i64::from (*c + i)), src.clone ());
} }
// Put the table back and pretend it's all okay
*self.reg_mut (*a) = Value::Table (dst.into ());
}, },
Instruction::SetTabUp (_a, _b, _c) => unimplemented! (), Instruction::SetTabUp (_a, _b, _c) => unimplemented! (),
Instruction::TailCall (_a, _b, _c, _k) => unimplemented! (), Instruction::TailCall (_a, _b, _c, _k) => unimplemented! (),

View File

@ -214,6 +214,64 @@ fn fma () {
} }
} }
#[test]
fn heap () {
use std::{
cell::RefCell,
collections::HashMap,
rc::Rc,
};
use crate::value::Table;
{
let mut allocations = HashMap::new ();
let mut ctr = 0;
let c = ctr;
allocations.insert (ctr, Table::default ());
ctr += 1;
let a = ctr;
allocations.insert (ctr, Table::default ());
ctr += 1;
allocations.get_mut (&a).unwrap ().insert (1, c);
allocations.get_mut (&c).unwrap ().insert (2, "eee");
}
if true {
#[derive (Clone, Debug, PartialEq)]
enum Value {
S (Rc <String>),
T (Rc <RefCell <HashMap <i64, Value>>>),
}
let c = Value::T (Default::default ());
let a = Value::T (Default::default ());
match &a {
Value::T (t) => t.borrow_mut ().insert (1, c.clone ()),
_ => panic! ("impossible"),
};
match &c {
Value::T (t) => t.borrow_mut ().insert (2, Value::S (Rc::new (String::from ("eee")))),
_ =>panic! ("impossible"),
};
let actual = match &a {
Value::T (t) => match t.borrow ().get (&1) {
Some (Value::T (t)) => t.borrow ().get (&2).unwrap ().clone (),
_ => panic! ("impossible"),
},
_ => panic! ("impossible"),
};
assert_eq! (actual, Value::S (Rc::new ("eee".into ())));
}
}
#[test] #[test]
fn is_93 () { fn is_93 () {
assert_eq! (Value::from ("93"), Value::from ("93")); assert_eq! (Value::from ("93"), Value::from ("93"));

View File

@ -1,4 +1,5 @@
use std::{ use std::{
cell::RefCell,
cmp::{ cmp::{
Eq, Eq,
PartialEq, PartialEq,
@ -25,7 +26,7 @@ pub enum Value {
Integer (i64), Integer (i64),
String (Rc <String>), String (Rc <String>),
Table (Rc <Table>), Table (Rc <RefCell <Table>>),
// These are all bogus, I haven't figured out how to implement // These are all bogus, I haven't figured out how to implement
// tables and function pointers yet // tables and function pointers yet
@ -99,7 +100,7 @@ impl From <f64> for Value {
impl From <Table> for Value { impl From <Table> for Value {
fn from (x: Table) -> Self { fn from (x: Table) -> Self {
Self::Table (x.into ()) Self::Table (Rc::new (RefCell::new (x)))
} }
} }
@ -145,7 +146,7 @@ impl Value {
} }
} }
pub fn as_table_mut (&mut self) -> Option <&mut Rc <Table>> { pub fn as_table (&self) -> Option <&Rc <RefCell <Table>>> {
match self { match self {
Self::Table (t) => Some (t), Self::Table (t) => Some (t),
_ => None, _ => None,

View File

@ -28,10 +28,10 @@ c [1] = "ddd"
local a = { c } local a = { c }
local b = { c } local b = { c }
print (a [1]) print (a [1][2])
print (b [1]) print (b [1][2])
c [2] = "eee" c [2] = "eee"
print (a [2]) print (a [1][2])
print (b [2]) print (b [1][2])