diff options
author | Aria Shrimpton <me@aria.rip> | 2024-03-19 15:59:13 +0000 |
---|---|---|
committer | Aria Shrimpton <me@aria.rip> | 2024-03-19 21:27:31 +0000 |
commit | 443951f481148db0b06d545d6f22a06f59df2606 (patch) | |
tree | 46e5a7ef534cacc9a989113e84efebeede715684 | |
parent | 69f00cd8d8fe977e59feddb166f018be6480110c (diff) |
more library types & more consistent naming
-rw-r--r-- | src/crates/library/src/adaptive.rs | 8 | ||||
-rw-r--r-- | src/crates/library/src/lib.rs | 19 | ||||
-rw-r--r-- | src/crates/library/src/proptest/strategies.rs | 18 | ||||
-rw-r--r-- | src/crates/library/src/sortedvec.rs (renamed from src/crates/library/src/sorted_vector.rs) | 0 | ||||
-rw-r--r-- | src/crates/library/src/sortedvecmap.rs | 139 | ||||
-rw-r--r-- | src/crates/library/src/sortedvecset.rs (renamed from src/crates/library/src/sorted_unique_vector.rs) | 72 | ||||
-rw-r--r-- | src/crates/library/src/vecmap.rs | 143 | ||||
-rw-r--r-- | src/crates/library/src/vecset.rs | 356 |
8 files changed, 705 insertions, 50 deletions
diff --git a/src/crates/library/src/adaptive.rs b/src/crates/library/src/adaptive.rs index 179a2fa..5f21716 100644 --- a/src/crates/library/src/adaptive.rs +++ b/src/crates/library/src/adaptive.rs @@ -194,12 +194,11 @@ where mod tests { use std::collections::HashSet; - use crate::{traits::Container, AdaptiveContainer, SortedUniqueVec}; + use crate::{traits::Container, AdaptiveContainer, SortedVecSet}; #[test] fn adaptive_container_lo_functionality() { - let mut c: AdaptiveContainer<10, SortedUniqueVec<_>, HashSet<_>, usize> = - Default::default(); + let mut c: AdaptiveContainer<10, SortedVecSet<_>, HashSet<_>, usize> = Default::default(); for i in 0..5 { c.insert(i); @@ -210,8 +209,7 @@ mod tests { #[test] fn adaptive_container_adapts() { - let mut c: AdaptiveContainer<10, SortedUniqueVec<_>, HashSet<_>, usize> = - Default::default(); + let mut c: AdaptiveContainer<10, SortedVecSet<_>, HashSet<_>, usize> = Default::default(); for i in 1..=9 { c.insert(i); diff --git a/src/crates/library/src/lib.rs b/src/crates/library/src/lib.rs index 44df8db..4a0c94f 100644 --- a/src/crates/library/src/lib.rs +++ b/src/crates/library/src/lib.rs @@ -10,9 +10,6 @@ pub use profiler::{MappingProfilerWrapper, ProfilerWrapper}; mod adaptive; pub use adaptive::AdaptiveContainer; -mod sorted_unique_vector; -mod sorted_vector; - mod btreemap; mod hashmap; mod hashset; @@ -20,8 +17,20 @@ mod list; mod treeset; mod vector; -pub use sorted_unique_vector::SortedUniqueVec; -pub use sorted_vector::SortedVec; +mod vecset; +pub use vecset::VecSet; + +mod vecmap; +pub use vecmap::VecMap; + +mod sortedvec; +pub use sortedvec::SortedVec; + +mod sortedvecset; +pub use sortedvecset::SortedVecSet; + +mod sortedvecmap; +pub use sortedvecmap::SortedVecMap; #[cfg(test)] pub mod proptest; diff --git a/src/crates/library/src/proptest/strategies.rs b/src/crates/library/src/proptest/strategies.rs index e61daa4..69a860e 100644 --- a/src/crates/library/src/proptest/strategies.rs +++ b/src/crates/library/src/proptest/strategies.rs @@ -2,18 +2,18 @@ use proptest::prelude::*; use std::ops::Range; -use crate::{SortedUniqueVec, SortedVec}; +use crate::{SortedVec, SortedVecSet, VecSet}; use proptest::collection::vec; -pub fn sorted_unique_vec<T: Strategy + 'static>( +pub fn sorted_vec_set<T: Strategy + 'static>( element: T, size: Range<usize>, -) -> impl Strategy<Value = SortedUniqueVec<T::Value>> +) -> impl Strategy<Value = SortedVecSet<T::Value>> where <T as Strategy>::Value: PartialEq + Ord, { - vec(element, size.clone()).prop_map(SortedUniqueVec::from_vec) + vec(element, size.clone()).prop_map(SortedVecSet::from_vec) } pub fn sorted_vec<T: Strategy + 'static>( @@ -25,3 +25,13 @@ where { vec(element, size.clone()).prop_map(SortedVec::from_vec) } + +pub fn vec_set<T: Strategy + 'static>( + element: T, + size: Range<usize>, +) -> impl Strategy<Value = VecSet<T::Value>> +where + <T as Strategy>::Value: Ord, +{ + vec(element, size.clone()).prop_map(VecSet::from_vec) +} diff --git a/src/crates/library/src/sorted_vector.rs b/src/crates/library/src/sortedvec.rs index 925e3ef..925e3ef 100644 --- a/src/crates/library/src/sorted_vector.rs +++ b/src/crates/library/src/sortedvec.rs diff --git a/src/crates/library/src/sortedvecmap.rs b/src/crates/library/src/sortedvecmap.rs new file mode 100644 index 0000000..1f05200 --- /dev/null +++ b/src/crates/library/src/sortedvecmap.rs @@ -0,0 +1,139 @@ +/*LIBSPEC-NAME* +rust-hashmap-spec primrose_library::SortedVecMap +*ENDLIBSPEC-NAME*/ + +use crate::{traits::Mapping, vecmap::extract_key}; +use std::{hash::Hash, mem::replace}; + +#[derive(Clone)] +pub struct SortedVecMap<K, V> { + v: Vec<(K, V)>, +} + +/*IMPL* +Mapping +*ENDIMPL*/ +impl<K: Ord + Hash, V> Mapping<K, V> for SortedVecMap<K, V> { + /*LIBSPEC* + /*OPNAME* + len op-len pre-len post-len + *ENDOPNAME*/ + (define (pre-len xs) (is-map? xs)) + (define (op-len xs) (cons xs (length xs))) + (define (post-len xs r) (equal? r (op-len xs))) + *ENDLIBSPEC*/ + fn len(&self) -> usize { + self.v.len() + } + + /*LIBSPEC* + /*OPNAME* + contains op-contains pre-contains post-contains + *ENDOPNAME*/ + (define (pre-contains xs) (is-map? xs)) + (define (op-contains xs k) (assoc k xs)) + (define (post-contains xs k r) (equal? r (op-contains xs k))) + *ENDLIBSPEC*/ + fn contains(&mut self, key: &K) -> bool { + self.v.binary_search_by_key(&key, extract_key).is_ok() + } + + /*LIBSPEC* + /*OPNAME* + insert op-insert pre-insert post-insert + *ENDOPNAME*/ + (define (pre-insert xs) (is-map? xs)) + (define (op-insert xs k v) + (let ([idx (index-where xs (lambda (p) (equal? k (car p))))]) + (cond [idx (list-set xs idx (cons k v))] + [else (list* (cons k v) xs)]))) + (define (post-insert xs k v r) (equal? r (op-insert xs k v))) + *ENDLIBSPEC*/ + fn insert(&mut self, key: K, val: V) -> Option<V> { + match self.v.binary_search_by_key(&&key, extract_key) { + Ok(idx) => Some(replace(&mut self.v[idx].1, val)), + Err(idx) => { + self.v.insert(idx, (key, val)); + None + } + } + } + + /*LIBSPEC* + /*OPNAME* + get op-get pre-get post-get + *ENDOPNAME*/ + (define (pre-get xs) (is-map? xs)) + (define (op-get xs k) (cdr (assoc k xs))) + (define (post-get xs k r) (equal? r (op-get xs k))) + *ENDLIBSPEC*/ + fn get(&self, key: &K) -> Option<&V> { + Some(&self.v[self.v.binary_search_by_key(&key, extract_key).ok()?].1) + } + + /*LIBSPEC* + /*OPNAME* + remove op-remove pre-remove post-remove + *ENDOPNAME*/ + (define (pre-remove xs) (is-map? xs)) + (define (op-remove xs k) (cdr (assoc k xs))) + (define (post-remove xs k r) (equal? r (op-remove xs k))) + *ENDLIBSPEC*/ + fn remove(&mut self, key: &K) -> Option<V> { + Some( + self.v + .remove(self.v.binary_search_by_key(&key, extract_key).ok()?) + .1, + ) + } + + /*LIBSPEC* + /*OPNAME* + clear op-clear pre-clear post-clear + *ENDOPNAME*/ + (define (pre-clear xs) (is-map? xs)) + (define (op-clear xs) null) + (define (post-clear xs r) (equal? r (op-clear xs))) + *ENDLIBSPEC*/ + fn clear(&mut self) { + self.v.clear() + } + + fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a K, &'a V)> + 'a + where + K: 'a, + V: 'a, + { + self.v.iter().map(|(k, v)| (k, v)) + } +} + +impl<K, V> Default for SortedVecMap<K, V> { + fn default() -> Self { + Self { v: Vec::default() } + } +} + +impl<K: Ord, V> FromIterator<(K, V)> for SortedVecMap<K, V> { + fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self { + let mut v: Vec<(K, V)> = iter.into_iter().collect(); + v.sort_by(|(k1, _), (k2, _)| k1.cmp(k2)); + v.dedup_by(|(k1, _), (k2, _)| k1 == k2); + Self { v } + } +} + +impl<K, V> IntoIterator for SortedVecMap<K, V> { + type Item = (K, V); + + type IntoIter = std::vec::IntoIter<(K, V)>; + + fn into_iter(self) -> Self::IntoIter { + self.v.into_iter() + } +} + +#[cfg(test)] +mod tests { + // TODO +} diff --git a/src/crates/library/src/sorted_unique_vector.rs b/src/crates/library/src/sortedvecset.rs index b974693..0016374 100644 --- a/src/crates/library/src/sorted_unique_vector.rs +++ b/src/crates/library/src/sortedvecset.rs @@ -1,5 +1,5 @@ /*LIBSPEC-NAME* -rust-eager-unique-vec-spec primrose_library::SortedUniqueVec +rust-eager-unique-vec-spec primrose_library::SortedVecSet *ENDLIBSPEC-NAME*/ use crate::traits::{Container, Indexable}; @@ -8,19 +8,19 @@ use std::vec::Vec; /// A Unique Vector #[derive(Debug, Clone)] -pub struct SortedUniqueVec<T> { +pub struct SortedVecSet<T> { v: Vec<T>, } -impl<T: PartialEq + std::cmp::Ord> SortedUniqueVec<T> { - pub fn from_vec(mut v: Vec<T>) -> SortedUniqueVec<T> { +impl<T: PartialEq + std::cmp::Ord> SortedVecSet<T> { + pub fn from_vec(mut v: Vec<T>) -> SortedVecSet<T> { v.sort(); v.dedup(); - SortedUniqueVec { v } + SortedVecSet { v } } - pub fn new() -> SortedUniqueVec<T> { - SortedUniqueVec { v: Vec::new() } + pub fn new() -> SortedVecSet<T> { + SortedVecSet { v: Vec::new() } } pub fn len(&self) -> usize { @@ -71,17 +71,17 @@ impl<T: PartialEq + std::cmp::Ord> SortedUniqueVec<T> { /*IMPL* Container *ENDIMPL*/ -impl<T: Ord + PartialEq> Container<T> for SortedUniqueVec<T> { +impl<T: Ord + PartialEq> Container<T> for SortedVecSet<T> { /*LIBSPEC* /*OPNAME* len op-len pre-len post-len *ENDOPNAME*/ (define (op-len xs) (cons xs (length xs))) - (define (pre-len xs) (equal? xs (remove-duplicates xs))) + (define (pre-len xs) (equal? xs (remove-duplicates (sort xs)))) (define (post-len xs r) (equal? r (op-len xs))) *ENDLIBSPEC*/ fn len(&self) -> usize { - SortedUniqueVec::len(self) + SortedVecSet::len(self) } /*LIBSPEC* @@ -92,11 +92,11 @@ impl<T: Ord + PartialEq> Container<T> for SortedUniqueVec<T> { (cond [(list? (member x xs)) (cons xs #t)] [else (cons xs #f)])) - (define (pre-contains xs) (equal? xs (remove-duplicates xs))) + (define (pre-contains xs) (equal? xs (remove-duplicates (sort xs)))) (define (post-contains xs x r) (equal? r (op-contains xs x))) *ENDLIBSPEC*/ fn contains(&self, x: &T) -> bool { - SortedUniqueVec::contains(self, x) // use fully qualified syntax to avoid function name collision + SortedVecSet::contains(self, x) // use fully qualified syntax to avoid function name collision } /*LIBSPEC* @@ -104,11 +104,11 @@ impl<T: Ord + PartialEq> Container<T> for SortedUniqueVec<T> { is-empty op-is-empty pre-is-empty post-is-empty *ENDOPNAME*/ (define (op-is-empty xs) (cons xs (null? xs))) - (define (pre-is-empty xs) (equal? xs (remove-duplicates xs))) + (define (pre-is-empty xs) (equal? xs (remove-duplicates (sort xs)))) (define (post-is-empty xs r) (equal? r (op-is-empty xs))) *ENDLIBSPEC*/ fn is_empty(&self) -> bool { - SortedUniqueVec::is_empty(self) + SortedVecSet::is_empty(self) } /*LIBSPEC* @@ -116,11 +116,11 @@ impl<T: Ord + PartialEq> Container<T> for SortedUniqueVec<T> { clear op-clear pre-clear post-clear *ENDOPNAME*/ (define (op-clear xs) null) - (define (pre-clear xs) (equal? xs (remove-duplicates xs))) + (define (pre-clear xs) (equal? xs (remove-duplicates (sort xs)))) (define (post-clear xs r) (equal? r (op-clear xs))) *ENDLIBSPEC*/ fn clear(&mut self) { - SortedUniqueVec::clear(self); + SortedVecSet::clear(self); } /*LIBSPEC* @@ -128,11 +128,11 @@ impl<T: Ord + PartialEq> Container<T> for SortedUniqueVec<T> { insert op-insert pre-insert post-insert *ENDOPNAME*/ (define (op-insert xs x) (remove-duplicates (append xs (list x)))) - (define (pre-insert xs) (equal? xs (remove-duplicates xs))) + (define (pre-insert xs) (equal? xs (remove-duplicates (sort xs)))) (define (post-insert xs x ys) (equal? ys (op-insert xs x))) *ENDLIBSPEC*/ fn insert(&mut self, elt: T) { - SortedUniqueVec::push(self, elt); + SortedVecSet::push(self, elt); } /*LIBSPEC* @@ -143,7 +143,7 @@ impl<T: Ord + PartialEq> Container<T> for SortedUniqueVec<T> { (cond [(list? (member x xs)) (cons (remove x xs) x)] [else (cons xs null)])) - (define (pre-remove xs) (equal? xs (remove-duplicates xs))) + (define (pre-remove xs) (equal? xs (remove-duplicates (sort xs)))) (define (post-remove xs r) (equal? r (op-remove xs))) *ENDLIBSPEC*/ fn remove(&mut self, elt: T) -> Option<T> { @@ -161,7 +161,7 @@ impl<T: Ord + PartialEq> Container<T> for SortedUniqueVec<T> { /*IMPL* Indexable *ENDIMPL*/ -impl<T: PartialEq + Ord> Indexable<T> for SortedUniqueVec<T> { +impl<T: PartialEq + Ord> Indexable<T> for SortedVecSet<T> { /*LIBSPEC* /*OPNAME* first op-first pre-first post-first @@ -174,7 +174,7 @@ impl<T: PartialEq + Ord> Indexable<T> for SortedUniqueVec<T> { (define (post-first xs r) (equal? r (op-first xs))) *ENDLIBSPEC*/ fn first(&self) -> Option<&T> { - SortedUniqueVec::first(self) + SortedVecSet::first(self) } /*LIBSPEC* @@ -189,7 +189,7 @@ impl<T: PartialEq + Ord> Indexable<T> for SortedUniqueVec<T> { (define (post-last xs r) (equal? r (op-last xs))) *ENDLIBSPEC*/ fn last(&self) -> Option<&T> { - SortedUniqueVec::last(self) + SortedVecSet::last(self) } /*LIBSPEC* @@ -209,13 +209,13 @@ impl<T: PartialEq + Ord> Indexable<T> for SortedUniqueVec<T> { } } -impl<T: Ord> Default for SortedUniqueVec<T> { +impl<T: Ord> Default for SortedVecSet<T> { fn default() -> Self { Self::new() } } -impl<T> IntoIterator for SortedUniqueVec<T> { +impl<T> IntoIterator for SortedVecSet<T> { type Item = T; type IntoIter = std::vec::IntoIter<T>; @@ -224,7 +224,7 @@ impl<T> IntoIterator for SortedUniqueVec<T> { } } -impl<E: Ord> FromIterator<E> for SortedUniqueVec<E> { +impl<E: Ord> FromIterator<E> for SortedVecSet<E> { fn from_iter<T: IntoIterator<Item = E>>(iter: T) -> Self { let mut v = Vec::from_iter(iter); v.sort(); @@ -236,11 +236,11 @@ impl<E: Ord> FromIterator<E> for SortedUniqueVec<E> { #[cfg(test)] mod tests { use super::*; - use crate::proptest::{strategies::sorted_unique_vec, *}; + use crate::proptest::{strategies::sorted_vec_set, *}; use im::conslist::ConsList; use proptest::prelude::*; - fn abstraction<T>(v: SortedUniqueVec<T>) -> ConsList<T> + fn abstraction<T>(v: SortedVecSet<T>) -> ConsList<T> where T: PartialEq + Ord, { @@ -254,7 +254,7 @@ mod tests { })] #[test] - fn test_sorted_unique_vec_len(ref mut v in sorted_unique_vec(".*", 0..100)) { + fn test_sorted_vec_set_len(ref mut v in sorted_vec_set(".*", 0..100)) { let abs_list = abstraction(v.clone()); //pre assert_eq!(abs_list, unique(&abs_list)); @@ -264,7 +264,7 @@ mod tests { } #[test] - fn test_sorted_unique_vec_contains(ref mut v in sorted_unique_vec(".*", 0..100), a in ".*") { + fn test_sorted_vec_set_contains(ref mut v in sorted_vec_set(".*", 0..100), a in ".*") { let abs_list = abstraction(v.clone()); //pre assert_eq!(abs_list, unique(&abs_list)); @@ -274,7 +274,7 @@ mod tests { } #[test] - fn test_sorted_unique_vec_is_empty(ref mut v in sorted_unique_vec(".*", 0..100)) { + fn test_sorted_vec_set_is_empty(ref mut v in sorted_vec_set(".*", 0..100)) { let abs_list = abstraction(v.clone()); //pre assert_eq!(abs_list, unique(&abs_list)); @@ -284,7 +284,7 @@ mod tests { } #[test] - fn test_sorted_unique_vec_insert(ref mut v in sorted_unique_vec(0_usize..100, 0..100), a in 0_usize..100) { + fn test_sorted_vec_set_insert(ref mut v in sorted_vec_set(0_usize..100, 0..100), a in 0_usize..100) { let abs_list = abstraction(v.clone()); //pre assert_eq!(abs_list, unique(&abs_list).sort()); @@ -295,7 +295,7 @@ mod tests { } #[test] - fn test_sorted_unique_vec_clear(ref mut v in sorted_unique_vec(".*", 0..100)) { + fn test_sorted_vec_set_clear(ref mut v in sorted_vec_set(".*", 0..100)) { let abs_list = abstraction(v.clone()); //pre assert_eq!(abs_list, unique(&abs_list)); @@ -306,7 +306,7 @@ mod tests { } #[test] - fn test_sorted_unique_vec_remove(ref mut v in sorted_unique_vec(".*", 0..100), a in ".*") { + fn test_sorted_vec_set_remove(ref mut v in sorted_vec_set(".*", 0..100), a in ".*") { let abs_list = abstraction(v.clone()); //pre assert_eq!(abs_list, unique(&abs_list)); @@ -318,7 +318,7 @@ mod tests { } #[test] - fn test_sorted_unique_vec_first(ref mut v in sorted_unique_vec(".*", 0..100)) { + fn test_sorted_vec_set_first(ref mut v in sorted_vec_set(".*", 0..100)) { let abs_list = abstraction(v.clone()); //pre assert_eq!(abs_list, unique(&abs_list)); @@ -330,7 +330,7 @@ mod tests { } #[test] - fn test_sorted_unique_vec_last(ref mut v in sorted_unique_vec(".*", 0..100)) { + fn test_sorted_vec_set_last(ref mut v in sorted_vec_set(".*", 0..100)) { let abs_list = abstraction(v.clone()); //pre assert_eq!(abs_list, unique(&abs_list)); @@ -342,7 +342,7 @@ mod tests { } #[test] - fn test_sorted_unique_vec_nth(ref mut v in sorted_unique_vec(".*", 0..100), n in 0usize..100) { + fn test_sorted_vec_set_nth(ref mut v in sorted_vec_set(".*", 0..100), n in 0usize..100) { let abs_list = abstraction(v.clone()); //pre assert_eq!(abs_list, unique(&abs_list)); diff --git a/src/crates/library/src/vecmap.rs b/src/crates/library/src/vecmap.rs new file mode 100644 index 0000000..700f78b --- /dev/null +++ b/src/crates/library/src/vecmap.rs @@ -0,0 +1,143 @@ +/*LIBSPEC-NAME* +rust-hashmap-spec primrose_library::VecMap +*ENDLIBSPEC-NAME*/ + +use crate::traits::Mapping; +use std::hash::Hash; + +#[derive(Clone)] +pub struct VecMap<K, V> { + v: Vec<(K, V)>, +} + +pub(crate) fn extract_key<K, V>((k, _): &(K, V)) -> &K { + k +} + +pub(crate) fn extract_value<K, V>((_, v): &(K, V)) -> &V { + v +} + +/*IMPL* +Mapping +*ENDIMPL*/ +impl<K: Ord + Hash, V> Mapping<K, V> for VecMap<K, V> { + /*LIBSPEC* + /*OPNAME* + len op-len pre-len post-len + *ENDOPNAME*/ + (define (pre-len xs) (is-map? xs)) + (define (op-len xs) (cons xs (length xs))) + (define (post-len xs r) (equal? r (op-len xs))) + *ENDLIBSPEC*/ + fn len(&self) -> usize { + self.v.len() + } + + /*LIBSPEC* + /*OPNAME* + contains op-contains pre-contains post-contains + *ENDOPNAME*/ + (define (pre-contains xs) (is-map? xs)) + (define (op-contains xs k) (assoc k xs)) + (define (post-contains xs k r) (equal? r (op-contains xs k))) + *ENDLIBSPEC*/ + fn contains(&mut self, key: &K) -> bool { + self.v.iter().any(|(k, _)| k == key) + } + + /*LIBSPEC* + /*OPNAME* + insert op-insert pre-insert post-insert + *ENDOPNAME*/ + (define (pre-insert xs) (is-map? xs)) + (define (op-insert xs k v) + (let ([idx (index-where xs (lambda (p) (equal? k (car p))))]) + (cond [idx (list-set xs idx (cons k v))] + [else (list* (cons k v) xs)]))) + (define (post-insert xs k v r) (equal? r (op-insert xs k v))) + *ENDLIBSPEC*/ + fn insert(&mut self, key: K, val: V) -> Option<V> { + let old = if let Some(idx) = self.v.iter().position(|(k, _)| *k == key) { + Some(self.v.remove(idx).1) + } else { + None + }; + self.v.push((key, val)); + old + } + + /*LIBSPEC* + /*OPNAME* + get op-get pre-get post-get + *ENDOPNAME*/ + (define (pre-get xs) (is-map? xs)) + (define (op-get xs k) (cdr (assoc k xs))) + (define (post-get xs k r) (equal? r (op-get xs k))) + *ENDLIBSPEC*/ + fn get(&self, key: &K) -> Option<&V> { + self.v.iter().find(|(k, _)| k == key).map(extract_value) + } + + /*LIBSPEC* + /*OPNAME* + remove op-remove pre-remove post-remove + *ENDOPNAME*/ + (define (pre-remove xs) (is-map? xs)) + (define (op-remove xs k) (cdr (assoc k xs))) + (define (post-remove xs k r) (equal? r (op-remove xs k))) + *ENDLIBSPEC*/ + fn remove(&mut self, key: &K) -> Option<V> { + Some(self.v.remove(self.v.iter().position(|(k, _)| k == key)?).1) + } + + /*LIBSPEC* + /*OPNAME* + clear op-clear pre-clear post-clear + *ENDOPNAME*/ + (define (pre-clear xs) (is-map? xs)) + (define (op-clear xs) null) + (define (post-clear xs r) (equal? r (op-clear xs))) + *ENDLIBSPEC*/ + fn clear(&mut self) { + self.v.clear() + } + + fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a K, &'a V)> + 'a + where + K: 'a, + V: 'a, + { + self.v.iter().map(|(k, v)| (k, v)) + } +} + +impl<K, V> Default for VecMap<K, V> { + fn default() -> Self { + Self { v: Vec::default() } + } +} + +impl<K: Ord, V> FromIterator<(K, V)> for VecMap<K, V> { + fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self { + let mut v: Vec<(K, V)> = iter.into_iter().collect(); + v.sort_by(|(k1, _), (k2, _)| k1.cmp(k2)); + v.dedup_by(|(k1, _), (k2, _)| k1 == k2); + Self { v } + } +} + +impl<K, V> IntoIterator for VecMap<K, V> { + type Item = (K, V); + + type IntoIter = std::vec::IntoIter<(K, V)>; + + fn into_iter(self) -> Self::IntoIter { + self.v.into_iter() + } +} + +#[cfg(test)] +mod tests { + // TODO +} diff --git a/src/crates/library/src/vecset.rs b/src/crates/library/src/vecset.rs new file mode 100644 index 0000000..ccf747a --- /dev/null +++ b/src/crates/library/src/vecset.rs @@ -0,0 +1,356 @@ +/*LIBSPEC-NAME* +rust-eager-unique-vec-spec primrose_library::VecSet +*ENDLIBSPEC-NAME*/ + +use crate::traits::{Container, Indexable}; + +use std::vec::Vec; + +/// A set represented by a Vector, where items aren't necessarily sorted. +#[derive(Debug, Clone)] +pub struct VecSet<T> { + v: Vec<T>, +} + +impl<T: PartialEq + std::cmp::Ord> VecSet<T> { + pub fn from_vec(mut v: Vec<T>) -> VecSet<T> { + v.sort(); + v.dedup(); + VecSet { v } + } + + pub fn new() -> VecSet<T> { + VecSet { v: Vec::new() } + } + + pub fn len(&self) -> usize { + self.v.len() + } + + pub fn contains(&self, x: &T) -> bool { + self.v.contains(x) + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + // Duplicated elements will be discarded + pub fn push(&mut self, value: T) { + if !self.contains(&value) { + self.v.push(value); + } + } + + pub fn pop(&mut self) -> Option<T> { + self.v.pop() + } + + pub fn remove(&mut self, index: usize) -> T { + self.v.swap_remove(index) + } + + pub fn clear(&mut self) { + self.v.clear() + } + + pub fn first(&self) -> Option<&T> { + self.v.first() + } + + pub fn last(&self) -> Option<&T> { + self.v.last() + } + + pub fn to_vec(self) -> Vec<T> { + self.v + } +} + +/*IMPL* +Container +*ENDIMPL*/ +impl<T: Ord + PartialEq> Container<T> for VecSet<T> { + /*LIBSPEC* + /*OPNAME* + len op-len pre-len post-len + *ENDOPNAME*/ + (define (op-len xs) (cons xs (length xs))) + (define (pre-len xs) (equal? xs (sort xs))) + (define (post-len xs r) (equal? r (op-len xs))) + *ENDLIBSPEC*/ + fn len(&self) -> usize { + VecSet::len(self) + } + + /*LIBSPEC* + /*OPNAME* + contains op-contains pre-contains post-contains + *ENDOPNAME*/ + (define (op-contains xs x) + (cond + [(list? (member x xs)) (cons xs #t)] + [else (cons xs #f)])) + (define (pre-contains xs) (equal? xs (sort xs))) + (define (post-contains xs x r) (equal? r (op-contains xs x))) + *ENDLIBSPEC*/ + fn contains(&self, x: &T) -> bool { + VecSet::contains(self, x) // use fully qualified syntax to avoid function name collision + } + + /*LIBSPEC* + /*OPNAME* + is-empty op-is-empty pre-is-empty post-is-empty + *ENDOPNAME*/ + (define (op-is-empty xs) (cons xs (null? xs))) + (define (pre-is-empty xs) (equal? xs (sort xs))) + (define (post-is-empty xs r) (equal? r (op-is-empty xs))) + *ENDLIBSPEC*/ + fn is_empty(&self) -> bool { + VecSet::is_empty(self) + } + + /*LIBSPEC* + /*OPNAME* + clear op-clear pre-clear post-clear + *ENDOPNAME*/ + (define (op-clear xs) null) + (define (pre-clear xs) (equal? xs (sort xs))) + (define (post-clear xs r) (equal? r (op-clear xs))) + *ENDLIBSPEC*/ + fn clear(&mut self) { + VecSet::clear(self); + } + + /*LIBSPEC* + /*OPNAME* + insert op-insert pre-insert post-insert + *ENDOPNAME*/ + (define (op-insert xs x) (sort (append xs (list x)))) + (define (pre-insert xs) (equal? xs (sort xs))) + (define (post-insert xs x ys) (equal? ys (op-insert xs x))) + *ENDLIBSPEC*/ + fn insert(&mut self, elt: T) { + VecSet::push(self, elt); + } + + /*LIBSPEC* + /*OPNAME* + remove op-remove pre-remove post-remove + *ENDOPNAME*/ + (define (op-remove xs x) + (cond + [(list? (member x xs)) (cons (remove x xs) x)] + [else (cons xs null)])) + (define (pre-remove xs) (equal? xs (sort xs))) + (define (post-remove xs r) (equal? r (op-remove xs))) + *ENDLIBSPEC*/ + fn remove(&mut self, elt: T) -> Option<T> { + let idx = self.iter().position(|x| *x == elt)?; + Some(self.v.remove(idx)) + } + + fn iter<'a>(&'a self) -> impl Iterator<Item = &'a T> + where + T: 'a, + { + self.v.iter() + } +} + +/*IMPL* +Indexable +*ENDIMPL*/ +impl<T: PartialEq + Ord> Indexable<T> for VecSet<T> { + /*LIBSPEC* + /*OPNAME* + first op-first pre-first post-first + *ENDOPNAME*/ + (define (op-first xs) + (cond + [(null? xs) (cons xs null)] + [else (cons xs (first xs))])) + (define (pre-first xs) #t) + (define (post-first xs r) (equal? r (op-first xs))) + *ENDLIBSPEC*/ + fn first(&self) -> Option<&T> { + VecSet::first(self) + } + + /*LIBSPEC* + /*OPNAME* + last op-last pre-last post-last + *ENDOPNAME*/ + (define (op-last xs) + (cond + [(null? xs) (cons xs null)] + [else (cons xs (last xs))])) + (define (pre-last xs) #t) + (define (post-last xs r) (equal? r (op-last xs))) + *ENDLIBSPEC*/ + fn last(&self) -> Option<&T> { + VecSet::last(self) + } + + /*LIBSPEC* + /*OPNAME* + nth op-nth pre-nth post-nth + *ENDOPNAME*/ + (define (op-nth xs n) + (cond + [(>= n (length xs)) (cons xs null)] + [(< n 0) (cons xs null)] + [else (cons xs (list-ref xs n))])) + (define (pre-nth xs) #t) + (define (post-nth xs n r) (equal? r (op-nth xs n))) + *ENDLIBSPEC*/ + fn nth(&self, n: usize) -> Option<&T> { + self.v.get(n) + } +} + +impl<T: Ord> Default for VecSet<T> { + fn default() -> Self { + Self::new() + } +} + +impl<T> IntoIterator for VecSet<T> { + type Item = T; + type IntoIter = std::vec::IntoIter<T>; + + fn into_iter(self) -> Self::IntoIter { + self.v.into_iter() + } +} + +impl<E: Ord> FromIterator<E> for VecSet<E> { + fn from_iter<T: IntoIterator<Item = E>>(iter: T) -> Self { + let mut v = Vec::from_iter(iter); + v.sort(); + v.dedup(); + Self { v } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::proptest::{strategies::vec_set, *}; + use im::conslist::ConsList; + use proptest::prelude::*; + + fn abstraction<T>(v: VecSet<T>) -> ConsList<T> + where + T: PartialEq + Ord, + { + let list: ConsList<T> = ConsList::from(v.to_vec()); + list + } + + proptest! { + #![proptest_config(ProptestConfig { + cases: 100, .. ProptestConfig::default() + })] + + #[test] + fn test_vec_set_len(ref mut v in vec_set(".*", 0..100)) { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, unique(&abs_list)); + //post + assert_eq!(Container::<String>::len(v), abs_list.len()); + assert_eq!(abstraction(v.clone()), abs_list); + } + + #[test] + fn test_vec_set_contains(ref mut v in vec_set(".*", 0..100), a in ".*") { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, unique(&abs_list)); + //post + assert_eq!(Container::<String>::contains(v, &a), contains(&abs_list, &a)); + assert_eq!(abstraction(v.clone()), abs_list); + } + + #[test] + fn test_vec_set_is_empty(ref mut v in vec_set(".*", 0..100)) { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, unique(&abs_list)); + //post + assert_eq!(Container::<String>::is_empty(v), abs_list.is_empty()); + assert_eq!(abstraction(v.clone()), abs_list); + } + + #[test] + fn test_vec_set_insert(ref mut v in vec_set(0_usize..100, 0..100), a in 0_usize..100) { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, unique(&abs_list)); + //post + let after_list = unique(&abs_list.append(conslist![a.clone()])); + Container::<usize>::insert(v, a.clone()); + assert_eq!(abstraction(v.clone()), after_list); + } + + #[test] + fn test_vec_set_clear(ref mut v in vec_set(".*", 0..100)) { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, unique(&abs_list)); + //post + let after_list = clear(&abs_list); + Container::<String>::clear(v); + assert_eq!(abstraction(v.clone()), after_list); + } + + #[test] + fn test_vec_set_remove(ref mut v in vec_set(".*", 0..100), a in ".*") { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, unique(&abs_list)); + //post + let (after_list, abs_elem) = remove(&abs_list, a.clone()); + let elem = Container::<String>::remove(v, a.clone()); + assert_eq!(abstraction(v.clone()), after_list); + assert_eq!(elem, abs_elem); + } + + #[test] + fn test_vec_set_first(ref mut v in vec_set(".*", 0..100)) { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, unique(&abs_list)); + //post + let elem = Indexable::<String>::first(v); + let abs_first = first(&abs_list); + assert_eq!(elem, abs_first); + assert_eq!(abstraction(v.clone()), abs_list); + } + + #[test] + fn test_vec_set_last(ref mut v in vec_set(".*", 0..100)) { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, unique(&abs_list)); + //post + let elem = Indexable::<String>::last(v); + let abs_last = last(&abs_list); + assert_eq!(elem, abs_last); + assert_eq!(abstraction(v.clone()), abs_list); + } + + #[test] + fn test_vec_set_nth(ref mut v in vec_set(".*", 0..100), n in 0usize..100) { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, unique(&abs_list)); + //post + let elem = Indexable::<String>::nth(v, n); + let abs_nth = nth(&abs_list, n); + assert_eq!(elem, abs_nth); + assert_eq!(abstraction(v.clone()), abs_list); + } + } +} |