diff --git a/src/state.rs b/src/state.rs index 3600467..722810b 100644 --- a/src/state.rs +++ b/src/state.rs @@ -7,7 +7,6 @@ use crate::{ instruction::Instruction, value::{ BogusClosure, - Table, Value, }, }; @@ -226,7 +225,9 @@ impl State { _ => 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) => { let t = match self.reg (*b) { @@ -236,7 +237,7 @@ impl State { let key = self.reg (*c); - let val = t.get (key.clone ()); + let val = t.borrow ().get (key.clone ()); *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::Table (t) => { let key = Value::from (i64::try_from (key).unwrap ()); - t.get (key) + t.borrow ().get (key) }, _ => unimplemented! (), }; @@ -419,10 +420,10 @@ impl State { _ => panic! ("GetTabUp only supports string keys"), }; - let dst = self.reg_mut (*a).as_table_mut () - .expect ("SetField only works on tables"); + let mut dst = self.reg (*a).as_table () + .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) => { let value = if *k_flag { @@ -433,10 +434,9 @@ impl State { } .clone (); - let dst = self.reg_mut (*a).as_table_mut () - .expect ("SetI only works on tables"); + let mut dst = self.reg_mut (*a).as_table ().expect ("SetI only works on tables").borrow_mut (); - Rc::get_mut (dst).expect ("shrug").insert (i64::from (*b), value); + dst.insert (i64::from (*b), value); }, Instruction::SetList (a, b, c, k) => { if *b == 0 { @@ -446,18 +446,12 @@ impl State { panic! ("SetList with k = true not implemented"); } - // Temporarily move the table out - - 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 (); + let mut dst = self.reg (*a).as_table ().expect ("SetList only works on tables").borrow_mut (); for i in 1..=*b { let src = self.reg (*a + i); 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::TailCall (_a, _b, _c, _k) => unimplemented! (), diff --git a/src/tests.rs b/src/tests.rs index 6d5202e..7634421 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -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 ), + T (Rc >>), + } + + 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] fn is_93 () { assert_eq! (Value::from ("93"), Value::from ("93")); diff --git a/src/value.rs b/src/value.rs index 2fbe524..4547065 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,4 +1,5 @@ use std::{ + cell::RefCell, cmp::{ Eq, PartialEq, @@ -25,7 +26,7 @@ pub enum Value { Integer (i64), String (Rc ), - Table (Rc ), + Table (Rc >), // These are all bogus, I haven't figured out how to implement // tables and function pointers yet @@ -99,7 +100,7 @@ impl From for Value { impl From
for Value { 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
> { + pub fn as_table (&self) -> Option <&Rc >> { match self { Self::Table (t) => Some (t), _ => None, diff --git a/test_vectors/hello.lua b/test_vectors/hello.lua index 4d882e8..167d7aa 100644 --- a/test_vectors/hello.lua +++ b/test_vectors/hello.lua @@ -28,10 +28,10 @@ c [1] = "ddd" local a = { c } local b = { c } -print (a [1]) -print (b [1]) +print (a [1][2]) +print (b [1][2]) c [2] = "eee" -print (a [2]) -print (b [2]) +print (a [1][2]) +print (b [1][2])