From 443951f481148db0b06d545d6f22a06f59df2606 Mon Sep 17 00:00:00 2001 From: Aria Shrimpton Date: Tue, 19 Mar 2024 15:59:13 +0000 Subject: more library types & more consistent naming --- src/crates/library/src/adaptive.rs | 8 +- src/crates/library/src/lib.rs | 19 +- src/crates/library/src/proptest/strategies.rs | 18 +- src/crates/library/src/sorted_unique_vector.rs | 356 ------------------------- src/crates/library/src/sorted_vector.rs | 353 ------------------------ src/crates/library/src/sortedvec.rs | 353 ++++++++++++++++++++++++ src/crates/library/src/sortedvecmap.rs | 139 ++++++++++ src/crates/library/src/sortedvecset.rs | 356 +++++++++++++++++++++++++ src/crates/library/src/vecmap.rs | 143 ++++++++++ src/crates/library/src/vecset.rs | 356 +++++++++++++++++++++++++ 10 files changed, 1378 insertions(+), 723 deletions(-) delete mode 100644 src/crates/library/src/sorted_unique_vector.rs delete mode 100644 src/crates/library/src/sorted_vector.rs create mode 100644 src/crates/library/src/sortedvec.rs create mode 100644 src/crates/library/src/sortedvecmap.rs create mode 100644 src/crates/library/src/sortedvecset.rs create mode 100644 src/crates/library/src/vecmap.rs create mode 100644 src/crates/library/src/vecset.rs 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( +pub fn sorted_vec_set( element: T, size: Range, -) -> impl Strategy> +) -> impl Strategy> where ::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( @@ -25,3 +25,13 @@ where { vec(element, size.clone()).prop_map(SortedVec::from_vec) } + +pub fn vec_set( + element: T, + size: Range, +) -> impl Strategy> +where + ::Value: Ord, +{ + vec(element, size.clone()).prop_map(VecSet::from_vec) +} diff --git a/src/crates/library/src/sorted_unique_vector.rs b/src/crates/library/src/sorted_unique_vector.rs deleted file mode 100644 index b974693..0000000 --- a/src/crates/library/src/sorted_unique_vector.rs +++ /dev/null @@ -1,356 +0,0 @@ -/*LIBSPEC-NAME* -rust-eager-unique-vec-spec primrose_library::SortedUniqueVec -*ENDLIBSPEC-NAME*/ - -use crate::traits::{Container, Indexable}; - -use std::vec::Vec; - -/// A Unique Vector -#[derive(Debug, Clone)] -pub struct SortedUniqueVec { - v: Vec, -} - -impl SortedUniqueVec { - pub fn from_vec(mut v: Vec) -> SortedUniqueVec { - v.sort(); - v.dedup(); - SortedUniqueVec { v } - } - - pub fn new() -> SortedUniqueVec { - SortedUniqueVec { v: Vec::new() } - } - - pub fn len(&self) -> usize { - self.v.len() - } - - pub fn contains(&self, x: &T) -> bool { - self.v.binary_search(x).is_ok() - } - - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - // Duplicated elements will be discarded - pub fn push(&mut self, value: T) { - // Ok indicates already in list - if let Err(idx) = self.v.binary_search(&value) { - self.v.insert(idx, value); - } - } - - pub fn pop(&mut self) -> Option { - self.v.pop() - } - - pub fn remove(&mut self, index: usize) -> T { - self.v.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 { - self.v - } -} - -/*IMPL* -Container -*ENDIMPL*/ -impl Container for SortedUniqueVec { - /*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 (post-len xs r) (equal? r (op-len xs))) - *ENDLIBSPEC*/ - fn len(&self) -> usize { - SortedUniqueVec::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 (remove-duplicates 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 - } - - /*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 (remove-duplicates xs))) - (define (post-is-empty xs r) (equal? r (op-is-empty xs))) - *ENDLIBSPEC*/ - fn is_empty(&self) -> bool { - SortedUniqueVec::is_empty(self) - } - - /*LIBSPEC* - /*OPNAME* - clear op-clear pre-clear post-clear - *ENDOPNAME*/ - (define (op-clear xs) null) - (define (pre-clear xs) (equal? xs (remove-duplicates xs))) - (define (post-clear xs r) (equal? r (op-clear xs))) - *ENDLIBSPEC*/ - fn clear(&mut self) { - SortedUniqueVec::clear(self); - } - - /*LIBSPEC* - /*OPNAME* - 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 (post-insert xs x ys) (equal? ys (op-insert xs x))) - *ENDLIBSPEC*/ - fn insert(&mut self, elt: T) { - SortedUniqueVec::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 (remove-duplicates xs))) - (define (post-remove xs r) (equal? r (op-remove xs))) - *ENDLIBSPEC*/ - fn remove(&mut self, elt: T) -> Option { - Some(self.v.remove(self.v.binary_search(&elt).ok()?)) - } - - fn iter<'a>(&'a self) -> impl Iterator - where - T: 'a, - { - self.v.iter() - } -} - -/*IMPL* -Indexable -*ENDIMPL*/ -impl Indexable for SortedUniqueVec { - /*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> { - SortedUniqueVec::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> { - SortedUniqueVec::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 Default for SortedUniqueVec { - fn default() -> Self { - Self::new() - } -} - -impl IntoIterator for SortedUniqueVec { - type Item = T; - type IntoIter = std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.v.into_iter() - } -} - -impl FromIterator for SortedUniqueVec { - fn from_iter>(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::sorted_unique_vec, *}; - use im::conslist::ConsList; - use proptest::prelude::*; - - fn abstraction(v: SortedUniqueVec) -> ConsList - where - T: PartialEq + Ord, - { - let list: ConsList = ConsList::from(v.to_vec()); - list - } - - proptest! { - #![proptest_config(ProptestConfig { - cases: 100, .. ProptestConfig::default() - })] - - #[test] - fn test_sorted_unique_vec_len(ref mut v in sorted_unique_vec(".*", 0..100)) { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, unique(&abs_list)); - //post - assert_eq!(Container::::len(v), abs_list.len()); - assert_eq!(abstraction(v.clone()), abs_list); - } - - #[test] - fn test_sorted_unique_vec_contains(ref mut v in sorted_unique_vec(".*", 0..100), a in ".*") { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, unique(&abs_list)); - //post - assert_eq!(Container::::contains(v, &a), contains(&abs_list, &a)); - assert_eq!(abstraction(v.clone()), abs_list); - } - - #[test] - fn test_sorted_unique_vec_is_empty(ref mut v in sorted_unique_vec(".*", 0..100)) { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, unique(&abs_list)); - //post - assert_eq!(Container::::is_empty(v), abs_list.is_empty()); - assert_eq!(abstraction(v.clone()), abs_list); - } - - #[test] - fn test_sorted_unique_vec_insert(ref mut v in sorted_unique_vec(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()); - //post - let after_list = unique(&abs_list.append(conslist![a.clone()])).sort(); - Container::::insert(v, a.clone()); - assert_eq!(abstraction(v.clone()), after_list); - } - - #[test] - fn test_sorted_unique_vec_clear(ref mut v in sorted_unique_vec(".*", 0..100)) { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, unique(&abs_list)); - //post - let after_list = clear(&abs_list); - Container::::clear(v); - assert_eq!(abstraction(v.clone()), after_list); - } - - #[test] - fn test_sorted_unique_vec_remove(ref mut v in sorted_unique_vec(".*", 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::::remove(v, a.clone()); - assert_eq!(abstraction(v.clone()), after_list); - assert_eq!(elem, abs_elem); - } - - #[test] - fn test_sorted_unique_vec_first(ref mut v in sorted_unique_vec(".*", 0..100)) { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, unique(&abs_list)); - //post - let elem = Indexable::::first(v); - let abs_first = first(&abs_list); - assert_eq!(elem, abs_first); - assert_eq!(abstraction(v.clone()), abs_list); - } - - #[test] - fn test_sorted_unique_vec_last(ref mut v in sorted_unique_vec(".*", 0..100)) { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, unique(&abs_list)); - //post - let elem = Indexable::::last(v); - let abs_last = last(&abs_list); - assert_eq!(elem, abs_last); - assert_eq!(abstraction(v.clone()), abs_list); - } - - #[test] - fn test_sorted_unique_vec_nth(ref mut v in sorted_unique_vec(".*", 0..100), n in 0usize..100) { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, unique(&abs_list)); - //post - let elem = Indexable::::nth(v, n); - let abs_nth = nth(&abs_list, n); - assert_eq!(elem, abs_nth); - assert_eq!(abstraction(v.clone()), abs_list); - } - } -} diff --git a/src/crates/library/src/sorted_vector.rs b/src/crates/library/src/sorted_vector.rs deleted file mode 100644 index 925e3ef..0000000 --- a/src/crates/library/src/sorted_vector.rs +++ /dev/null @@ -1,353 +0,0 @@ -/*LIBSPEC-NAME* -rust-eager-sorted-vec-spec primrose_library::SortedVec -*ENDLIBSPEC-NAME*/ - -use crate::traits::{Container, Indexable}; - -use std::vec::Vec; - -/// A Sorted Vector -#[derive(Debug, Clone)] -pub struct SortedVec { - v: Vec, -} - -impl SortedVec { - pub fn from_vec(mut v: Vec) -> SortedVec { - v.sort(); - SortedVec { v } - } - - pub fn new() -> SortedVec { - SortedVec { v: Vec::new() } - } - - pub fn len(&self) -> usize { - self.v.len() - } - - pub fn contains(&self, x: &T) -> bool { - self.v.binary_search(x).is_ok() - } - - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - pub fn push(&mut self, value: T) { - let index = self.v.binary_search(&value).unwrap_or_else(|i| i); - self.v.insert(index, value); - } - - pub fn pop(&mut self) -> Option { - self.v.pop() - } - - pub fn remove(&mut self, index: usize) -> T { - self.v.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 { - self.v - } -} - -/*IMPL* -Container -*ENDIMPL*/ -impl Container for SortedVec { - /*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 { - SortedVec::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 { - SortedVec::contains(self, x) - } - - /*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 { - SortedVec::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) { - SortedVec::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) { - SortedVec::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 { - let idx = self.v.binary_search(&elt).ok()?; - Some(self.v.remove(idx)) - } - - fn iter<'a>(&'a self) -> impl Iterator - where - T: 'a, - { - self.v.iter() - } -} - -/*IMPL* -Indexable -*ENDIMPL*/ -impl Indexable for SortedVec { - /*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> { - SortedVec::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> { - SortedVec::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> { - SortedVec::iter(self).nth(n) - } -} - -impl Default for SortedVec { - fn default() -> Self { - Self::new() - } -} - -impl IntoIterator for SortedVec { - type Item = T; - type IntoIter = std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.v.into_iter() - } -} - -impl FromIterator for SortedVec { - fn from_iter>(iter: T) -> Self { - let mut v = Vec::from_iter(iter); - v.sort(); - Self { v } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::proptest::{strategies::sorted_vec, *}; - - use im::conslist::ConsList; - use proptest::prelude::*; - - fn abstraction(v: SortedVec) -> ConsList - where - T: Ord, - { - let list: ConsList = ConsList::from(v.to_vec()); - list - } - - proptest! { - #![proptest_config(ProptestConfig { - cases: 100, .. ProptestConfig::default() - })] - - #[test] - fn test_sorted_vec_len(ref mut v in sorted_vec(".*", 0..100)) { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, abs_list.sort()); - //post - assert_eq!(Container::::len(v), abs_list.len()); - assert_eq!(abstraction(v.clone()), abs_list); - } - - #[test] - fn test_sorted_vec_contains(ref mut v in sorted_vec(".*", 0..100), a in ".*") { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, abs_list.sort()); - //post - assert_eq!(Container::::contains(v, &a), contains(&abs_list, &a)); - assert_eq!(abstraction(v.clone()), abs_list); - } - - #[test] - fn test_sorted_vec_is_empty(ref mut v in sorted_vec(".*", 0..100)) { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, abs_list.sort()); - //post - assert_eq!(Container::::is_empty(v), abs_list.is_empty()); - assert_eq!(abstraction(v.clone()), abs_list); - } - - #[test] - fn test_sorted_vec_insert(ref mut v in sorted_vec(".*", 0..100), a in ".*") { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, abs_list.sort()); - //post - let after_list = abs_list.append(conslist![a.clone()]).sort(); - Container::::insert(v, a.clone()); - assert_eq!(abstraction(v.clone()), after_list); - } - - #[test] - fn test_sorted_vec_clear(ref mut v in sorted_vec(".*", 0..100)) { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, abs_list.sort()); - //post - let after_list = clear(&abs_list); - Container::::clear(v); - assert_eq!(abstraction(v.clone()), after_list); - } - - #[test] - fn test_sorted_vec_remove(ref mut v in sorted_vec(".*", 0..100), a in ".*") { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, abs_list.sort()); - //post - let (after_list, abs_elem) = remove(&abs_list, a.clone()); - let elem = Container::::remove(v, a.clone()); - assert_eq!(abstraction(v.clone()), after_list); - assert_eq!(elem, abs_elem); - } - - #[test] - fn test_sorted_vec_first(ref mut v in sorted_vec(".*", 0..100)) { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, abs_list.sort()); - //post - let elem = Indexable::::first(v); - let abs_first = first(&abs_list); - assert_eq!(elem, abs_first); - assert_eq!(abstraction(v.clone()), abs_list); - } - - #[test] - fn test_sorted_vec_last(ref mut v in sorted_vec(".*", 0..100)) { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, abs_list.sort()); - //post - let elem = Indexable::::last(v); - let abs_last = last(&abs_list); - assert_eq!(elem, abs_last); - assert_eq!(abstraction(v.clone()), abs_list); - } - - #[test] - fn test_sorted_vec_nth(ref mut v in sorted_vec(".*", 0..100), n in 0usize..100) { - let abs_list = abstraction(v.clone()); - //pre - assert_eq!(abs_list, abs_list.sort()); - //post - let elem = Indexable::::nth(v, n); - let abs_nth = nth(&abs_list, n); - assert_eq!(elem, abs_nth); - assert_eq!(abstraction(v.clone()), abs_list); - } - } -} diff --git a/src/crates/library/src/sortedvec.rs b/src/crates/library/src/sortedvec.rs new file mode 100644 index 0000000..925e3ef --- /dev/null +++ b/src/crates/library/src/sortedvec.rs @@ -0,0 +1,353 @@ +/*LIBSPEC-NAME* +rust-eager-sorted-vec-spec primrose_library::SortedVec +*ENDLIBSPEC-NAME*/ + +use crate::traits::{Container, Indexable}; + +use std::vec::Vec; + +/// A Sorted Vector +#[derive(Debug, Clone)] +pub struct SortedVec { + v: Vec, +} + +impl SortedVec { + pub fn from_vec(mut v: Vec) -> SortedVec { + v.sort(); + SortedVec { v } + } + + pub fn new() -> SortedVec { + SortedVec { v: Vec::new() } + } + + pub fn len(&self) -> usize { + self.v.len() + } + + pub fn contains(&self, x: &T) -> bool { + self.v.binary_search(x).is_ok() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + pub fn push(&mut self, value: T) { + let index = self.v.binary_search(&value).unwrap_or_else(|i| i); + self.v.insert(index, value); + } + + pub fn pop(&mut self) -> Option { + self.v.pop() + } + + pub fn remove(&mut self, index: usize) -> T { + self.v.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 { + self.v + } +} + +/*IMPL* +Container +*ENDIMPL*/ +impl Container for SortedVec { + /*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 { + SortedVec::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 { + SortedVec::contains(self, x) + } + + /*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 { + SortedVec::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) { + SortedVec::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) { + SortedVec::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 { + let idx = self.v.binary_search(&elt).ok()?; + Some(self.v.remove(idx)) + } + + fn iter<'a>(&'a self) -> impl Iterator + where + T: 'a, + { + self.v.iter() + } +} + +/*IMPL* +Indexable +*ENDIMPL*/ +impl Indexable for SortedVec { + /*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> { + SortedVec::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> { + SortedVec::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> { + SortedVec::iter(self).nth(n) + } +} + +impl Default for SortedVec { + fn default() -> Self { + Self::new() + } +} + +impl IntoIterator for SortedVec { + type Item = T; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.v.into_iter() + } +} + +impl FromIterator for SortedVec { + fn from_iter>(iter: T) -> Self { + let mut v = Vec::from_iter(iter); + v.sort(); + Self { v } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::proptest::{strategies::sorted_vec, *}; + + use im::conslist::ConsList; + use proptest::prelude::*; + + fn abstraction(v: SortedVec) -> ConsList + where + T: Ord, + { + let list: ConsList = ConsList::from(v.to_vec()); + list + } + + proptest! { + #![proptest_config(ProptestConfig { + cases: 100, .. ProptestConfig::default() + })] + + #[test] + fn test_sorted_vec_len(ref mut v in sorted_vec(".*", 0..100)) { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, abs_list.sort()); + //post + assert_eq!(Container::::len(v), abs_list.len()); + assert_eq!(abstraction(v.clone()), abs_list); + } + + #[test] + fn test_sorted_vec_contains(ref mut v in sorted_vec(".*", 0..100), a in ".*") { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, abs_list.sort()); + //post + assert_eq!(Container::::contains(v, &a), contains(&abs_list, &a)); + assert_eq!(abstraction(v.clone()), abs_list); + } + + #[test] + fn test_sorted_vec_is_empty(ref mut v in sorted_vec(".*", 0..100)) { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, abs_list.sort()); + //post + assert_eq!(Container::::is_empty(v), abs_list.is_empty()); + assert_eq!(abstraction(v.clone()), abs_list); + } + + #[test] + fn test_sorted_vec_insert(ref mut v in sorted_vec(".*", 0..100), a in ".*") { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, abs_list.sort()); + //post + let after_list = abs_list.append(conslist![a.clone()]).sort(); + Container::::insert(v, a.clone()); + assert_eq!(abstraction(v.clone()), after_list); + } + + #[test] + fn test_sorted_vec_clear(ref mut v in sorted_vec(".*", 0..100)) { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, abs_list.sort()); + //post + let after_list = clear(&abs_list); + Container::::clear(v); + assert_eq!(abstraction(v.clone()), after_list); + } + + #[test] + fn test_sorted_vec_remove(ref mut v in sorted_vec(".*", 0..100), a in ".*") { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, abs_list.sort()); + //post + let (after_list, abs_elem) = remove(&abs_list, a.clone()); + let elem = Container::::remove(v, a.clone()); + assert_eq!(abstraction(v.clone()), after_list); + assert_eq!(elem, abs_elem); + } + + #[test] + fn test_sorted_vec_first(ref mut v in sorted_vec(".*", 0..100)) { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, abs_list.sort()); + //post + let elem = Indexable::::first(v); + let abs_first = first(&abs_list); + assert_eq!(elem, abs_first); + assert_eq!(abstraction(v.clone()), abs_list); + } + + #[test] + fn test_sorted_vec_last(ref mut v in sorted_vec(".*", 0..100)) { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, abs_list.sort()); + //post + let elem = Indexable::::last(v); + let abs_last = last(&abs_list); + assert_eq!(elem, abs_last); + assert_eq!(abstraction(v.clone()), abs_list); + } + + #[test] + fn test_sorted_vec_nth(ref mut v in sorted_vec(".*", 0..100), n in 0usize..100) { + let abs_list = abstraction(v.clone()); + //pre + assert_eq!(abs_list, abs_list.sort()); + //post + let elem = Indexable::::nth(v, n); + let abs_nth = nth(&abs_list, n); + assert_eq!(elem, abs_nth); + assert_eq!(abstraction(v.clone()), abs_list); + } + } +} 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 { + v: Vec<(K, V)>, +} + +/*IMPL* +Mapping +*ENDIMPL*/ +impl Mapping for SortedVecMap { + /*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 { + 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 { + 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 + 'a + where + K: 'a, + V: 'a, + { + self.v.iter().map(|(k, v)| (k, v)) + } +} + +impl Default for SortedVecMap { + fn default() -> Self { + Self { v: Vec::default() } + } +} + +impl FromIterator<(K, V)> for SortedVecMap { + fn from_iter>(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 IntoIterator for SortedVecMap { + 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/sortedvecset.rs b/src/crates/library/src/sortedvecset.rs new file mode 100644 index 0000000..0016374 --- /dev/null +++ b/src/crates/library/src/sortedvecset.rs @@ -0,0 +1,356 @@ +/*LIBSPEC-NAME* +rust-eager-unique-vec-spec primrose_library::SortedVecSet +*ENDLIBSPEC-NAME*/ + +use crate::traits::{Container, Indexable}; + +use std::vec::Vec; + +/// A Unique Vector +#[derive(Debug, Clone)] +pub struct SortedVecSet { + v: Vec, +} + +impl SortedVecSet { + pub fn from_vec(mut v: Vec) -> SortedVecSet { + v.sort(); + v.dedup(); + SortedVecSet { v } + } + + pub fn new() -> SortedVecSet { + SortedVecSet { v: Vec::new() } + } + + pub fn len(&self) -> usize { + self.v.len() + } + + pub fn contains(&self, x: &T) -> bool { + self.v.binary_search(x).is_ok() + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + // Duplicated elements will be discarded + pub fn push(&mut self, value: T) { + // Ok indicates already in list + if let Err(idx) = self.v.binary_search(&value) { + self.v.insert(idx, value); + } + } + + pub fn pop(&mut self) -> Option { + self.v.pop() + } + + pub fn remove(&mut self, index: usize) -> T { + self.v.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 { + self.v + } +} + +/*IMPL* +Container +*ENDIMPL*/ +impl Container for SortedVecSet { + /*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 (sort xs)))) + (define (post-len xs r) (equal? r (op-len xs))) + *ENDLIBSPEC*/ + fn len(&self) -> usize { + SortedVecSet::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 (remove-duplicates (sort xs)))) + (define (post-contains xs x r) (equal? r (op-contains xs x))) + *ENDLIBSPEC*/ + fn contains(&self, x: &T) -> bool { + SortedVecSet::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 (remove-duplicates (sort xs)))) + (define (post-is-empty xs r) (equal? r (op-is-empty xs))) + *ENDLIBSPEC*/ + fn is_empty(&self) -> bool { + SortedVecSet::is_empty(self) + } + + /*LIBSPEC* + /*OPNAME* + clear op-clear pre-clear post-clear + *ENDOPNAME*/ + (define (op-clear xs) null) + (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) { + SortedVecSet::clear(self); + } + + /*LIBSPEC* + /*OPNAME* + 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 (sort xs)))) + (define (post-insert xs x ys) (equal? ys (op-insert xs x))) + *ENDLIBSPEC*/ + fn insert(&mut self, elt: T) { + SortedVecSet::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 (remove-duplicates (sort xs)))) + (define (post-remove xs r) (equal? r (op-remove xs))) + *ENDLIBSPEC*/ + fn remove(&mut self, elt: T) -> Option { + Some(self.v.remove(self.v.binary_search(&elt).ok()?)) + } + + fn iter<'a>(&'a self) -> impl Iterator + where + T: 'a, + { + self.v.iter() + } +} + +/*IMPL* +Indexable +*ENDIMPL*/ +impl Indexable for SortedVecSet { + /*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> { + SortedVecSet::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> { + SortedVecSet::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 Default for SortedVecSet { + fn default() -> Self { + Self::new() + } +} + +impl IntoIterator for SortedVecSet { + type Item = T; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.v.into_iter() + } +} + +impl FromIterator for SortedVecSet { + fn from_iter>(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::sorted_vec_set, *}; + use im::conslist::ConsList; + use proptest::prelude::*; + + fn abstraction(v: SortedVecSet) -> ConsList + where + T: PartialEq + Ord, + { + let list: ConsList = ConsList::from(v.to_vec()); + list + } + + proptest! { + #![proptest_config(ProptestConfig { + cases: 100, .. ProptestConfig::default() + })] + + #[test] + 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)); + //post + assert_eq!(Container::::len(v), abs_list.len()); + assert_eq!(abstraction(v.clone()), abs_list); + } + + #[test] + 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)); + //post + assert_eq!(Container::::contains(v, &a), contains(&abs_list, &a)); + assert_eq!(abstraction(v.clone()), abs_list); + } + + #[test] + 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)); + //post + assert_eq!(Container::::is_empty(v), abs_list.is_empty()); + assert_eq!(abstraction(v.clone()), abs_list); + } + + #[test] + 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()); + //post + let after_list = unique(&abs_list.append(conslist![a.clone()])).sort(); + Container::::insert(v, a.clone()); + assert_eq!(abstraction(v.clone()), after_list); + } + + #[test] + 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)); + //post + let after_list = clear(&abs_list); + Container::::clear(v); + assert_eq!(abstraction(v.clone()), after_list); + } + + #[test] + 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)); + //post + let (after_list, abs_elem) = remove(&abs_list, a.clone()); + let elem = Container::::remove(v, a.clone()); + assert_eq!(abstraction(v.clone()), after_list); + assert_eq!(elem, abs_elem); + } + + #[test] + 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)); + //post + let elem = Indexable::::first(v); + let abs_first = first(&abs_list); + assert_eq!(elem, abs_first); + assert_eq!(abstraction(v.clone()), abs_list); + } + + #[test] + 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)); + //post + let elem = Indexable::::last(v); + let abs_last = last(&abs_list); + assert_eq!(elem, abs_last); + assert_eq!(abstraction(v.clone()), abs_list); + } + + #[test] + 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)); + //post + let elem = Indexable::::nth(v, n); + let abs_nth = nth(&abs_list, n); + assert_eq!(elem, abs_nth); + assert_eq!(abstraction(v.clone()), 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 { + v: Vec<(K, V)>, +} + +pub(crate) fn extract_key((k, _): &(K, V)) -> &K { + k +} + +pub(crate) fn extract_value((_, v): &(K, V)) -> &V { + v +} + +/*IMPL* +Mapping +*ENDIMPL*/ +impl Mapping for VecMap { + /*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 { + 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 { + 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 + 'a + where + K: 'a, + V: 'a, + { + self.v.iter().map(|(k, v)| (k, v)) + } +} + +impl Default for VecMap { + fn default() -> Self { + Self { v: Vec::default() } + } +} + +impl FromIterator<(K, V)> for VecMap { + fn from_iter>(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 IntoIterator for VecMap { + 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 { + v: Vec, +} + +impl VecSet { + pub fn from_vec(mut v: Vec) -> VecSet { + v.sort(); + v.dedup(); + VecSet { v } + } + + pub fn new() -> VecSet { + 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 { + 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 { + self.v + } +} + +/*IMPL* +Container +*ENDIMPL*/ +impl Container for VecSet { + /*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 { + let idx = self.iter().position(|x| *x == elt)?; + Some(self.v.remove(idx)) + } + + fn iter<'a>(&'a self) -> impl Iterator + where + T: 'a, + { + self.v.iter() + } +} + +/*IMPL* +Indexable +*ENDIMPL*/ +impl Indexable for VecSet { + /*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 Default for VecSet { + fn default() -> Self { + Self::new() + } +} + +impl IntoIterator for VecSet { + type Item = T; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.v.into_iter() + } +} + +impl FromIterator for VecSet { + fn from_iter>(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(v: VecSet) -> ConsList + where + T: PartialEq + Ord, + { + let list: ConsList = 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::::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::::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::::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::::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::::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::::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::::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::::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::::nth(v, n); + let abs_nth = nth(&abs_list, n); + assert_eq!(elem, abs_nth); + assert_eq!(abstraction(v.clone()), abs_list); + } + } +} -- cgit v1.2.3