🐛 bug: switch to RefCell so some more of the tables tests will pass
parent
0d5e1098bc
commit
fcfd9397ff
28
src/state.rs
28
src/state.rs
|
@ -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! (),
|
||||||
|
|
58
src/tests.rs
58
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 <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"));
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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])
|
||||||
|
|
Loading…
Reference in New Issue