diff --git a/src/callable/primitive/c.rs b/src/callable/primitive/c.rs index c79490ce..a6ad91e7 100644 --- a/src/callable/primitive/c.rs +++ b/src/callable/primitive/c.rs @@ -53,7 +53,6 @@ impl Callable for PrimitiveC { // lets first see what we're aiming to build. let ty: u8 = vals .values - .borrow() .iter() .map(|(_, v)| match v { Obj::Null => 0, @@ -76,7 +75,6 @@ impl Callable for PrimitiveC { // otherwise, try to collapse vectors into same type let ret = vals .values - .borrow() .iter() .map(|(_, r)| match r { Obj::Vector(Vector::Logical(_)) => Vector::from(Vec::::new()), diff --git a/src/callable/primitive/names.rs b/src/callable/primitive/names.rs index ac809071..67348b38 100644 --- a/src/callable/primitive/names.rs +++ b/src/callable/primitive/names.rs @@ -68,7 +68,6 @@ impl Callable for PrimitiveNames { Function(..) => Ok(Null), // return formals? List(x) => { Ok(x.values - .borrow() .iter() .map(|(k, _)| match k { Some(name) => OptionNA::Some(name.clone()), diff --git a/src/lang.rs b/src/lang.rs index c215b499..3262aa69 100644 --- a/src/lang.rs +++ b/src/lang.rs @@ -8,7 +8,7 @@ use crate::object::*; use crate::parser::LocalizedParser; use crate::parser::ParseResult; use crate::session::{Session, SessionParserConfig}; -use std::collections::HashSet; +use hashbrown::HashSet; use core::fmt; use std::fmt::Display; @@ -229,7 +229,6 @@ impl Obj { match self { Obj::List(v) => v .values - .borrow() .iter() .find(|(k, _)| *k == Some(String::from(name))) .map(|(_, v)| v.clone()), @@ -1170,7 +1169,7 @@ pub fn assert_formals(session: &Session, formals: ExprList) -> Result true, (Obj::List(l), Obj::List(r)) => { - let lb = l.values.borrow(); - let rb = r.values.borrow(); - let liter = lb.iter(); - let riter = rb.iter(); + let liter = l.values.iter(); + let riter = r.values.iter(); liter .zip(riter) .all(|((lk, lv), (rk, rv))| lk == rk && lv == rv) diff --git a/src/object/environment.rs b/src/object/environment.rs index 7342b966..232d79ba 100644 --- a/src/object/environment.rs +++ b/src/object/environment.rs @@ -55,7 +55,7 @@ impl Environment { } pub fn append(&self, l: List) { - for (key, value) in l.values.borrow().iter() { + for (key, value) in l.values.iter() { if let Some(name) = key { self.values.borrow_mut().insert(name.clone(), value.clone()); } diff --git a/src/object/vector/core.rs b/src/object/vector/core.rs index 8e9b25d2..18eeb539 100644 --- a/src/object/vector/core.rs +++ b/src/object/vector/core.rs @@ -54,7 +54,12 @@ pub enum Vector { impl Clone for Vector { fn clone(&self) -> Self { - self.lazy_copy() + match self { + Vector::Double(v) => Vector::Double(v.clone()), + Vector::Character(v) => Vector::Character(v.clone()), + Vector::Integer(v) => Vector::Integer(v.clone()), + Vector::Logical(v) => Vector::Logical(v.clone()), + } } } @@ -69,18 +74,6 @@ impl Vector { } } - /// Create a lazy copy of the vector. - /// When mutating vectors, the internal data only needs to be copied when there is more than - /// one such lazy copy. - pub fn lazy_copy(&self) -> Self { - match self { - Vector::Double(v) => Vector::Double(v.clone()), - Vector::Character(v) => Vector::Character(v.clone()), - Vector::Integer(v) => Vector::Integer(v.clone()), - Vector::Logical(v) => Vector::Logical(v.clone()), - } - } - pub fn try_get(&self, index: Obj) -> EvalResult { let err = Error::Other("Vector index cannot be coerced into a valid indexing type.".to_string()); diff --git a/src/object/vector/rep.rs b/src/object/vector/rep.rs index 7ce94f9c..648907fb 100644 --- a/src/object/vector/rep.rs +++ b/src/object/vector/rep.rs @@ -8,8 +8,7 @@ use super::reptype::RepTypeIter; use super::subset::Subset; use super::types::*; use super::{OptionNA, Pow, VecPartialCmp}; -use crate::object::CowObj; -use crate::object::ViewMut; +use crate::object::{CowObj, Obj, ViewMut}; /// Vector Representation /// @@ -18,7 +17,7 @@ use crate::object::ViewMut; #[derive(Debug, PartialEq)] pub struct Rep(pub RefCell>); -impl Clone for Rep { +impl Clone for Rep { fn clone(&self) -> Self { match self.borrow().clone() { RepType::Subset(v, s) => Rep(RefCell::new(RepType::Subset(v.clone(), s.clone()))), @@ -26,17 +25,23 @@ impl Clone for Rep { } } -impl ViewMut for Rep { +impl ViewMut for Rep { fn view_mut(&self) -> Self { Self(RefCell::new(self.borrow().view_mut())) } } +impl Rep { + pub fn get_inner_mut(&self, index: usize) -> Option { + self.0.borrow().get_inner_mut(index) + } +} + impl Rep where - T: AtomicMode + Clone + Default, + T: Clone + Default, { - fn borrow(&self) -> Ref> { + pub fn borrow(&self) -> Ref> { self.0.borrow() } fn materialize_inplace(&self) -> &Self { @@ -47,6 +52,14 @@ where self } + /// Try to get mutable access to the internal vector through the passed closure. + pub fn with_inner_mut(&self, f: F) -> R + where + F: FnOnce(&mut Vec) -> R, + { + self.0.borrow().with_inner_mut(f) + } + pub fn materialize(&self) -> Self { self.borrow().materialize().into() } @@ -101,6 +114,10 @@ where x.map(|x| x.into()) } + pub fn get_inner(&self, index: usize) -> Option { + self.borrow().get_inner(index) + } + pub fn assign(&mut self, value: Self) -> Self { self.0.borrow_mut().assign(value.0.into_inner()).into() } @@ -109,19 +126,31 @@ where /// Internally, this is defined by the [crate::object::coercion::AtomicMode] /// implementation of the vector's element type. /// - pub fn is_double(&self) -> bool { + pub fn is_double(&self) -> bool + where + T: AtomicMode, + { T::is_double() } /// See [Self::is_double] for more information - pub fn is_logical(&self) -> bool { + pub fn is_logical(&self) -> bool + where + T: AtomicMode, + { T::is_logical() } /// See [Self::is_double] for more information - pub fn is_integer(&self) -> bool { + pub fn is_integer(&self) -> bool + where + T: AtomicMode, + { T::is_integer() } /// See [Self::is_double] for more information - pub fn is_character(&self) -> bool { + pub fn is_character(&self) -> bool + where + T: AtomicMode, + { T::is_character() } @@ -151,7 +180,7 @@ where /// pub fn as_mode(&self) -> Rep where - T: CoercibleInto, + T: CoercibleInto + AtomicMode, Mode: Clone, { Rep(RefCell::new(self.borrow().as_mode())) @@ -160,7 +189,7 @@ where /// See [Self::as_mode] for more information pub fn as_logical(&self) -> Rep where - T: CoercibleInto, + T: CoercibleInto + AtomicMode, { self.as_mode::() } @@ -168,7 +197,7 @@ where /// See [Self::as_mode] for more information pub fn as_integer(&self) -> Rep where - T: CoercibleInto, + T: CoercibleInto + AtomicMode, { self.as_mode::() } @@ -176,7 +205,7 @@ where /// See [Self::as_mode] for more information pub fn as_double(&self) -> Rep where - T: CoercibleInto, + T: CoercibleInto + AtomicMode, { self.as_mode::() } @@ -184,7 +213,7 @@ where /// See [Self::as_mode] for more information pub fn as_character(&self) -> Rep where - T: CoercibleInto, + T: CoercibleInto + AtomicMode, { self.as_mode::() } @@ -210,14 +239,14 @@ where .vectorized_partial_cmp(other.0.into_inner()) } - fn get_inner(&self, index: usize) -> Option { - self.borrow().get_inner(index) + pub fn iter(&self) -> RepIter { + self.clone().into_iter() } } impl Default for Rep where - T: AtomicMode + Clone + Default, + T: Clone + Default, { fn default() -> Self { Rep(RefCell::new(RepType::default())) @@ -228,7 +257,7 @@ pub struct RepIter(RepTypeIter); impl IntoIterator for Rep where - T: AtomicMode + Clone + Default, + T: Clone + Default, { type Item = T; type IntoIter = RepIter; @@ -240,7 +269,7 @@ where impl Iterator for RepIter where - T: AtomicMode + Clone + Default, + T: Clone + Default, { type Item = T; fn next(&mut self) -> Option { @@ -250,7 +279,7 @@ where impl From> for Rep where - T: AtomicMode + Clone + Default, + T: Clone + Default, { fn from(rep: RepType) -> Self { Rep(RefCell::new(rep)) @@ -273,6 +302,12 @@ where } } +impl From, Obj)>> for Rep<(Option, Obj)> { + fn from(value: Vec<(Option, Obj)>) -> Self { + Rep(RefCell::new(value.into())) + } +} + impl From>> for Rep { fn from(value: Vec>) -> Self { Rep(RefCell::new(value.into())) diff --git a/src/object/vector/reptype.rs b/src/object/vector/reptype.rs index 74c5f607..d876045c 100644 --- a/src/object/vector/reptype.rs +++ b/src/object/vector/reptype.rs @@ -6,7 +6,7 @@ use super::subset::Subset; use super::subsets::Subsets; use super::types::*; use super::{OptionNA, Pow, VecPartialCmp}; -use crate::object::{CowObj, ViewMut}; +use crate::object::{CowObj, Obj, ViewMut}; /// Vector #[derive(Debug, PartialEq)] @@ -25,15 +25,28 @@ impl Clone for RepType { } } -impl Default for RepType { +impl Default for RepType { fn default() -> Self { Self::new() } } +impl RepType { + /// Retrieve the internal data as a mutable view. + pub fn get_inner_mut(&self, index: usize) -> Option { + match self { + RepType::Subset(v, subsets) => { + let vb = v.borrow(); + let index = subsets.get_index_at(index).unwrap(); + vb.get(index).map(|i| i.view_mut()) + } + } + } +} + impl IntoIterator for RepType where - T: AtomicMode + Clone + Default, + T: Clone + Default, { type Item = T; type IntoIter = RepTypeIter; @@ -50,13 +63,13 @@ pub enum RepTypeIter { SubsetIter(RepType, usize, usize), } -impl Iterator for RepTypeIter { +impl Iterator for RepTypeIter { type Item = T; fn next(&mut self) -> Option { match self { RepTypeIter::SubsetIter(rep, i, len) => { if i < len { - let x = Some(rep.get_atom(*i)); + let x = rep.get_inner(*i); *i += 1; x } else { @@ -75,7 +88,7 @@ impl ViewMut for RepType { } } -impl RepType { +impl RepType { /// Create an empty vector /// /// The primary use case for this function is to support testing, and there @@ -105,10 +118,19 @@ impl RepType { } } + /// Try to get mutable access to the internal vector through the passed closure. + pub fn with_inner_mut(&self, f: F) -> R + where + F: FnOnce(&mut Vec) -> R, + { + match self { + RepType::Subset(v, _) => v.with_inner_mut(f), + } + } + /// Subsetting a Vector /// /// Introduce a new subset into the aggregate list of subset indices. - /// pub fn subset(&self, subset: Subset) -> Self { match self { RepType::Subset(v, Subsets(subsets)) => { @@ -127,7 +149,6 @@ impl RepType { }, } } - #[must_use] pub fn is_empty(&self) -> bool { self.len() == 0 @@ -151,16 +172,6 @@ impl RepType { } } - pub fn get_atom(&self, index: usize) -> T { - match self { - RepType::Subset(v, subsets) => { - let vb = v.borrow(); - let index = subsets.get_index_at(index).unwrap(); - vb[index].clone() - } - } - } - /// Assignment to Subset Indices /// /// Assignment to a vector from another. The aggregate subsetted indices @@ -197,13 +208,21 @@ impl RepType { /// Materialize a Vector /// /// Apply subsets and clone values into a new vector. - /// pub fn materialize(&self) -> Self where T: Clone, { match self { RepType::Subset(v, subsets) => { + // early exit when there is nothing to do + match subsets { + Subsets(s) => { + if s.as_slice().is_empty() { + return self.clone(); + } + } + } + let vc = v.clone(); let vb = vc.borrow(); let mut res: Vec = vec![]; @@ -222,19 +241,31 @@ impl RepType { } } - pub fn is_double(&self) -> bool { + pub fn is_double(&self) -> bool + where + T: AtomicMode, + { T::is_double() } - pub fn is_logical(&self) -> bool { + pub fn is_logical(&self) -> bool + where + T: AtomicMode, + { T::is_logical() } - pub fn is_integer(&self) -> bool { + pub fn is_integer(&self) -> bool + where + T: AtomicMode, + { T::is_integer() } - pub fn is_character(&self) -> bool { + pub fn is_character(&self) -> bool + where + T: AtomicMode, + { T::is_character() } @@ -334,6 +365,12 @@ where } } +impl From, Obj)>> for RepType<(Option, Obj)> { + fn from(value: Vec<(Option, Obj)>) -> Self { + RepType::Subset(value.into(), Subsets::default()) + } +} + impl From>> for RepType { fn from(value: Vec>) -> Self { let value: Vec<_> = value.into_iter().map(|i| i.coerce_into()).collect();