diff --git a/src/state.rs b/src/state.rs index 6e3f3c7..4821b14 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,7 +1,4 @@ -use std::{ - collections::HashMap, - rc::Rc, -}; +use std::rc::Rc; use crate::{ instruction::Instruction, @@ -71,15 +68,16 @@ impl Default for State { impl State { pub fn upvalues_from_args > (args: I) -> Vec { - let arg: Vec <_> = args.map (|s| s.to_string ()).collect (); + let arg = args.map (|s| Value::from (s)).enumerate (); + let arg = Value::from_iter (arg.map (|(i, v)| (Value::from (i), v))); - let env = HashMap::from_iter ([ - ("arg", Value::BogusArg (arg.into ())), + let env = [ + ("arg", arg), ("print", Value::BogusPrint), - ].map (|(k, v)| (k.to_string (), v))); + ].into_iter ().map (|(k, v)| (k.to_string (), v)); vec! [ - Value::BogusEnv (env.into ()), + Value::from_iter (env.into_iter ()), ] } @@ -272,30 +270,21 @@ impl State { let b = usize::try_from (*b).unwrap (); let c = usize::try_from (*c).unwrap (); - let env = match upvalues.get (b).unwrap () { - Value::BogusEnv (x) => x, - _ => panic! ("Only allowed upvalue is BogusEnv"), - }; + let table = upvalues.get (b).unwrap ().as_table ().expect ("GetTabUp only works on tables").borrow (); let key = match k.get (c).unwrap () { - Value::String (s) => s.as_ref (), + Value::String (s) => String::from (s.as_ref()), _ => panic! ("GetTabUp only supports string keys"), }; - let value = env.get (key).unwrap (); - *self.reg_mut (*a) = value.clone (); + *self.reg_mut (*a) = table.get (key); }, Instruction::GetI (a, b, c) => { - let key = usize::try_from (*c).unwrap (); + let key = i64::try_from (*c).unwrap (); - let table = self.reg (*b); - let value = match table { - 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.borrow ().get (key) - }, - _ => unimplemented! (), + let value = { + let table = self.reg (*b).as_table ().expect ("GetI only works on tables").borrow (); + table.get (key) }; *self.reg_mut (*a) = value; diff --git a/src/value.rs b/src/value.rs index ad2b8b7..4f61e28 100644 --- a/src/value.rs +++ b/src/value.rs @@ -29,11 +29,9 @@ pub enum Value { Table (Rc >), // These are all bogus, I haven't figured out how to implement - // tables and function pointers yet + // closures yet - BogusArg (Rc >), BogusClosure (Rc ), - BogusEnv (Rc >), BogusPrint, } @@ -54,9 +52,7 @@ impl fmt::Display for Value { Value::String (s) => write! (f, "{}", s), Value::Table (t) => write! (f, "table: {:?}", std::rc::Rc::as_ptr (t)), - Value::BogusArg (_) => write! (f, "BogusArg"), Value::BogusClosure (_) => write! (f, "BogusClosure"), - Value::BogusEnv (_) => write! (f, "BogusEnv"), Value::BogusPrint => write! (f, "BogusPrint"), } } @@ -98,12 +94,37 @@ impl From for Value { } } +impl From for Value { + fn from (x: usize) -> Self { + Self::Integer (i64::try_from (x).unwrap ()) + } +} + impl From for Value { fn from (x: Table) -> Self { Self::Table (Rc::new (RefCell::new (x))) } } +impl FromIterator <(Value, Value)> for Value { + fn from_iter > (i: I) -> Self { + let table = Table::from_iter (i); + Self::from (table) + } +} + +impl FromIterator <(String, Value)> for Value { + fn from_iter > (i: I) -> Self { + Self::from_iter (i.into_iter ().map (|(s, v)| (Value::from (s), v))) + } +} + +impl FromIterator for Value { + fn from_iter > (i: I) -> Self { + Self::from_iter ((1..).zip (i.into_iter ()).map (|(i, v)| (Value::from (i), v))) + } +} + impl Eq for Value {} impl std::hash::Hash for Value { @@ -122,9 +143,7 @@ impl std::hash::Hash for Value { Self::String (x) => x.hash (state), Self::Table (x) => Rc::as_ptr (&x).hash (state), - Self::BogusArg (_) => panic! ("can't hash Bogus values"), Self::BogusClosure (_) => panic! ("can't hash Bogus values"), - Self::BogusEnv (_) => panic! ("can't hash Bogus values"), Self::BogusPrint => panic! ("can't hash Bogus values"), } } @@ -205,6 +224,17 @@ impl Table { } } +impl FromIterator <(Value, Value)> for Table { + fn from_iter> (i: I) -> Self + { + let hash = i.into_iter ().collect (); + Self { + array: Default::default (), + hash, + } + } +} + #[cfg (test)] mod tests { use std::collections::HashMap;