diff --git a/Cargo.toml b/Cargo.toml index 05446bb548..272ea8c8a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,24 +2,30 @@ members = [ "lib/rust/ast", - "lib/rust/enso-data", - "lib/rust/enso-generics", - "lib/rust/enso-logger", - "lib/rust/enso-macro-utils", - "lib/rust/enso-optics", - "lib/rust/enso-prelude", - "lib/rust/enso-shapely/impl", - "lib/rust/enso-shapely/macros", "lib/rust/flexer", "lib/rust/flexer-testing/definition", "lib/rust/flexer-testing/generation", "lib/rust/launcher-shims", - "lib/rust/lazy-reader", "lib/rust/lexer/definition", "lib/rust/lexer/generation", "lib/rust/parser", ] +# These patch versions exist to allow local development of these libraries alongside Enso. It +# assumes you have `rust-lib` in the same directory as `enso`. See: +# https://github.com/enso-org/rust-lib/blob/main/docs/CONTRIBUTING.md#developing-in-conjunction-with-enso--ide +[patch.crates-io] +# enso-automata = { path = '../rust-lib/src/automata' } +# enso-data = { path = '../rust-lib/src/data' } +# enso-generics = { path = '../rust-lib/src/generics' } +# enso-lazy-reader = { path = '../rust-lib/src/lazy-reader' } +# enso-logger = { path = '../rust-lib/src/logger' } +# enso-macro-utils = { path = '../rust-lib/src/macro-utils' } +# enso-optics = { path = '../rust-lib/src/optics' } +# enso-prelude = { path = '../rust-lib/src/prelude' } +# enso-shapely = { path = '../rust-lib/src/shapely/impl' } +# enso-shapely-macros = { path = '../rust-lib/src/shapely/macros' } + [profile.dev] opt-level = 0 lto = false diff --git a/lib/rust/enso-data/Cargo.toml b/lib/rust/enso-data/Cargo.toml deleted file mode 100644 index 42c07248cc..0000000000 --- a/lib/rust/enso-data/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "enso-data" -version = "0.1.0" -authors = ["Enso Team "] -edition = "2018" - -description = "Useful data-types." -readme = "README.md" -homepage = "https://github.com/enso-org/enso/lib/rust/enso-data" -repository = "https://github.com/enso-org/enso" -license-file = "../../../LICENSE" - -[lib] -crate-type = ["cdylib", "rlib"] - -[dependencies] -enso-prelude = { version = "0.1.0" , path = "../enso-prelude" } - -serde = { version = "1.0" , features = ["derive"] } diff --git a/lib/rust/enso-data/README.md b/lib/rust/enso-data/README.md deleted file mode 100644 index 9412e43506..0000000000 --- a/lib/rust/enso-data/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Enso Data - -Useful data types. diff --git a/lib/rust/enso-data/src/hash_map_tree.rs b/lib/rust/enso-data/src/hash_map_tree.rs deleted file mode 100644 index 4bcb1fab7b..0000000000 --- a/lib/rust/enso-data/src/hash_map_tree.rs +++ /dev/null @@ -1,331 +0,0 @@ -//! A tree structure build on top of the `HashMap`. - -use crate::prelude::*; - -use std::collections::hash_map::RandomState; -use std::hash::BuildHasher; - - - -// =================== -// === HashMapTree === -// =================== - -/// A tree build on top of the `HashMap`. Each node in the tree can have zero or more branches -/// accessible by the given key type. -#[derive(Derivative)] -#[derivative(Debug (bound="K:Eq+Hash+Debug , V:Debug , S:BuildHasher"))] -#[derivative(Default (bound="K:Eq+Hash , V:Default , S:BuildHasher+Default"))] -#[derivative(Clone (bound="K:Clone , V:Clone , S:Clone"))] -pub struct HashMapTree { - /// Value of the current tree node. - pub value : V, - /// Branches of the current tree node. - pub branches : HashMap,S> -} - -impl HashMapTree -where K : Eq+Hash, - S : BuildHasher+Default { - /// Constructor. - pub fn new() -> Self where T:Default { - default() - } - - /// Constructor with explicit root value. - pub fn from_value(value:T) -> Self { - let branches = default(); - Self {value,branches} - } - - /// Sets the value at position described by `path`. In case a required sub-branch does not - /// exist, a default instance will be created. - #[inline] - pub fn set(&mut self, path:P, value:T) - where P:IntoIterator, T:Default, I:Into { - self.get_or_create_node(path).value = value; - } - - /// Sets the value at position described by `path`. In case a required sub-branch does not - /// exist, uses `cons_missing` to create it. - #[inline] - pub fn set_with(&mut self, path:P, value:T, cons_missing:F) - where P:IntoIterator, T:Default, I:Into, F:FnMut()->T { - self.get_or_create_node_with(path,cons_missing).value = value; - } - - /// Gets a reference to a value at the specified path if the path exists in the tree. - #[inline] - pub fn get(&self, segments:P) -> Option<&T> - where P:IntoIterator, I:Into { - self.get_node(segments).map(|node| &node.value) - } - - /// Gets a mutable reference to a value at the specified path if the path exists in the tree. - #[inline] - pub fn get_mut(&mut self, segments:P) -> Option<&mut T> - where P:IntoIterator, I:Into { - self.get_node_mut(segments).map(|node| &mut node.value) - } - - /// Gets a reference to a node at the specified path if the node exists. - #[inline] - pub fn get_node(&self, segments:P) -> Option<&HashMapTree> - where P:IntoIterator, I:Into { - segments.into_iter().fold(Some(self),|map,t| { - map.and_then(|m| { - let key = t.into(); - m.branches.get(&key) - }) - }) - } - - /// Gets a mutable reference to a node at the specified path if the node exists. - #[inline] - pub fn get_node_mut(&mut self, segments:P) -> Option<&mut HashMapTree> - where P:IntoIterator, I:Into { - segments.into_iter().fold(Some(self),|map,t| { - map.and_then(|m| { - let key = t.into(); - m.branches.get_mut(&key) - }) - }) - } - - /// Removes the node at the specified path. - #[inline] - pub fn remove(&mut self, segments:P) -> Option - where P:IntoIterator, I:Into { - let mut segments = segments.into_iter().map(|t|t.into()).collect_vec(); - segments.pop().and_then(|last| { - self.get_node_mut(segments).and_then(|node| { - node.branches.remove(&last).map(|branch| branch.value) - }) - }) - } - - /// Iterates over keys in `path`. For each key, traverses into the appropriate branch. In case - /// the branch does not exist, a default instance will be created. Returns mutable reference to - /// the target tree node. - #[inline] - pub fn get_or_create_node(&mut self, path:P) -> &mut HashMapTree - where P:IntoIterator, T:Default, I:Into { - self.get_or_create_node_with(path,default) - } - - /// Iterates over keys in `path`. For each key, traverses into the appropriate branch. In case - /// the branch does not exist, uses `cons_missing` to construct it. Returns mutable reference to - /// the target tree node. - #[inline] - pub fn get_or_create_node_with - (&mut self, path:P, cons_missing:F) -> &mut HashMapTree - where P:IntoIterator, I:Into, F:FnMut()->T { - self.get_or_create_node_traversing_with(path,cons_missing,|_|{}) - } - - /// Iterates over keys in `path`. For each key, traverses into the appropriate branch. In case - /// the branch does not exist, uses `cons_missing` provided with the current path to construct - /// it. Returns mutable reference to the target tree node. - #[inline] - pub fn get_or_create_node_path_with - (&mut self, path:P, cons_missing:F) -> &mut HashMapTree - where K:Clone, P:IntoIterator, I:Into, F:FnMut(&[K])->T { - self.get_or_create_node_traversing_path_with(path,cons_missing,|_|{}) - } - - /// Iterates over keys in `path`. For each key, traverses into the appropriate branch. In case - /// the branch does not exist, uses `cons_missing` to construct it. Moreover, for each traversed - /// branch the `callback` is evaluated. Returns mutable reference to the target tree node. - #[inline] - pub fn get_or_create_node_traversing_with - (&mut self, segments:P, mut cons_missing:F, mut callback:M) -> &mut HashMapTree - where P:IntoIterator, I:Into, F:FnMut()->T, M:FnMut(&mut HashMapTree) { - segments.into_iter().fold(self,|map,t| { - let key = t.into(); - let entry = map.branches.entry(key); - let node = entry.or_insert_with(|| HashMapTree::from_value(cons_missing())); - callback(node); - node - }) - } - - /// Iterates over keys in `path`. For each key, traverses into the appropriate branch. In case - /// the branch does not exist, uses `cons_missing` provided with the current path to construct - /// it. Moreover, for each traversed branch the `callback` is evaluated. Returns mutable - /// reference to the target tree node. - #[inline] - pub fn get_or_create_node_traversing_path_with - (&mut self, segments:P, mut cons_missing:F, mut callback:M) -> &mut HashMapTree - where K : Clone, - P : IntoIterator, - I : Into, - F : FnMut(&[K])->T, - M : FnMut(&mut HashMapTree) { - let mut path = Vec::new(); - segments.into_iter().fold(self,|map,t| { - let key = t.into(); - path.push(key.clone()); - let entry = map.branches.entry(key); - let node = entry.or_insert_with(|| HashMapTree::from_value(cons_missing(&path))); - callback(node); - node - }) - } - - /// Zips two trees together into a new tree with cloned values. - #[inline] - pub fn zip_clone - (&self, other:&HashMapTree) -> HashMapTree,S> - where K:Clone, T:Clone, T2:Clone { - Self::zip_clone_branches(Some(self),Some(other)) - } - - fn zip_clone_branches - (tree1:Option<&HashMapTree>, tree2:Option<&HashMapTree>) - -> HashMapTree,S> - where K:Clone, T:Clone, T2:Clone { - match (tree1,tree2) { - (Some(tree1),Some(tree2)) => { - let value = AtLeastOneOfTwo::Both(tree1.value.clone(),tree2.value.clone()); - let mut keys = tree1.branches.keys().cloned().collect::>(); - keys.extend(tree2.branches.keys().cloned()); - let branches = keys.into_iter().map(|key| { - let branch1 = tree1.branches.get(&key); - let branch2 = tree2.branches.get(&key); - (key,Self::zip_clone_branches(branch1,branch2)) - }).collect(); - HashMapTree {value,branches} - } - - (Some(tree),None) => { - let value = AtLeastOneOfTwo::First(tree.value.clone()); - let mut keys = tree.branches.keys().cloned().collect::>(); - keys.extend(tree.branches.keys().cloned()); - let branches = tree.branches.iter().map(|(key,branch)| { - (key.clone(),Self::zip_clone_branches(Some(branch),None)) - }).collect(); - HashMapTree {value,branches} - } - - (None,Some(tree)) => { - let value = AtLeastOneOfTwo::Second(tree.value.clone()); - let mut keys = tree.branches.keys().cloned().collect::>(); - keys.extend(tree.branches.keys().cloned()); - let branches = tree.branches.iter().map(|(key,branch)| { - (key.clone(),Self::zip_clone_branches(None,Some(branch))) - }).collect(); - HashMapTree {value,branches} - } - _ => panic!("Impossible") - } - } -} - -impl HashMapTree,S> -where K:Eq+Hash { - /// Gets the current value or creates new default one if missing. - pub fn value_or_default(&mut self) -> &mut T where T:Default { - self.value_or_set_with(default) - } - - /// Gets the current value or creates new one if missing. - pub fn value_or_set(&mut self, val:T) -> &mut T { - self.value_or_set_with(move || val) - } - - /// Gets the current value or creates new one if missing. - pub fn value_or_set_with(&mut self, cons:F) -> &mut T - where F:FnOnce()->T { - if self.value.is_none() { - self.value = Some(cons()); - }; - self.value.as_mut().unwrap() - } -} - - -// === Impls === - -impl PartialSemigroup> for HashMapTree - where K : Eq + Hash + Clone, - V : Semigroup, - S : BuildHasher + Clone { - fn concat_mut(&mut self, other:Self) { - self.value.concat_mut(&other.value); - PartialSemigroup::concat_mut(&mut self.branches, other.branches); - } -} - -impl PartialSemigroup<&HashMapTree> for HashMapTree - where K : Eq + Hash + Clone, - V : Semigroup, - S : BuildHasher + Clone { - fn concat_mut(&mut self, other:&Self) { - self.value.concat_mut(&other.value); - PartialSemigroup::concat_mut(&mut self.branches, &other.branches); - } -} - - -// === Iterators === - -macro_rules! define_borrow_iterator { - ($tp_name:ident $fn_name:ident $($mut:tt)?) => { - /// Iterator. - pub struct $tp_name<'a,K,V,S> { - iters : Vec>>, - path : Vec<&'a K>, - } - - impl<'a,K,V,S> Iterator for $tp_name<'a,K,V,S> { - type Item = (Vec<&'a K>, &'a $($mut)? V); - fn next(&mut self) -> Option { - loop { - match self.iters.pop() { - None => break None, - Some(mut iter) => { - match iter.next() { - None => { self.path.pop(); } - Some((sub_key,sub_tree)) => { - self.iters.push(iter); - self.iters.push(sub_tree.branches.$fn_name()); - self.path.push(sub_key); - break Some((self.path.clone(),& $($mut)? sub_tree.value)) - } - } - } - } - } - } - } - - impl<'a,K,V,S> IntoIterator for &'a $($mut)? HashMapTree { - type Item = (Vec<&'a K>,&'a $($mut)? V); - type IntoIter = $tp_name<'a,K,V,S>; - - #[inline] - fn into_iter(self) -> Self::IntoIter { - let iters = vec![self.branches.$fn_name()]; - let path = default(); - $tp_name {iters,path} - } - } - - impl<'a,K,V,S> Debug for $tp_name<'a,K,V,S> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f,stringify!($tp_name)) - } - } - }; -} - -define_borrow_iterator!(Iter iter); -define_borrow_iterator!(IterMut iter_mut mut); - - - -// ============= -// === Tests === -// ============= - -// TODO: We should have tests here. diff --git a/lib/rust/enso-data/src/index.rs b/lib/rust/enso-data/src/index.rs deleted file mode 100644 index e31fc57d1c..0000000000 --- a/lib/rust/enso-data/src/index.rs +++ /dev/null @@ -1,84 +0,0 @@ -//! This module defines a typed index struct. Useful to introduce type safety when using indexes -//! several indexable containers. - -use crate::prelude::*; - - - -// ============= -// === Index === -// ============= - -/// Typed newtype for `usize` meant to be used as a typed index. -pub struct Index { - /// Raw value. - pub raw : usize, - phantom : PhantomData -} - -impl Index { - /// Constructor - pub fn new(raw:usize) -> Self { - let phantom = default(); - Self {raw,phantom} - } -} - -// === Impls === - -impl Copy for Index {} -impl Eq for Index {} - -impl Clone for Index { - fn clone(&self) -> Self { - *self - } -} - -impl Hash for Index { - fn hash(&self, state:&mut H) { - self.raw.hash(state) - } -} - -impl PartialEq for Index { - fn eq(&self, other:&Self) -> bool { - self.raw == other.raw - } -} - -impl From> for usize { - fn from(t:Index) -> Self { - t.raw - } -} - -impl From<&Index> for usize { - fn from(t:&Index) -> Self { - t.raw - } -} - -impl From for Index { - fn from(t:usize) -> Self { - Self::new(t) - } -} - -impl From<&usize> for Index { - fn from(t:&usize) -> Self { - Self::new(*t) - } -} - -impl Debug for Index { - fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { - write!(f,"{}",self.raw) - } -} - -impl Display for Index { - fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { - write!(f,"{}",self.raw) - } -} diff --git a/lib/rust/enso-data/src/lib.rs b/lib/rust/enso-data/src/lib.rs deleted file mode 100644 index 1faf02c68a..0000000000 --- a/lib/rust/enso-data/src/lib.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! Library of general data structures. - -#![feature(associated_type_bounds)] -#![feature(trait_alias)] - -#![warn(unsafe_code)] -#![warn(missing_copy_implementations)] -#![warn(missing_debug_implementations)] -#![warn(missing_docs)] - -pub mod hash_map_tree; -pub mod index; -pub mod opt_vec; -pub mod text; - -pub use enso_prelude as prelude; diff --git a/lib/rust/enso-data/src/opt_vec.rs b/lib/rust/enso-data/src/opt_vec.rs deleted file mode 100644 index 9928bb749d..0000000000 --- a/lib/rust/enso-data/src/opt_vec.rs +++ /dev/null @@ -1,259 +0,0 @@ -//! A sparse vector implementation. - -use crate::prelude::*; -use std::iter::FilterMap; -use std::slice; - - - -// ============== -// === OptVec === -// ============== - -// === Definition === - -/// A contiguous growable sparse array type. Similar to `Vec`, but allowing missing values. -/// After a value is removed, it remembers the index for reuse in the future. Unlike `Vec`, it is -/// parametrized with optional `Index` type variable which will be used for indexing the vector. -/// Index have to implement the `Index` trait. -#[derive(Derivative)] -#[derivative(Default(bound=""))] -#[derive(Clone,Debug,Shrinkwrap)] -pub struct OptVec { - #[shrinkwrap(main_field)] - items : Vec>, - free_ixs : SmallVec<[Index; 128]>, -} - - -// === Types === - -/// A trait for any vector index type. -pub trait Index = Debug + Copy + Into where usize : Into; - -/// Iterator type of this vector. -pub type Iter<'t,T> = FilterMap>, OptionAsRef>; - -/// Mutable iterator type of this vector. -pub type IterMut<'t,T> = FilterMap>, OptionAsRefMut>; - -/// Subtype of `Iter`. -pub type OptionAsRef = for<'r> fn(&'r Option) -> Option<&'r T>; - -/// Subtype of `IterMut`. -pub type OptionAsRefMut = for<'r> fn(&'r mut Option) -> Option<&'r mut T>; - - -// === Construction === - -impl OptVec { - /// Constructs a new, empty `Vec`. It will not allocate until elements are pushed onto it. - pub fn new() -> Self { - default() - } -} - - -// === Status Checks === - -impl OptVec { - /// Returns the number of elements in the vector, including reserved indexes. Also referred to - /// as its 'length'. - pub fn len(&self) -> usize { - self.items.len() - self.free_ixs.len() - } - - /// Returns true if vector contains no element. - pub fn is_empty(&self) -> bool { - self.items.len() == self.free_ixs.len() - } -} - - -// === Modifiers === - -impl OptVec { - /// Inserts the provided element to the vector. It reuses free indexes if any. - pub fn insert(&mut self, item: T) -> I { - self.insert_with_ix(|_| item) - } - - /// Finds a free index and inserts the element. The index is re-used in case the array is sparse - /// or is added in case of no free places. - pub fn insert_with_ix T>(&mut self, f: F) -> I { - match self.free_ixs.pop() { - None => { - let index = self.items.len().into(); - self.items.push(Some(f(index))); - index - } - Some(index) => { - self.items[index.into()] = Some(f(index)); - index - } - } - } - - /// Reserve an index for further reuse. Please remember that you cannot use the index to read - /// values unless the value is set. - pub fn reserve_index(&mut self) -> I { - self.free_ixs.pop().unwrap_or_else(|| { - let index = self.items.len().into(); - self.items.push(None); - index - }) - } - - /// Sets the value at given index. Panics if the index was already freed. - pub fn set(&mut self, index:I, t:T) { - self.items[index.into()] = Some(t); - } - - /// Removes the element at provided index and marks the index to be reused. Does nothing if the - /// index was already empty. Panics if the index was out of bounds. - pub fn remove(&mut self, index:I) -> Option { - let item = self.items[index.into()].take(); - item.iter().for_each(|_| self.free_ixs.push(index)); - item - } -} - - -// === Indexing === - -impl OptVec { - /// Index into vector. Returns `None` if the key was already freed. - pub fn safe_index(&self, index:I) -> Option<&T> { - self.items[index.into()].as_ref() - } - - /// Index into vector. Returns `None` if the key was already freed. - pub fn safe_index_mut(&mut self, index:I) -> Option<&mut T> { - self.items[index.into()].as_mut() - } -} - -impl std::ops::Index for OptVec { - type Output = T; - fn index(&self, index:I) -> &Self::Output { - let error = || panic!(format!("Trying to access removed index `{:?}`.",index)); - self.items.index(index.into()).as_ref().unwrap_or_else(error) - } -} - -impl std::ops::IndexMut for OptVec { - fn index_mut(&mut self, index:I) -> &mut Self::Output { - let error = || panic!(format!("Trying to access removed index `{:?}`.",index)); - self.items.index_mut(index.into()).as_mut().unwrap_or_else(error) - } -} - - -// === Iterators === - -impl OptVec { - /// Iterator. - pub fn iter(&self) -> Iter { - self.items.iter().filter_map(Option::as_ref) - } - - /// Mutable iterator. - pub fn iter_mut(&mut self) -> IterMut { - self.items.iter_mut().filter_map(Option::as_mut) - } -} - -impl<'a,T,I:Index> IntoIterator for &'a OptVec { - type Item = &'a T; - type IntoIter = Iter<'a,T>; - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl<'a,T,I:Index> IntoIterator for &'a mut OptVec { - type Item = &'a mut T; - type IntoIter = IterMut<'a,T>; - fn into_iter(self) -> Self::IntoIter { - self.iter_mut() - } -} - - - -// ============= -// === Tests === -// ============= - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_add() { - let mut v = OptVec::::new(); - assert!(v.is_empty()); - - let ix1 = v.insert(1); - assert_eq!(ix1,0); - assert_eq!(v.len(),1); - assert!(!v.is_empty()); - - let ix2 = v.insert(2); - assert_eq!(ix2,1); - assert_eq!(v.len(),2); - - v.remove(ix1); - assert_eq!(v.len(),1); - - v.remove(ix2); - assert_eq!(v.len(),0); - assert!(v.is_empty()); - - let ix3 = v.insert(3); - assert_eq!(v.len(),1); - - let ix4 = v.insert(4); - assert_eq!(ix3,1); - assert_eq!(ix4,0); - assert_eq!(v.len(),2); - } - - #[test] - fn test_iter() { - let mut v = OptVec::::new(); - - let ix1 = v.insert(0); - let _ix2 = v.insert(1); - let _ix3 = v.insert(2); - assert_eq!(v.len(),3); - - for (i,value) in v.into_iter().enumerate() { - assert_eq!(i, *value); - } - - v.remove(ix1); - assert_eq!(v.len(),2); - for (i,value) in v.into_iter().enumerate() { - assert_eq!(i + 1, *value); - } - } - - #[test] - fn test_iter_mut() { - let mut v = OptVec::::new(); - - let ix1 = v.insert(0); - let _ix2 = v.insert(1); - let _ix3 = v.insert(2); - assert_eq!(v.len(),3); - - v.remove(ix1); - assert_eq!(v.len(),2); - - for value in &mut v { *value *= 2; } - for (i, value) in v.into_iter().enumerate() { - assert_eq!((i + 1) * 2, *value); - } - } -} diff --git a/lib/rust/enso-data/src/text.rs b/lib/rust/enso-data/src/text.rs deleted file mode 100644 index e5f80e6158..0000000000 --- a/lib/rust/enso-data/src/text.rs +++ /dev/null @@ -1,525 +0,0 @@ -//! The common structures for text location and manipulation. - -use enso_prelude::*; - -use std::ops::Add; -use std::ops::AddAssign; -use std::ops::Range; -use std::ops::Sub; -use std::ops::SubAssign; -use serde::Serialize; -use serde::Deserialize; - - - -/// ====================================== -/// === Text Coordinates And Distances === -/// ====================================== - -// === Index === - -/// Strongly typed index into container. -#[allow(missing_docs)] -#[derive(Clone,Copy,Debug,Default,Hash,PartialEq,Eq,PartialOrd,Ord,Serialize,Deserialize)] -pub struct Index { pub value:usize } - -impl Index { - /// Initializes Index with given value. - pub fn new(value:usize) -> Self { - Index {value} - } - - /// Create char index from the byte index. It must traverse the content to count chars. - pub fn convert_byte_index(content:impl Str, index:ByteIndex) -> Self { - let slice = &content.as_ref()[..index.value]; - Self::new(slice.chars().count()) - } -} - - -// === ByteIndex === - -/// Strongly typed index of byte in String (which may differ with analogous character index, -/// because some chars takes more than one byte). -//TODO[ao] We should use structures from ensogl::,math::topology to represent different quantities -// and units. -#[allow(missing_docs)] -#[derive(Clone,Copy,Debug,Default,Hash,PartialEq,Eq,PartialOrd,Ord,Serialize,Deserialize)] -pub struct ByteIndex { pub value:usize } - -impl ByteIndex { - /// Initializes Index with given value. - pub fn new(value:usize) -> Self { - ByteIndex {value} - } -} - - -// === Size === - -/// Strongly typed size of container. -#[allow(missing_docs)] -#[derive(Clone,Copy,Debug,Default,Hash,PartialEq,Eq,PartialOrd,Ord,Serialize,Deserialize)] -pub struct Size { pub value:usize } - -impl Size { - /// Initializes Size with given value. - pub fn new(value:usize) -> Self { - Size {value} - } - - /// Checks if this is a non-empty size (more than zero elements). - pub fn non_empty(self) -> bool { - self.value > 0 - } - - /// Checks if this is an empty size (zero elements). - pub fn is_empty(self) -> bool { - self.value == 0 - } -} - -impl Add for Size { - type Output = Size; - fn add(self, rhs:Size) -> Size { - Size {value:self.value + rhs.value} - } -} - -impl AddAssign for Size { - fn add_assign(&mut self, rhs: Size) { - *self = *self + rhs; - } -} - -impl Sub for Size { - type Output = Size; - fn sub(self, rhs:Size) -> Size { - Size{value: self.value - rhs.value} - } -} - -impl SubAssign for Size { - fn sub_assign(&mut self, rhs: Size) { - *self = *self - rhs; - } -} - -impl Display for Size { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f,"{}",self.value) - } -} - -impl From<&str> for Size { - fn from(text:&str) -> Self { - Size::new(text.len()) - } -} - - -// === Span === - -/// Strongly typed span into container with index and size. -#[allow(missing_docs)] -#[derive(Clone,Copy,Debug,Default,Hash,PartialEq,Eq,PartialOrd,Ord,Serialize,Deserialize)] -pub struct Span { pub index:Index, pub size:Size } - -impl Span { - /// Initializes Span with given values. - pub fn new(index:Index, size:Size) -> Self { - Span {index,size} - } - - /// Creates a span describing a range between two indices. - pub fn from_indices(begin:Index, end:Index) -> Self { - if end < begin { - Self::from_indices(end,begin) - } else { - let index = begin; - let size = end - begin; - Span {index,size} - } - } - - /// Creates a span from zero index with given length. - pub fn from_beginning(size:Size) -> Self { - Span {index:Index::new(0), size} - } - - /// Get the character after last character of this span. - /// - /// If span has size 0, it returns the `index` field. - pub fn end(&self) -> Index { - self.index + self.size - } - - /// Check if this span contains character under `index`. - pub fn contains(&self, index:Index) -> bool { - self.index <= index && self.end() > index - } - - /// Check if this span contains the whole another span. - pub fn contains_span(&self, span:&Span) -> bool { - self.index <= span.index && self.end() >= span.end() - } - - /// Converts span to `Range`. - pub fn range(self) -> Range { - let start = self.index.value; - let end = self.end().value; - start .. end - } - - /// Expand the span by moving its left (start) index. - pub fn extend_left(&mut self, size:Size) { - self.index -= size; - self.size += size; - } - - /// Expand the span by moving its right (end) index. - pub fn extend_right(&mut self, size:Size) { - self.size += size; - } - - /// Shrink the span by moving its left (start) index. - pub fn shrink_left(&mut self, size:Size) { - self.index += size; - self.size -= size; - } - - /// Shrink the span by moving its right (end) index. - pub fn shrink_right(&mut self, size:Size) { - self.size -= size; - } - - /// Move the whole span left, maintaining its size. - pub fn move_left(&mut self, size:Size) { - self.index -= size; - } - - /// Move the whole span right, maintaining its size. - pub fn move_right(&mut self, size:Size) { - self.index += size; - } - - /// Move the start index of the span, adjusting the size. - pub fn set_left(&mut self, new_left:Index) { - let end = self.end(); - self.index = new_left; - self.size = end - new_left; - } - - /// Move the end index of the span, adjusting the size. - pub fn set_right(&mut self, new_right:Index) { - self.size = new_right - self.index; - } -} - -impls! { From + &From > for Span { |range| - Span::from_indices(Index::new(range.start), Index::new(range.end)) -}} - -impls! { Into + &Into > for Span { |this| - this.range() -}} - -impl PartialEq> for Span { - fn eq(&self, other:&Range) -> bool { - &self.range() == other - } -} - -impl Display for Span { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f,"{}..{}",self.index.value,self.end().value) - } -} - -impl std::ops::Index for str { - type Output = str; - - fn index(&self, index:Span) -> &Self::Output { - &self[index.range()] - } -} - -impl std::ops::Index for String { - type Output = str; - - fn index(&self, index:Span) -> &Self::Output { - &self.as_str()[index] - } -} - -impl From> for Span { - fn from(range:Range) -> Self { - Span::from_indices(range.start,range.end) - } -} - - -// === Operators for Index and Size === - -impl Add for Index { - type Output = Index; - fn add(self, rhs:Size) -> Index { - Index {value:self.value + rhs.value} - } -} - -impl AddAssign for Index { - fn add_assign(&mut self, rhs: Size) { - *self = *self + rhs; - } -} - -impl Sub for Index { - type Output = Index; - fn sub(self, rhs:Size) -> Index { - Index {value:self.value - rhs.value} - } -} - -impl SubAssign for Index { - fn sub_assign(&mut self, rhs: Size) { - *self = *self - rhs; - } -} - -impl Sub for Index { - type Output = Size; - fn sub(self, rhs:Index) -> Size { - Size {value:self.value - rhs.value} - } -} - - -// === TextLocation === - -/// A position of character in a multiline text. -#[derive(Copy,Clone,Debug,PartialEq,Eq,PartialOrd,Ord)] -pub struct TextLocation { - /// Line index. - pub line: usize, - /// Column is a index of char in given line. - pub column: usize, -} - -/// Short pretty print representation in the form of `line:column`. -impl Display for TextLocation { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f,"{}:{}",self.line,self.column) - } -} - -impl TextLocation { - /// Create location at begin of given line. - pub fn at_line_begin(line_index:usize) -> Self { - TextLocation { - line : line_index, - column : 0, - } - } - - /// Create location at begin of the whole document. - pub fn at_document_begin() -> Self { - TextLocation { - line : 0, - column : 0, - } - } - - /// Create location at and of the whole document. It iterates over all the content. - pub fn at_document_end(content:impl Str) -> Self { - Self::after_chars(content.as_ref().chars()) - } - - /// Convert from index of document with `content`. It iterates over all characters before - /// `index`. - pub fn from_index(content:impl Str, index:Index) -> Self { - let before = content.as_ref().chars().take(index.value); - Self::after_chars(before) - } - - /// Converts a range of indices into a range of TextLocation. It iterates over all characters - /// before range's end. - pub fn convert_range(content:impl Str, range:&Range) -> Range { - let content = content.as_ref(); - Self::from_index(content,range.start)..Self::from_index(content,range.end) - } - - /// Converts a range in bytes into a range of TextLocation. It iterates over all characters - /// before range's end. - pub fn convert_byte_range(content:impl Str, range:&Range) -> Range { - let start = Index::convert_byte_index(content.as_ref(), range.start); - let end = Index::convert_byte_index(content.as_ref(), range.end); - Self::convert_range(content,&(start..end)) - } - - fn after_chars(chars:IntoCharsIter) -> Self - where IntoCharsIter : IntoIterator { - let iter = chars.into_iter(); - let len = iter.clone().count(); - let newlines = iter.enumerate().filter(|(_,c)| *c == '\n'); - let newlines_indices = newlines.map(|(i,_)| i); - TextLocation { - line : newlines_indices.clone().count(), - column : len - newlines_indices.last().map_or(0, |i| i + 1), - } - } -} - - - -// ============== -// === Change === -// ============== - -/// A template for structure describing a text operation in one place. -/// -/// This is a generalized template, because we use different representation for both index -/// (e.g. `Index` or `TextLocation`) and inserted content (it may be just String, but also e.g. -/// Vec, or Vec> split by newlines). -#[derive(Clone,Debug,Eq,Hash,PartialEq)] -pub struct TextChangeTemplate { - /// Text fragment to be replaced. If we don't mean to remove any text, this should be an empty - /// range with start set at position there `lines` will be inserted - /// (see `TextChangeTemplate::insert` definition). - pub replaced: Range, - /// Text which replaces fragment described in `replaced` field. - pub inserted: Content, -} - -/// The simplest change representation. -pub type TextChange = TextChangeTemplate; - - -// === Constructors === - -impl TextChangeTemplate { - /// Creates operation which inserts text at given position. - pub fn insert(at:Index, text:Content) -> Self { - TextChangeTemplate { - replaced : at..at, - inserted: text, - } - } -} - -impl TextChangeTemplate { - /// Creates operation which replaces text at given range with given string. - pub fn replace(replaced:Range, text:Content) -> Self { - let inserted = text; - TextChangeTemplate {replaced,inserted} - } -} - -impl TextChangeTemplate { - /// Calculate the size of the replaced text. - pub fn replaced_size(&self) -> Index::Output { - self.replaced.end.clone() - self.replaced.start.clone() - } -} - -impl TextChangeTemplate { - /// Calculate the size of the replaced text. - pub fn replaced_span(&self) -> Span { - let index = self.replaced.start; - let size = self.replaced_size(); - Span {index,size} - } - - /// Applies the text edit on given `String` value. - /// - /// # Panics - /// - /// Panics if the replaced span is out of the string value bounds. - pub fn apply(&self, target:&mut String) where Content:AsRef { - //debug!(logger, "change: {change:?}, my code: \n```\n{code}\n```"); - let replaced_indices = self.replaced.start.value..self.replaced.end.value; - //debug!(logger, "replacing range {replaced_indices:?} with {change.inserted}"); - target.replace_range(replaced_indices,self.inserted.as_ref()); - } - - /// Applies the text edit on string and returns the result. - /// - /// # Panics - /// - /// Panics if the replaced span is out of the string value bounds. - pub fn applied(&self, target:&str) -> String where Content:AsRef { - let mut target = target.to_string(); - self.apply(&mut target); - target - } -} - -impl TextChangeTemplate { - /// Creates operation which deletes text at given range. - pub fn delete(range:Range) -> Self { - TextChangeTemplate { - replaced : range, - inserted : default(), - } - } -} - - - -// ================= -// === Utilities === -// ================= - -/// Split text to lines handling both CR and CRLF line endings. -pub fn split_to_lines(text:&str) -> impl Iterator + '_ { - text.split('\n').map(cut_cr_at_end_of_line).map(|s| s.to_string()) -} - -/// Returns slice without carriage return (also known as CR or `'\r'`) at line's end -fn cut_cr_at_end_of_line(from:&str) -> &str { - if from.ends_with('\r') { - &from[..from.len()-1] - } else { - from - } -} - - - -// ============ -// === Text === -// ============ - -#[cfg(test)] -mod test { - use super::*; - - use super::Index; - - #[test] - fn converting_index_to_location() { - let str = "first\nsecond\nthird"; - assert_eq!(TextLocation::from_index(str,Index::new(0)), TextLocation {line:0, column:0}); - assert_eq!(TextLocation::from_index(str,Index::new(5)), TextLocation {line:0, column:5}); - assert_eq!(TextLocation::from_index(str,Index::new(6)), TextLocation {line:1, column:0}); - assert_eq!(TextLocation::from_index(str,Index::new(9)), TextLocation {line:1, column:3}); - assert_eq!(TextLocation::from_index(str,Index::new(12)), TextLocation {line:1, column:6}); - assert_eq!(TextLocation::from_index(str,Index::new(13)), TextLocation {line:2, column:0}); - assert_eq!(TextLocation::from_index(str,Index::new(18)), TextLocation {line:2, column:5}); - - let str = ""; - assert_eq!(TextLocation {line:0, column:0}, TextLocation::from_index(str,Index::new(0))); - - let str= "\n"; - assert_eq!(TextLocation {line:0, column:0}, TextLocation::from_index(str,Index::new(0))); - assert_eq!(TextLocation {line:1, column:0}, TextLocation::from_index(str,Index::new(1))); - } - - #[test] - fn text_location_at_end() { - let str = "first\nsecond\nthird"; - assert_eq!(TextLocation::at_document_end(str) , TextLocation {line:2, column:5}); - assert_eq!(TextLocation::at_document_end("") , TextLocation {line:0, column:0}); - assert_eq!(TextLocation::at_document_end("\n"), TextLocation {line:1, column:0}); - } -} diff --git a/lib/rust/enso-generics/Cargo.toml b/lib/rust/enso-generics/Cargo.toml deleted file mode 100644 index 4bb3536919..0000000000 --- a/lib/rust/enso-generics/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "enso-generics" -version = "0.1.0" -authors = ["Enso Team "] -edition = "2018" - -description = "A library for type-level and generic programming." -readme = "README.md" -homepage = "https://github.com/enso-org/enso/lib/rust/enso-generics" -repository = "https://github.com/enso-org/enso" -license-file = "../../../LICENSE" - -keywords = ["type-level", "generic"] - -[lib] -crate-type = ["cdylib", "rlib"] - -[dependencies] -nalgebra = { version = "0.21.1" } diff --git a/lib/rust/enso-generics/README.md b/lib/rust/enso-generics/README.md deleted file mode 100644 index 7b08940f99..0000000000 --- a/lib/rust/enso-generics/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Enso Generics - -A library for generic and type-level programming. diff --git a/lib/rust/enso-generics/src/generic.rs b/lib/rust/enso-generics/src/generic.rs deleted file mode 100644 index 64a405e152..0000000000 --- a/lib/rust/enso-generics/src/generic.rs +++ /dev/null @@ -1,208 +0,0 @@ -//! Generic representation of data types. Refer to the crate documentation to learn more. - -// This crate defines many helper traits and uses this flag on purpose. -#![allow(missing_docs)] - -use super::hlist; -pub use nalgebra::base::dimension::*; - - - -// ============== -// === Traits === -// ============== - -/// Common traits. -pub mod traits { - pub use super::HasRepr as _TRAIT_HasRepr; - pub use super::HasFieldsCount as _TRAIT_HasFieldsCount; - - pub use super::HasItemAt as _TRAIT_HasItemAt; - pub use super::HasItemAt0 as _TRAIT_HasItemAt0; - pub use super::HasItemAt1 as _TRAIT_HasItemAt1; - pub use super::HasItemAt2 as _TRAIT_HasItemAt2; - pub use super::HasItemAt3 as _TRAIT_HasItemAt3; - pub use super::HasItemAt4 as _TRAIT_HasItemAt4; - pub use super::HasItemAt5 as _TRAIT_HasItemAt5; - pub use super::HasItemAt6 as _TRAIT_HasItemAt6; - pub use super::HasItemAt7 as _TRAIT_HasItemAt7; - pub use super::HasItemAt8 as _TRAIT_HasItemAt8; - pub use super::HasItemAt9 as _TRAIT_HasItemAt9; - pub use super::HasItemAt10 as _TRAIT_HasItemAt10; - pub use super::HasItemAt11 as _TRAIT_HasItemAt11; - pub use super::HasItemAt12 as _TRAIT_HasItemAt12; - pub use super::HasItemAt13 as _TRAIT_HasItemAt13; - pub use super::HasItemAt14 as _TRAIT_HasItemAt14; - pub use super::HasItemAt15 as _TRAIT_HasItemAt15; - - pub use super::_GetItemAt as _TRAIT__GetItemAt; - pub use super::GetItemAt as _TRAIT_GetItemAt; - pub use super::GetItemAt0 as _TRAIT_GetItemAt0; - pub use super::GetItemAt1 as _TRAIT_GetItemAt1; - pub use super::GetItemAt2 as _TRAIT_GetItemAt2; - pub use super::GetItemAt3 as _TRAIT_GetItemAt3; - pub use super::GetItemAt4 as _TRAIT_GetItemAt4; - pub use super::GetItemAt5 as _TRAIT_GetItemAt5; - pub use super::GetItemAt6 as _TRAIT_GetItemAt6; - pub use super::GetItemAt7 as _TRAIT_GetItemAt7; - pub use super::GetItemAt8 as _TRAIT_GetItemAt8; - pub use super::GetItemAt9 as _TRAIT_GetItemAt9; - pub use super::GetItemAt10 as _TRAIT_GetItemAt10; - pub use super::GetItemAt11 as _TRAIT_GetItemAt11; - pub use super::GetItemAt12 as _TRAIT_GetItemAt12; - pub use super::GetItemAt13 as _TRAIT_GetItemAt13; - pub use super::GetItemAt14 as _TRAIT_GetItemAt14; - pub use super::GetItemAt15 as _TRAIT_GetItemAt15; - - pub use super::ItemAt as _TRAIT_ItemAt; - pub use super::ItemAt0 as _TRAIT_ItemAt0; - pub use super::ItemAt1 as _TRAIT_ItemAt1; - pub use super::ItemAt2 as _TRAIT_ItemAt2; - pub use super::ItemAt3 as _TRAIT_ItemAt3; - pub use super::ItemAt4 as _TRAIT_ItemAt4; - pub use super::ItemAt5 as _TRAIT_ItemAt5; - pub use super::ItemAt6 as _TRAIT_ItemAt6; - pub use super::ItemAt7 as _TRAIT_ItemAt7; - pub use super::ItemAt8 as _TRAIT_ItemAt8; - pub use super::ItemAt9 as _TRAIT_ItemAt9; - pub use super::ItemAt10 as _TRAIT_ItemAt10; - pub use super::ItemAt11 as _TRAIT_ItemAt11; - pub use super::ItemAt12 as _TRAIT_ItemAt12; - pub use super::ItemAt13 as _TRAIT_ItemAt13; - pub use super::ItemAt14 as _TRAIT_ItemAt14; - pub use super::ItemAt15 as _TRAIT_ItemAt15; -} - - - -// =============== -// === HasRepr === -// =============== - -/// Association of a given type with its generic representation. -pub trait HasRepr { - type GenericRepr : hlist::HList; -} - -/// Type level accessor of a generic representation of the given type. -pub type Repr = ::GenericRepr; - -/// Converts the type to its generic representation. Please note that this trait is implemented -/// automatically for every type which implements `Into>`. -pub trait IntoGeneric : HasRepr + Into> { - fn into_generic(self) -> Repr { - self.into() - } -} -impl IntoGeneric for T where T : HasRepr + Into> {} - - - -// ====================== -// === HasFieldsCount === -// ====================== - -/// Information of field count of any structure implementing `Generics`. This trait is implemented -/// automatically. -pub trait HasFieldsCount { - const FIELDS_COUNT : usize; - fn fields_count() -> usize { - Self::FIELDS_COUNT - } -} - -impl HasFieldsCount for T -where T:HasRepr { - const FIELDS_COUNT : usize = as hlist::HasLength>::LEN; -} - - - -// ================ -// === HasIndex === -// ================ - -/// Trait for heterogeneous containers like tuples which contain element at index `Ix`. -pub trait HasItemAt { type Item; } -pub trait HasItemAt0 = HasItemAt; -pub trait HasItemAt1 = HasItemAt; -pub trait HasItemAt2 = HasItemAt; -pub trait HasItemAt3 = HasItemAt; -pub trait HasItemAt4 = HasItemAt; -pub trait HasItemAt5 = HasItemAt; -pub trait HasItemAt6 = HasItemAt; -pub trait HasItemAt7 = HasItemAt; -pub trait HasItemAt8 = HasItemAt; -pub trait HasItemAt9 = HasItemAt; -pub trait HasItemAt10 = HasItemAt; -pub trait HasItemAt11 = HasItemAt; -pub trait HasItemAt12 = HasItemAt; -pub trait HasItemAt13 = HasItemAt; -pub trait HasItemAt14 = HasItemAt; -pub trait HasItemAt15 = HasItemAt; - -/// Type of element at index `Ix`. Useful for heterogeneous containers like tuples. -pub type ItemAt = >::Item; -pub type ItemAt0 = ItemAt ; -pub type ItemAt1 = ItemAt ; -pub type ItemAt2 = ItemAt ; -pub type ItemAt3 = ItemAt ; -pub type ItemAt4 = ItemAt ; -pub type ItemAt5 = ItemAt ; -pub type ItemAt6 = ItemAt ; -pub type ItemAt7 = ItemAt ; -pub type ItemAt8 = ItemAt ; -pub type ItemAt9 = ItemAt ; -pub type ItemAt10 = ItemAt ; -pub type ItemAt11 = ItemAt ; -pub type ItemAt12 = ItemAt ; -pub type ItemAt13 = ItemAt ; -pub type ItemAt14 = ItemAt ; -pub type ItemAt15 = ItemAt ; - -/// Accessor for element at index `Ix`. -pub trait GetItemAt : HasItemAt + _GetItemAt { - fn get_item_at(&self) -> &ItemAt; -} - -/// Smart wrapper for `GetItemAt`. Enables syntax `lst.item_at::()`. -impl _GetItemAt for T {} -pub trait _GetItemAt { - fn item_at(&self) -> &ItemAt where Self:GetItemAt { - GetItemAt::::get_item_at(self) - } -} - -pub trait GetItemAt0 : GetItemAt { fn _0(&self) -> &ItemAt0 {self.item_at:: ()} } -pub trait GetItemAt1 : GetItemAt { fn _1(&self) -> &ItemAt1 {self.item_at:: ()} } -pub trait GetItemAt2 : GetItemAt { fn _2(&self) -> &ItemAt2 {self.item_at:: ()} } -pub trait GetItemAt3 : GetItemAt { fn _3(&self) -> &ItemAt3 {self.item_at:: ()} } -pub trait GetItemAt4 : GetItemAt { fn _4(&self) -> &ItemAt4 {self.item_at:: ()} } -pub trait GetItemAt5 : GetItemAt { fn _5(&self) -> &ItemAt5 {self.item_at:: ()} } -pub trait GetItemAt6 : GetItemAt { fn _6(&self) -> &ItemAt6 {self.item_at:: ()} } -pub trait GetItemAt7 : GetItemAt { fn _7(&self) -> &ItemAt7 {self.item_at:: ()} } -pub trait GetItemAt8 : GetItemAt { fn _8(&self) -> &ItemAt8 {self.item_at:: ()} } -pub trait GetItemAt9 : GetItemAt { fn _9(&self) -> &ItemAt9 {self.item_at:: ()} } -pub trait GetItemAt10 : GetItemAt { fn _10(&self) -> &ItemAt10 {self.item_at::()} } -pub trait GetItemAt11 : GetItemAt { fn _11(&self) -> &ItemAt11 {self.item_at::()} } -pub trait GetItemAt12 : GetItemAt { fn _12(&self) -> &ItemAt12 {self.item_at::()} } -pub trait GetItemAt13 : GetItemAt { fn _13(&self) -> &ItemAt13 {self.item_at::()} } -pub trait GetItemAt14 : GetItemAt { fn _14(&self) -> &ItemAt14 {self.item_at::()} } -pub trait GetItemAt15 : GetItemAt { fn _15(&self) -> &ItemAt15 {self.item_at::()} } - -impl> GetItemAt0 for T {} -impl> GetItemAt1 for T {} -impl> GetItemAt2 for T {} -impl> GetItemAt3 for T {} -impl> GetItemAt4 for T {} -impl> GetItemAt5 for T {} -impl> GetItemAt6 for T {} -impl> GetItemAt7 for T {} -impl> GetItemAt8 for T {} -impl> GetItemAt9 for T {} -impl> GetItemAt10 for T {} -impl> GetItemAt11 for T {} -impl> GetItemAt12 for T {} -impl> GetItemAt13 for T {} -impl> GetItemAt14 for T {} -impl> GetItemAt15 for T {} diff --git a/lib/rust/enso-generics/src/hlist.rs b/lib/rust/enso-generics/src/hlist.rs deleted file mode 100644 index ae48fa152c..0000000000 --- a/lib/rust/enso-generics/src/hlist.rs +++ /dev/null @@ -1,369 +0,0 @@ -//! HList provides many operations to create and manipulate heterogenous lists (HLists) whose length -//! and element types are known at compile-time. HLists can be used to implement records, variants, -//! type-indexed products (TIP), type-indexed co-products (TIC), or keyword arguments. - - - -// ============= -// === HList === -// ============= - -/// Type of every `HList`. -pub trait HList = HasLength; - -/// Empty `HList` value. -#[derive(Debug,Clone,Copy)] -pub struct Nil; - -/// Non-empty `HList` with head and tail. -#[derive(Debug,Clone,Copy)] -#[allow(missing_docs)] -pub struct Cons(pub Head, pub Tail); - - - -// === Smart Constructors === - -/// Creates new `HList` from the provided elements, similar to `vec!`. In order to provide type for -/// the list, use the `ty` macro. In order to pattern match on it, use the `pat` macro. -/// -/// ```compile_fail -/// let HList::pat![t1,t2] : HList::ty![&str,usize] = HList::new!["hello",7]; -/// ``` -#[macro_export] -macro_rules! new { - ($(,)*) => { $crate::Nil }; - ($t:expr $(,$($ts:expr),*)?) => { - $crate::Cons($t,$crate::new!{$($($ts),*)?}) - } -} - -/// Pattern matches on a `HList`. See docs of `new` to learn more. -#[macro_export] -macro_rules! pat { - ($(,)*) => { $crate::Nil }; - ($t:pat $(,$($ts:pat),*)?) => { - $crate::Cons($t,$crate::pat!{$($($ts),*)?}) - } -} - -/// Smart `HList` type constructor. See docs of `new` to learn more. -#[macro_export] -macro_rules! ty { - ($(,)*) => { $crate::Nil }; - ($t:ty $(,$($ts:ty),*)?) => { - $crate::Cons<$t,$crate::ty!{$($($ts),*)?}> - } -} - - - -// ============== -// === Length === -// ============== - -/// Compile-time known length value. -#[allow(missing_docs)] -pub trait HasLength { - const LEN : usize; - fn len() -> usize { - Self::LEN - } -} - -/// Compile-time known length value. -pub const fn len() -> usize { - ::LEN -} - -impl HasLength for Nil { const LEN : usize = 0; } -impl HasLength for Cons { const LEN : usize = 1 + len::(); } - - - -// ============ -// === Head === -// ============ - -/// Head element accessor. -#[allow(missing_docs)] -pub trait KnownHead { - type Head; -} - -/// Head element type accessor. -pub type Head = ::Head; - -/// Head element accessor. -#[allow(missing_docs)] -pub trait GetHead : KnownHead { - fn head(&self) -> &Self::Head; -} - -/// Mutable head element accessor. -#[allow(missing_docs)] -pub trait GetHeadMut : KnownHead { - fn head_mut(&mut self) -> &mut Self::Head; -} - -/// Head element clone. -#[allow(missing_docs)] -pub trait GetHeadClone : KnownHead { - fn head_clone(&self) -> Self::Head; -} - -impl GetHeadClone for T -where T:GetHead, Head:Clone { - default fn head_clone(&self) -> Self::Head { - self.head().clone() - } -} - - -// === Impls === - -impl KnownHead for Cons { - type Head = H; -} - -impl GetHead for Cons { - fn head(&self) -> &Self::Head { - &self.0 - } -} - -impl GetHeadMut for Cons { - fn head_mut(&mut self) -> &mut Self::Head { - &mut self.0 - } -} - - - -// ============ -// === Tail === -// ============ - -/// Tail element accessor. -#[allow(missing_docs)] -pub trait KnownTail { - type Tail; -} - -/// Tail element type accessor. -pub type Tail = ::Tail; - -/// Tail element accessor. -#[allow(missing_docs)] -pub trait GetTail : KnownTail { - fn tail(&self) -> &Self::Tail; -} - -/// Mutable tail element accessor. -#[allow(missing_docs)] -pub trait GetTailMut : KnownTail { - fn tail_mut(&mut self) -> &mut Self::Tail; -} - -/// Tail element clone. -#[allow(missing_docs)] -pub trait GetTailClone : KnownTail { - fn tail_clone(&self) -> Self::Tail; -} - -impl GetTailClone for T - where T:GetTail, Tail:Clone { - default fn tail_clone(&self) -> Self::Tail { - self.tail().clone() - } -} - - -// === Impls === - -impl KnownTail for Cons { - type Tail = T; -} - -impl GetTail for Cons { - fn tail(&self) -> &Self::Tail { - &self.1 - } -} - -impl GetTailMut for Cons { - fn tail_mut(&mut self) -> &mut Self::Tail { - &mut self.1 - } -} - - - -// ============ -// === Last === -// ============ - -/// Last element accessor. -#[allow(missing_docs)] -pub trait KnownLast { - type Last; -} - -/// Last element type accessor. -pub type Last = ::Last; - -/// Last element accessor. -#[allow(missing_docs)] -pub trait GetLast : KnownLast { - fn last(&self) -> &Self::Last; -} - -/// Mutable last element accessor. -#[allow(missing_docs)] -pub trait GetLastMut : KnownLast { - fn last_mut(&mut self) -> &mut Self::Last; -} - -/// Last element clone. -#[allow(missing_docs)] -pub trait GetLastClone : KnownLast { - fn last_clone(&self) -> Self::Last; -} - -impl GetLastClone for T - where T:GetLast, Last:Clone { - default fn last_clone(&self) -> Self::Last { - self.last().clone() - } -} - - -// === Impls === - -impl KnownLast for Cons { type Last = H; } -impl KnownLast for Cons { type Last = Last; } - -impl GetLast for Cons { - fn last(&self) -> &Self::Last { - &self.0 - } -} - -impl GetLastMut for Cons { - fn last_mut(&mut self) -> &mut Self::Last { - &mut self.0 - } -} - -impl GetLast for Cons { - fn last(&self) -> &Self::Last { - self.tail().last() - } -} - -impl GetLastMut for Cons { - fn last_mut(&mut self) -> &mut Self::Last { - self.tail_mut().last_mut() - } -} - - - - -// ============ -// === Init === -// ============ - -/// Init elements accessor (all but last). -#[allow(missing_docs)] -pub trait KnownInit { - type Init; -} - -/// Init elements type accessor. -pub type Init = ::Init; - -/// Init element clone. -#[allow(missing_docs)] -pub trait GetInitClone : KnownInit { - fn init_clone(&self) -> Self::Init; -} - - -// === Impls === - -impl KnownInit for Cons { type Init = Nil; } -impl KnownInit for Cons { type Init = Cons>; } - -impl GetInitClone for Cons { - fn init_clone(&self) -> Self::Init { - Nil - } -} - -impl GetInitClone for Cons { - fn init_clone(&self) -> Self::Init { - Cons(self.head().clone(),self.tail().init_clone()) - } -} - - - -// ================ -// === PushBack === -// ================ - -// TODO: Consider implementing PushBack for everything that converts to and from HList. - -/// Add a new element to the back of the list. -#[allow(missing_docs)] -pub trait PushBack : Sized { - type Output : KnownLast + KnownInit; - fn push_back(self,t:T) -> Self::Output; -} - -impl PushBack for Nil { - type Output = Cons; - #[inline(always)] - fn push_back(self,x:X) -> Self::Output { - Cons(x,Nil) - } -} - -impl PushBack for Cons - where T:PushBack { - type Output = Cons>::Output>; - #[inline(always)] - fn push_back(self,x:X) -> Self::Output { - let Cons(head,tail) = self; - Cons(head,tail.push_back(x)) - } -} - - - -// =============== -// === PopBack === -// =============== - -// TODO: Consider implementing PopBack for everything that converts to and from HList. - -/// Remove the last element of the list and return it and the new list. -#[allow(missing_docs)] -pub trait PopBack : KnownLast + KnownInit { - fn pop_back(self) -> (Self::Last,Self::Init); -} - -impl PopBack for Cons { - fn pop_back(self) -> (Self::Last,Self::Init) { - (self.0,Nil) - } -} - -impl PopBack for Cons -where T:PopBack { - fn pop_back(self) -> (Self::Last,Self::Init) { - let (last,tail) = self.1.pop_back(); - (last,Cons(self.0,tail)) - } -} diff --git a/lib/rust/enso-generics/src/lib.rs b/lib/rust/enso-generics/src/lib.rs deleted file mode 100644 index 38837673a2..0000000000 --- a/lib/rust/enso-generics/src/lib.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! Rust Generics implementation. -//! -//! Datatype-generic programming, also frequently just called generic programming or generics, is a -//! form of abstraction that allows defining functions that can operate on a large class of -//! data types. For a more in-depth introduction to generic programming in general, have a look at -//! [Datatype-Generic Programming](http://www.cs.ox.ac.uk/jeremy.gibbons/publications/dgp.pdf), or -//! the [Libraries for Generic Programming](http://dreixel.net/research/pdf/lgph.pdf) paper. - -#![deny(unconditional_recursion)] - -#![warn(missing_copy_implementations)] -#![warn(missing_debug_implementations)] -#![warn(missing_docs)] -#![warn(trivial_casts)] -#![warn(trivial_numeric_casts)] -#![warn(unsafe_code)] -#![warn(unused_import_braces)] -#![warn(unused_qualifications)] - -#![feature(const_fn)] -#![feature(specialization)] -#![feature(trait_alias)] - -pub mod generic; -pub mod hlist; -pub mod tuple; - -pub use generic::*; -pub use hlist::*; -pub use tuple::*; diff --git a/lib/rust/enso-generics/src/tuple.rs b/lib/rust/enso-generics/src/tuple.rs deleted file mode 100644 index 5f70a8300c..0000000000 --- a/lib/rust/enso-generics/src/tuple.rs +++ /dev/null @@ -1,622 +0,0 @@ -//! This module contains implementations of generic operations on tuples. - -use crate as hlist; -use nalgebra::base::dimension::*; - - - -// ==================== -// === HasTupleRepr === -// ==================== - -/// All types which have a tuple representation. -#[allow(missing_docs)] -pub trait HasTupleRepr { - type TupleRepr; -} - -/// Tuple representation of a type. -pub type TupleRepr = ::TupleRepr; - -/// Conversion of the given type to its tuple representation. -#[allow(missing_docs)] -pub trait IntoTuple : HasTupleRepr + Into> { - fn into_tuple(self) -> TupleRepr { - self.into() - } -} - -impl IntoTuple for T where T : HasTupleRepr + Into> {} - - - -// =================== -// === GenericRepr === -// =================== - -macro_rules! gen_as_hlist_for_tuples { - () => {}; - ($t:ident $(,$($ts:ident),*)?) => { - impl <$($($ts),*)?> $crate::HasRepr for ($($($ts,)*)?) { - type GenericRepr = hlist::ty! { $($($ts),*)? }; - } - gen_as_hlist_for_tuples! { $($($ts),*)? } - } -} - -gen_as_hlist_for_tuples! {T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12} - - - - -// ============================= -// === KnownLast / KnownInit === -// ============================= - -macro_rules! gen_known_last { - () => {}; - ($t:ident $(,$($ts:ident),*)?) => { - impl $crate::KnownLast for ($($($ts,)*)? X,) { type Last = X; } - gen_known_last! { $($($ts),*)? } - } -} - -macro_rules! gen_known_init { - () => {}; - ($t:ident $(,$($ts:ident),*)?) => { - impl $crate::KnownInit for ($($($ts,)*)? X,) { type Init = ($($($ts,)*)?); } - gen_known_init! { $($($ts),*)? } - } -} - -gen_known_last!{T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11} -gen_known_init!{T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11} - - - - -// ================ -// === PushBack === -// ================ - -impl hlist::PushBack -for () { - type Output = (X,); - fn push_back(self,x:X) -> Self::Output { - (x,) - } -} - -impl hlist::PushBack -for (T0,) { - type Output = (T0,X); - fn push_back(self,x:X) -> Self::Output { - (self.0,x) - } -} - -impl hlist::PushBack -for (T0,T1) { - type Output = (T0,T1,X); - fn push_back(self,x:X) -> Self::Output { - (self.0,self.1,x) - } -} - -impl hlist::PushBack -for (T0,T1,T2) { - type Output = (T0,T1,T2,X); - fn push_back(self,x:X) -> Self::Output { - (self.0,self.1,self.2,x) - } -} - -impl hlist::PushBack -for (T0,T1,T2,T3) { - type Output = (T0,T1,T2,T3,X); - fn push_back(self,x:X) -> Self::Output { - (self.0,self.1,self.2,self.3,x) - } -} - -impl hlist::PushBack -for (T0,T1,T2,T3,T4) { - type Output = (T0,T1,T2,T3,T4,X); - fn push_back(self,x:X) -> Self::Output { - (self.0,self.1,self.2,self.3,self.4,x) - } -} - -impl hlist::PushBack -for (T0,T1,T2,T3,T4,T5) { - type Output = (T0,T1,T2,T3,T4,T5,X); - fn push_back(self,x:X) -> Self::Output { - (self.0,self.1,self.2,self.3,self.4,self.5,x) - } -} - -impl hlist::PushBack -for (T0,T1,T2,T3,T4,T5,T6) { - type Output = (T0,T1,T2,T3,T4,T5,T6,X); - fn push_back(self,x:X) -> Self::Output { - (self.0,self.1,self.2,self.3,self.4,self.5,self.6,x) - } -} - -impl hlist::PushBack -for (T0,T1,T2,T3,T4,T5,T6,T7) { - type Output = (T0,T1,T2,T3,T4,T5,T6,T7,X); - fn push_back(self,x:X) -> Self::Output { - (self.0,self.1,self.2,self.3,self.4,self.5,self.6,self.7,x) - } -} - -impl hlist::PushBack -for (T0,T1,T2,T3,T4,T5,T6,T7,T8) { - type Output = (T0,T1,T2,T3,T4,T5,T6,T7,T8,X); - fn push_back(self,x:X) -> Self::Output { - (self.0,self.1,self.2,self.3,self.4,self.5,self.6,self.7,self.8,x) - } -} - -impl hlist::PushBack -for (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9) { - type Output = (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,X); - fn push_back(self,x:X) -> Self::Output { - (self.0,self.1,self.2,self.3,self.4,self.5,self.6,self.7,self.8,self.9,x) - } -} - -impl hlist::PushBack -for (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10) { - type Output = (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,X); - fn push_back(self,x:X) -> Self::Output { - (self.0,self.1,self.2,self.3,self.4,self.5,self.6,self.7,self.8,self.9,self.10,x) - } -} - - - - -// =============== -// === PopBack === -// =============== - -impl hlist::PopBack -for (T0,) { - fn pop_back(self) -> (Self::Last,Self::Init) { - (self.0,()) - } -} - -impl hlist::PopBack -for (T0,T1) { - fn pop_back(self) -> (Self::Last,Self::Init) { - (self.1,(self.0,)) - } -} - -impl hlist::PopBack -for (T0,T1,T2) { - fn pop_back(self) -> (Self::Last,Self::Init) { - (self.2,(self.0,self.1)) - } -} - -impl hlist::PopBack -for (T0,T1,T2,T3) { - fn pop_back(self) -> (Self::Last,Self::Init) { - (self.3,(self.0,self.1,self.2)) - } -} - -impl hlist::PopBack -for (T0,T1,T2,T3,T4) { - fn pop_back(self) -> (Self::Last,Self::Init) { - (self.4,(self.0,self.1,self.2,self.3)) - } -} - -impl hlist::PopBack -for (T0,T1,T2,T3,T4,T5) { - fn pop_back(self) -> (Self::Last,Self::Init) { - (self.5,(self.0,self.1,self.2,self.3,self.4)) - } -} - -impl hlist::PopBack -for (T0,T1,T2,T3,T4,T5,T6) { - fn pop_back(self) -> (Self::Last,Self::Init) { - (self.6,(self.0,self.1,self.2,self.3,self.4,self.5)) - } -} - -impl hlist::PopBack -for (T0,T1,T2,T3,T4,T5,T6,T7) { - fn pop_back(self) -> (Self::Last,Self::Init) { - (self.7,(self.0,self.1,self.2,self.3,self.4,self.5,self.6)) - } -} - -impl hlist::PopBack -for (T0,T1,T2,T3,T4,T5,T6,T7,T8) { - fn pop_back(self) -> (Self::Last,Self::Init) { - (self.8,(self.0,self.1,self.2,self.3,self.4,self.5,self.6,self.7)) - } -} - -impl hlist::PopBack -for (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9) { - fn pop_back(self) -> (Self::Last,Self::Init) { - (self.9,(self.0,self.1,self.2,self.3,self.4,self.5,self.6,self.7,self.8)) - } -} - -impl hlist::PopBack -for (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10) { - fn pop_back(self) -> (Self::Last,Self::Init) { - (self.10,(self.0,self.1,self.2,self.3,self.4,self.5,self.6,self.7,self.8,self.9)) - } -} - -impl hlist::PopBack -for (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11) { - fn pop_back(self) -> (Self::Last,Self::Init) { - (self.11,(self.0,self.1,self.2,self.3,self.4,self.5,self.6,self.7,self.8,self.9,self.10)) - } -} - - - -// ================================= -// === Conversion Tuple -> HList === -// ================================= - -impl From<()> -for hlist::ty![] { - #[inline(always)] - fn from(_:()) -> Self { - hlist::new![] - } -} - -impl From<(T0,)> -for hlist::ty![T0] { - #[inline(always)] - fn from(t:(T0,)) -> Self { - hlist::new![t.0] - } -} - -impl From<(T0,T1,)> -for hlist::ty![T0,T1] { - #[inline(always)] - fn from(t:(T0,T1,)) -> Self { - hlist::new![t.0,t.1] - } -} - -impl From<(T0,T1,T2,)> -for hlist::ty![T0,T1,T2] { - #[inline(always)] - fn from(t:(T0,T1,T2,)) -> Self { - hlist::new![t.0,t.1,t.2] - } -} - -impl From<(T0,T1,T2,T3,)> -for hlist::ty![T0,T1,T2,T3] { - #[inline(always)] - fn from(t:(T0,T1,T2,T3,)) -> Self { - hlist::new![t.0,t.1,t.2,t.3] - } -} - -impl From<(T0,T1,T2,T3,T4,)> -for hlist::ty![T0,T1,T2,T3,T4] { - #[inline(always)] - fn from(t:(T0,T1,T2,T3,T4,)) -> Self { - hlist::new![t.0,t.1,t.2,t.3,t.4] - } -} - -impl From<(T0,T1,T2,T3,T4,T5,)> -for hlist::ty![T0,T1,T2,T3,T4,T5] { - #[inline(always)] - fn from(t:(T0,T1,T2,T3,T4,T5,)) -> Self { - hlist::new![t.0,t.1,t.2,t.3,t.4,t.5] - } -} - -impl From<(T0,T1,T2,T3,T4,T5,T6,)> -for hlist::ty![T0,T1,T2,T3,T4,T5,T6] { - #[inline(always)] - fn from(t:(T0,T1,T2,T3,T4,T5,T6,)) -> Self { - hlist::new![t.0,t.1,t.2,t.3,t.4,t.5,t.6] - } -} - -impl From<(T0,T1,T2,T3,T4,T5,T6,T7,)> -for hlist::ty![T0,T1,T2,T3,T4,T5,T6,T7] { - #[inline(always)] - fn from(t:(T0,T1,T2,T3,T4,T5,T6,T7,)) -> Self { - hlist::new![t.0,t.1,t.2,t.3,t.4,t.5,t.6,t.7] - } -} - -impl From<(T0,T1,T2,T3,T4,T5,T6,T7,T8,)> -for hlist::ty![T0,T1,T2,T3,T4,T5,T6,T7,T8] { - #[inline(always)] - fn from(t:(T0,T1,T2,T3,T4,T5,T6,T7,T8,)) -> Self { - hlist::new![t.0,t.1,t.2,t.3,t.4,t.5,t.6,t.7,t.8] - } -} - -impl From<(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,)> -for hlist::ty![T0,T1,T2,T3,T4,T5,T6,T7,T8,T9] { - #[inline(always)] - fn from(t:(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,)) -> Self { - hlist::new![t.0,t.1,t.2,t.3,t.4,t.5,t.6,t.7,t.8,t.9] - } -} - -impl From<(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,)> -for hlist::ty![T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10] { - #[inline(always)] - fn from(t:(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,)) -> Self { - hlist::new![t.0,t.1,t.2,t.3,t.4,t.5,t.6,t.7,t.8,t.9,t.10] - } -} - -impl From<(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,)> -for hlist::ty![T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11] { - #[inline(always)] - fn from(t:(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,)) -> Self { - hlist::new![t.0,t.1,t.2,t.3,t.4,t.5,t.6,t.7,t.8,t.9,t.10,t.11] - } -} - - - - -// ================================= -// === Conversion HList -> Tuple === -// ================================= - -impl Into<()> -for hlist::ty![] { - #[inline(always)] - fn into(self) {} -} - -impl Into<(T0,)> -for hlist::ty![T0] { - #[inline(always)] - fn into(self) -> (T0,) { - let hlist::pat![t0] = self; - (t0,) - } -} - -impl Into<(T0,T1)> -for hlist::ty![T0,T1] { - #[inline(always)] - fn into(self) -> (T0,T1) { - let hlist::pat![t0,t1] = self; - (t0,t1) - } -} - -impl Into<(T0,T1,T2)> -for hlist::ty![T0,T1,T2] { - #[inline(always)] - fn into(self) -> (T0,T1,T2) { - let hlist::pat![t0,t1,t2] = self; - (t0,t1,t2) - } -} - -impl Into<(T0,T1,T2,T3)> -for hlist::ty![T0,T1,T2,T3] { - #[inline(always)] - fn into(self) -> (T0,T1,T2,T3) { - let hlist::pat![t0,t1,t2,t3] = self; - (t0,t1,t2,t3) - } -} - -impl Into<(T0,T1,T2,T3,T4)> -for hlist::ty![T0,T1,T2,T3,T4] { - #[inline(always)] - fn into(self) -> (T0,T1,T2,T3,T4) { - let hlist::pat![t0,t1,t2,t3,t4] = self; - (t0,t1,t2,t3,t4) - } -} - -impl Into<(T0,T1,T2,T3,T4,T5)> -for hlist::ty![T0,T1,T2,T3,T4,T5] { - #[inline(always)] - fn into(self) -> (T0,T1,T2,T3,T4,T5) { - let hlist::pat![t0,t1,t2,t3,t4,t5] = self; - (t0,t1,t2,t3,t4,t5) - } -} - -impl Into<(T0,T1,T2,T3,T4,T5,T6)> -for hlist::ty![T0,T1,T2,T3,T4,T5,T6] { - #[inline(always)] - fn into(self) -> (T0,T1,T2,T3,T4,T5,T6) { - let hlist::pat![t0,t1,t2,t3,t4,t5,t6] = self; - (t0,t1,t2,t3,t4,t5,t6) - } -} - -impl Into<(T0,T1,T2,T3,T4,T5,T6,T7)> -for hlist::ty![T0,T1,T2,T3,T4,T5,T6,T7] { - #[inline(always)] - fn into(self) -> (T0,T1,T2,T3,T4,T5,T6,T7) { - let hlist::pat![t0,t1,t2,t3,t4,t5,t6,t7] = self; - (t0,t1,t2,t3,t4,t5,t6,t7) - } -} - -impl Into<(T0,T1,T2,T3,T4,T5,T6,T7,T8)> -for hlist::ty![T0,T1,T2,T3,T4,T5,T6,T7,T8] { - #[inline(always)] - fn into(self) -> (T0,T1,T2,T3,T4,T5,T6,T7,T8) { - let hlist::pat![t0,t1,t2,t3,t4,t5,t6,t7,t8] = self; - (t0,t1,t2,t3,t4,t5,t6,t7,t8) - } -} - -impl Into<(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9)> -for hlist::ty![T0,T1,T2,T3,T4,T5,T6,T7,T8,T9] { - #[inline(always)] - fn into(self) -> (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9) { - let hlist::pat![t0,t1,t2,t3,t4,t5,t6,t7,t8,t9] = self; - (t0,t1,t2,t3,t4,t5,t6,t7,t8,t9) - } -} - -impl Into<(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10)> -for hlist::ty![T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10] { - #[inline(always)] - fn into(self) -> (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10) { - let hlist::pat![t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10] = self; - (t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10) - } -} - -impl Into<(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11)> -for hlist::ty![T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11] { - #[inline(always)] - fn into(self) -> (T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11) { - let hlist::pat![t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11] = self; - (t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11) - } -} - - - -// ============================== -// === HasTupleRepr for HList === -// ============================== - -impl HasTupleRepr -for hlist::ty![] { - type TupleRepr = (); -} - -impl HasTupleRepr -for hlist::ty![T1] { - type TupleRepr = (T1,); -} - -impl HasTupleRepr -for hlist::ty![T1,T2] { - type TupleRepr = (T1,T2); -} - -impl HasTupleRepr -for hlist::ty![T1,T2,T3] { - type TupleRepr = (T1,T2,T3); -} - -impl HasTupleRepr -for hlist::ty![T1,T2,T3,T4] { - type TupleRepr = (T1,T2,T3,T4); -} - -impl HasTupleRepr -for hlist::ty![T1,T2,T3,T4,T5] { - type TupleRepr = (T1,T2,T3,T4,T5); -} - -impl HasTupleRepr -for hlist::ty![T1,T2,T3,T4,T5,T6] { - type TupleRepr = (T1,T2,T3,T4,T5,T6); -} - -impl HasTupleRepr -for hlist::ty![T1,T2,T3,T4,T5,T6,T7] { - type TupleRepr = (T1,T2,T3,T4,T5,T6,T7); -} - -impl HasTupleRepr -for hlist::ty![T1,T2,T3,T4,T5,T6,T7,T8] { - type TupleRepr = (T1,T2,T3,T4,T5,T6,T7,T8); -} - -impl HasTupleRepr -for hlist::ty![T1,T2,T3,T4,T5,T6,T7,T8,T9] { - type TupleRepr = (T1,T2,T3,T4,T5,T6,T7,T8,T9); -} - -impl HasTupleRepr -for hlist::ty![T1,T2,T3,T4,T5,T6,T7,T8,T9,T10] { - type TupleRepr = (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10); -} - -impl HasTupleRepr -for hlist::ty![T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11] { - type TupleRepr = (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11); -} - - - -// ================= -// === HasItemAt === -// ================= - -macro_rules! gen_has_item_at { - ($at:ident $p:tt) => {}; - ($at:ident [$($p:ident),*] $t:ident $(,$($ts:ident),*)?) => { - impl<$($p,)* X $(,$($ts),*)?> $crate::HasItemAt<$at> for ($($p,)*X,$($($ts,)*)?) { - type Item = X; - } - gen_has_item_at! { $at [$($p),*] $($($ts),*)? } - } -} - -gen_has_item_at!{U0 [] T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11} -gen_has_item_at!{U1 [T0] T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11} -gen_has_item_at!{U2 [T0,T1] T2,T3,T4,T5,T6,T7,T8,T9,T10,T11} -gen_has_item_at!{U3 [T0,T1,T2] T3,T4,T5,T6,T7,T8,T9,T10,T11} -gen_has_item_at!{U4 [T0,T1,T2,T3] T4,T5,T6,T7,T8,T9,T10,T11} -gen_has_item_at!{U5 [T0,T1,T2,T3,T4] T5,T6,T7,T8,T9,T10,T11} -gen_has_item_at!{U6 [T0,T1,T2,T3,T4,T5] T6,T7,T8,T9,T10,T11} -gen_has_item_at!{U7 [T0,T1,T2,T3,T4,T5,T6] T7,T8,T9,T10,T11} -gen_has_item_at!{U8 [T0,T1,T2,T3,T4,T5,T6,T7] T8,T9,T10,T11} -gen_has_item_at!{U9 [T0,T1,T2,T3,T4,T5,T6,T7,T8] T9,T10,T11} -gen_has_item_at!{U10 [T0,T1,T2,T3,T4,T5,T6,T7,T8,T9] T10,T11} -gen_has_item_at!{U11 [T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10] T11} - - - -// ================= -// === GetItemAt === -// ================= - -macro_rules! gen_get_item_at { - ($at:ident $num:tt $p:tt) => {}; - ($at:ident $num:tt [$($p:ident),*] $t:ident $(,$($ts:ident),*)?) => { - impl<$($p,)* X $(,$($ts),*)?> $crate::GetItemAt<$at> for ($($p,)*X,$($($ts,)*)?) { - fn get_item_at(&self) -> &X { &self.$num } - } - gen_get_item_at! { $at $num [$($p),*] $($($ts),*)? } - } -} - -gen_get_item_at!{U0 0 [] T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11} -gen_get_item_at!{U1 1 [T0] T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11} -gen_get_item_at!{U2 2 [T0,T1] T2,T3,T4,T5,T6,T7,T8,T9,T10,T11} -gen_get_item_at!{U3 3 [T0,T1,T2] T3,T4,T5,T6,T7,T8,T9,T10,T11} -gen_get_item_at!{U4 4 [T0,T1,T2,T3] T4,T5,T6,T7,T8,T9,T10,T11} -gen_get_item_at!{U5 5 [T0,T1,T2,T3,T4] T5,T6,T7,T8,T9,T10,T11} -gen_get_item_at!{U6 6 [T0,T1,T2,T3,T4,T5] T6,T7,T8,T9,T10,T11} -gen_get_item_at!{U7 7 [T0,T1,T2,T3,T4,T5,T6] T7,T8,T9,T10,T11} -gen_get_item_at!{U8 8 [T0,T1,T2,T3,T4,T5,T6,T7] T8,T9,T10,T11} -gen_get_item_at!{U9 9 [T0,T1,T2,T3,T4,T5,T6,T7,T8] T9,T10,T11} -gen_get_item_at!{U10 10 [T0,T1,T2,T3,T4,T5,T6,T7,T8,T9] T10,T11} -gen_get_item_at!{U11 11 [T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10] T11} diff --git a/lib/rust/enso-logger/Cargo.toml b/lib/rust/enso-logger/Cargo.toml deleted file mode 100644 index 0b657fed39..0000000000 --- a/lib/rust/enso-logger/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "enso-logger" -version = "0.1.0" -authors = ["Enso Team "] -edition = "2018" - -description = "A generic logging library." -readme = "README.md" -homepage = "https://github.com/enso-org/enso/lib/rust/enso-logger" -repository = "https://github.com/enso-org/enso" -license-file = "../../../LICENSE" - -[lib] -crate-type = ["cdylib", "rlib"] - -[features] -default = [] - -[dependencies] -enso-prelude = { version = "0.1.0" , path = "../enso-prelude" } -enso-shapely = { version = "0.1.0" , path = "../enso-shapely/impl" } -wasm-bindgen = { version = "=0.2.58", features = ["nightly"] } - -[dependencies.web-sys] -version = "0.3.4" -features = ['console'] diff --git a/lib/rust/enso-logger/README.md b/lib/rust/enso-logger/README.md deleted file mode 100644 index 68794925a1..0000000000 --- a/lib/rust/enso-logger/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Enso Logger - -A generic logging library. diff --git a/lib/rust/enso-logger/src/disabled.rs b/lib/rust/enso-logger/src/disabled.rs deleted file mode 100644 index 82b70e265d..0000000000 --- a/lib/rust/enso-logger/src/disabled.rs +++ /dev/null @@ -1,35 +0,0 @@ -//! Contains definition of trivial logger that discards all messages except warnings and errors. - -use enso_prelude::*; - -use crate::Message; -use crate::AnyLogger; -use crate::enabled; - -use enso_shapely::CloneRef; -use std::fmt::Debug; - - - -// ============== -// === Logger === -// ============== - -/// Trivial logger that discards all messages except warnings and errors. -#[derive(Clone,CloneRef,Debug,Default)] -pub struct Logger { - enabled : enabled::Logger, -} - - -// === Impls === - -impls!{ From + &From for Logger { |logger| Self::new(logger.path()) }} - -impl AnyLogger for Logger { - type Owned = Self; - fn new (path:impl Into) -> Self { Self {enabled : enabled::Logger::new(path) } } - fn path (&self) -> &str { self.enabled.path() } - fn warning (&self, msg:impl Message) { self.enabled.warning (msg) } - fn error (&self, msg:impl Message) { self.enabled.error (msg) } -} diff --git a/lib/rust/enso-logger/src/enabled.rs b/lib/rust/enso-logger/src/enabled.rs deleted file mode 100644 index 095a62a211..0000000000 --- a/lib/rust/enso-logger/src/enabled.rs +++ /dev/null @@ -1,97 +0,0 @@ -//! Contains implementation of default logger. - -use enso_prelude::*; - -use crate::AnyLogger; -use crate::Message; - -use enso_shapely::CloneRef; -use std::fmt::Debug; - -#[cfg(target_arch = "wasm32")] -use web_sys::console; -#[cfg(target_arch = "wasm32")] -use wasm_bindgen::JsValue; - - - -// ============== -// === Logger === -// ============== - -/// Default Logger implementation. -#[derive(Clone,CloneRef,Debug,Default)] -pub struct Logger { - /// Path that is used as an unique identifier of this logger. - path : ImString, - #[cfg(not(target_arch="wasm32"))] - indent : Rc>, -} - -#[cfg(not(target_arch="wasm32"))] -impl Logger { - fn format(&self, msg:impl Message) -> String { - let indent = " ".repeat(4*self.indent.get()); - msg.with(|s|iformat!("{indent}[{self.path}] {s}")) - } - - fn inc_indent(&self) { - self.indent.update(|t|t+1); - } - - fn dec_indent(&self) { - self.indent.update(|t|t.saturating_sub(1)); - } -} - -#[cfg(target_arch="wasm32")] -impl Logger { - fn format(&self, msg:impl Message) -> JsValue { - msg.with(|s|iformat!("[{self.path}] {s}")).into() - } -} - -#[cfg(not(target_arch="wasm32"))] -impl AnyLogger for Logger { - type Owned = Self; - fn new(path:impl Into) -> Self { - let path = path.into(); - let indent = default(); - Self {path,indent} - } - - fn path (&self) -> &str { &self.path } - fn trace (&self, msg:impl Message) { println!("{}",self.format(msg)) } - fn debug (&self, msg:impl Message) { println!("{}",self.format(msg)) } - fn info (&self, msg:impl Message) { println!("{}",self.format(msg)) } - fn warning (&self, msg:impl Message) { println!("[WARNING] {}",self.format(msg)) } - fn error (&self, msg:impl Message) { println!("[ERROR] {}",self.format(msg)) } - fn group_begin (&self, msg:impl Message) { println!("{}",self.format(msg)); self.inc_indent() } - fn group_end (&self) { self.dec_indent() } -} - - -#[cfg(target_arch="wasm32")] -impl AnyLogger for Logger { - type Owned = Self; - fn new(path:impl Into) -> Self { - let path = path.into(); - Self {path} - } - fn path (&self) -> &str { &self.path } - fn trace (&self, msg:impl Message) { console::trace_1 (&self.format(msg)) } - fn debug (&self, msg:impl Message) { console::debug_1 (&self.format(msg)) } - fn info (&self, msg:impl Message) { console::info_1 (&self.format(msg)) } - fn warning (&self, msg:impl Message) { console::warn_1 (&self.format(msg)) } - fn error (&self, msg:impl Message) { console::error_1 (&self.format(msg)) } - fn group_begin (&self, msg:impl Message) { console::group_1 (&self.format(msg)) } - fn group_end (&self) { console::group_end() } -} - - - -// =================== -// === Conversions === -// =================== - -impls!{ From + &From for Logger { |logger| Self::new(logger.path()) }} diff --git a/lib/rust/enso-logger/src/lib.rs b/lib/rust/enso-logger/src/lib.rs deleted file mode 100644 index 37e95d1c2b..0000000000 --- a/lib/rust/enso-logger/src/lib.rs +++ /dev/null @@ -1,235 +0,0 @@ -//! This crate contains implementation of logging interface. - -#![feature(cell_update)] - -#![deny(unconditional_recursion)] -#![warn(missing_copy_implementations)] -#![warn(missing_debug_implementations)] -#![warn(missing_docs)] -#![warn(trivial_casts)] -#![warn(trivial_numeric_casts)] -#![warn(unsafe_code)] -#![warn(unused_import_braces)] - -pub mod disabled; -pub mod enabled; - -use enso_prelude::*; - - - -// ============== -// === Message === -// ============== - -/// Message that can be logged. -pub trait Message { - /// Turns message into `&str` and passes it to input function. - fn withT>(&self, f:F) -> T; -} - -impl Message for &str { - fn withT>(&self, f:F) -> T { - f(self) - } -} - -implS, S:AsRef> Message for G { - fn withT>(&self, f:F) -> T { - f(self().as_ref()) - } -} - - - -// ================= -// === AnyLogger === -// ================= - -/// Interface common to all loggers. -pub trait AnyLogger { - /// Owned type of the logger. - type Owned; - - /// Creates a new logger. Path should be a unique identifier for this logger. - fn new(path:impl Into) -> Self::Owned; - - /// Path that is used as an unique identifier of this logger. - fn path(&self) -> &str; - - /// Creates a new logger with this logger as a parent. - fn sub(logger:impl AnyLogger, path:impl Into) -> Self::Owned { - let path = path.into(); - let super_path = logger.path(); - if super_path.is_empty() { Self::new(path) } - else { Self::new(iformat!("{super_path}.{path}")) } - } - - /// Creates a logger from AnyLogger. - fn from_logger(logger:impl AnyLogger) -> Self::Owned { - Self::new(logger.path()) - } - - /// Evaluates function `f` and visually groups all logs will occur during its execution. - fn group T>(&self, msg:impl Message, f:F) -> T { - self.group_begin(msg); - let out = f(); - self.group_end(); - out - } - - /// Log with stacktrace and info level verbosity. - fn trace(&self, _msg:impl Message) {} - - /// Log with debug level verbosity - fn debug(&self, _msg:impl Message) {} - - /// Log with info level verbosity. - fn info(&self, _msg:impl Message) {} - - /// Log with warning level verbosity. - fn warning(&self, _msg:impl Message) {} - - /// Log with error level verbosity. - fn error(&self, _msg:impl Message) {} - - /// Visually groups all logs between group_begin and group_end. - fn group_begin(&self, _msg:impl Message) {} - - /// Visually groups all logs between group_begin and group_end. - fn group_end(&self) {} -} - -impl AnyLogger for &T { - type Owned = T::Owned; - fn new (path:impl Into) -> Self::Owned { T::new(path) } - fn path (&self) -> &str { T::path(self) } - fn trace (&self, msg:impl Message) { T::trace (self,msg) } - fn debug (&self, msg:impl Message) { T::debug (self,msg) } - fn info (&self, msg:impl Message) { T::info (self,msg) } - fn warning (&self, msg:impl Message) { T::warning (self,msg) } - fn error (&self, msg:impl Message) { T::error (self,msg) } - fn group_begin (&self, msg:impl Message) { T::group_begin (self,msg) } - fn group_end (&self) { T::group_end (self) } -} - - - -// ============== -// === Macros === -// ============== - -/// Shortcut for `|| format!(..)`. -#[macro_export] -macro_rules! fmt { - ($($arg:tt)*) => (||(format!($($arg)*))) -} - -/// Evaluates expression and visually groups all logs will occur during its execution. -#[macro_export] -macro_rules! group { - ($logger:expr, $message:tt, {$($body:tt)*}) => {{ - let __logger = $logger.clone(); - __logger.group_begin(|| iformat!{$message}); - let out = {$($body)*}; - __logger.group_end(); - out - }}; -} - -/// Logs a message on on given level. -#[macro_export] -macro_rules! log_template { - ($method:ident $logger:expr, $message:tt $($rest:tt)*) => { - $crate::log_template_impl! {$method $logger, iformat!($message) $($rest)*} - }; -} - -/// Logs a message on on given level. -#[macro_export] -macro_rules! log_template_impl { - ($method:ident $logger:expr, $expr:expr) => {{ - $logger.$method(|| $expr); - }}; - ($method:ident $logger:expr, $expr:expr, $body:tt) => {{ - let __logger = $logger.clone(); - __logger.group_begin(|| $expr); - let out = $body; - __logger.group_end(); - out - }}; -} - -/// Logs an internal error with descriptive message. -#[macro_export] -macro_rules! with_internal_bug_message { ($f:ident $($args:tt)*) => { $crate::$f! { -"This is a bug. Please report it and and provide us with as much information as \ -possible at https://github.com/luna/enso/issues. Thank you!" -$($args)* -}};} - -/// Logs an internal error. -#[macro_export] -macro_rules! log_internal_bug_template { - ($($toks:tt)*) => { - $crate::with_internal_bug_message! { log_internal_bug_template_impl $($toks)* } - }; -} - -/// Logs an internal error. -#[macro_export] -macro_rules! log_internal_bug_template_impl { - ($note:tt $method:ident $logger:expr, $message:tt $($rest:tt)*) => { - $crate::log_template_impl! {$method $logger, - format!("Internal Error. {}\n\n{}",iformat!($message),$note) $($rest)* - } - }; -} - -/// Log with stacktrace and level:info. -#[macro_export] -macro_rules! trace { - ($($toks:tt)*) => { - $crate::log_template! {trace $($toks)*} - }; -} - -/// Log with level:debug -#[macro_export] -macro_rules! debug { - ($($toks:tt)*) => { - $crate::log_template! {debug $($toks)*} - }; -} - -/// Log with level:info. -#[macro_export] -macro_rules! info { - ($($toks:tt)*) => { - $crate::log_template! {info $($toks)*} - }; -} - -/// Log with level:warning. -#[macro_export] -macro_rules! warning { - ($($toks:tt)*) => { - $crate::log_template! {warning $($toks)*} - }; -} - -/// Log with level:error. -#[macro_export] -macro_rules! error { - ($($toks:tt)*) => { - $crate::log_template! {error $($toks)*} - }; -} - -/// Logs an internal warning. -#[macro_export] -macro_rules! internal_warning { - ($($toks:tt)*) => { - $crate::log_internal_bug_template! {warning $($toks)*} - }; -} diff --git a/lib/rust/enso-macro-utils/Cargo.toml b/lib/rust/enso-macro-utils/Cargo.toml deleted file mode 100644 index 8c2ee7246c..0000000000 --- a/lib/rust/enso-macro-utils/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "enso-macro-utils" -version = "0.1.0" -authors = ["Enso Team "] -edition = "2018" - -description = "Utilities for writing macros." -readme = "README.md" -homepage = "https://github.com/enso-org/enso/lib/rust/enso-macro-utils" -repository = "https://github.com/enso-org/enso" -license-file = "../../../LICENSE" - -keywords = ["macro", "utility"] -categories = ["development-tools::procedural-macro-helpers"] - -publish = true - -[lib] -crate-type = ["cdylib", "rlib"] - -[dependencies] -proc-macro2 = "1.0" -quote = "1.0" - -[dependencies.syn] -version = "1.0" -features = [ - 'extra-traits', - 'full', # for syn::ItemStruct - 'visit' -] - -[dev-dependencies] -wasm-bindgen-test = "0.2" diff --git a/lib/rust/enso-macro-utils/README.md b/lib/rust/enso-macro-utils/README.md deleted file mode 100644 index 493926f30a..0000000000 --- a/lib/rust/enso-macro-utils/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Macro Utils - -This crate provides some utilities useful for writing macros. diff --git a/lib/rust/enso-macro-utils/src/lib.rs b/lib/rust/enso-macro-utils/src/lib.rs deleted file mode 100644 index 746ac02cd5..0000000000 --- a/lib/rust/enso-macro-utils/src/lib.rs +++ /dev/null @@ -1,358 +0,0 @@ -//! A number of helper functions meant to be used in the procedural enso-shapely-macros -//! definitions. - -#![warn(missing_docs)] -#![feature(trait_alias)] - -use proc_macro2::TokenStream; -use proc_macro2::TokenTree; -use quote::quote; -use std::iter::FromIterator; -use syn::visit::Visit; -use syn::WhereClause; -use syn::WherePredicate; -use syn; - - - -// ===================== -// === Trait Aliases === -// ===================== - -pub trait Str = Into + AsRef; - - - -// ========================== -// === Token Stream Utils === -// ========================== - -/// Maps all the tokens in the stream using a given function. -pub fn map_tokens TokenTree> -(input:TokenStream, f:F) -> TokenStream { - let ret_iter = input.into_iter().map(f); - TokenStream::from_iter(ret_iter) -} - -/// Rewrites stream replacing each token with a sequence of tokens returned by -/// the given function. The groups (e.g. token tree within braces) are unpacked, -/// rewritten and repacked into groups -- the function is applied recursively. -pub fn rewrite_stream - TokenStream + Copy> -(input:TokenStream, f:F) -> TokenStream { - let mut ret = TokenStream::new(); - for token in input.into_iter() { - match token { - proc_macro2::TokenTree::Group(group) => { - let delim = group.delimiter(); - let span = group.span(); - let rewritten = rewrite_stream(group.stream(), f); - let mut new_group = proc_macro2::Group::new(delim,rewritten); - new_group.set_span(span); - let new_group = vec![TokenTree::from(new_group)]; - ret.extend(new_group.into_iter()) - } - _ => ret.extend(f(token)), - } - } - ret -} - - - -// =================== -// === Token Utils === -// =================== - -/// Is the given token an identifier matching to a given string? -pub fn matching_ident(token:&TokenTree, name:&str) -> bool { - match token { - TokenTree::Ident(ident) => *ident == name, - _ => false, - } -} - - - -// ============ -// === Repr === -// ============ - -/// Obtains text representation of given `ToTokens`-compatible input. -pub fn repr(t:&T) -> String { - quote!(#t).to_string() -} - - - -// =================== -// === Field Utils === -// =================== - -/// Collects all fields, named or not. -pub fn fields_list(fields:&syn::Fields) -> Vec<&syn::Field> { - match fields { - syn::Fields::Named (ref f) => f.named .iter().collect(), - syn::Fields::Unnamed(ref f) => f.unnamed.iter().collect(), - syn::Fields::Unit => Default::default(), - } -} - -/// Returns token that refers to the field. -/// -/// It is the field name for named field and field index for unnamed fields. -pub fn field_ident_token(field:&syn::Field, index:syn::Index) -> TokenStream { - match &field.ident { - Some(ident) => quote!(#ident), - None => quote!(#index), - } -} - -/// Returns names of the named fields. -pub fn field_names(fields:&syn::FieldsNamed) -> Vec<&syn::Ident> { - fields.named.iter().map(|field| { - field.ident.as_ref().expect("Impossible: no name on a named field.") - }).collect() -} - - - -// ================== -// === Path Utils === -// ================== - -/// Checks if a given `Path` consists of a single identifier same as given string. -pub fn path_matching_ident(path:&syn::Path, str:impl Str) -> bool { - path.get_ident().map_or(false, |ident| ident == str.as_ref()) -} - - - -// ====================== -// === Index Sequence === -// ====================== - -/// For given length, returns a sequence of Literals like `[0,1,2…]`. These are unsuffixed -/// usize literals, so e.g. can be used to identify the tuple unnamed fields. -pub fn index_sequence(len:usize) -> Vec { - (0..len).map(syn::Index::from).collect() -} - -/// For given length returns sequence of identifiers like `[field0,field1,…]`. -pub fn identifier_sequence(len:usize) -> Vec { - let format_field = |ix| quote::format_ident!("field{}",ix); - (0..len).map(format_field).collect() -} - - - -// ======================= -// === Type Path Utils === -// ======================= - -/// Obtain list of generic arguments on the path's segment. -pub fn path_segment_generic_args -(segment:&syn::PathSegment) -> Vec<&syn::GenericArgument> { - match segment.arguments { - syn::PathArguments::AngleBracketed(ref args) => - args.args.iter().collect(), - _ => - Vec::new(), - } -} - -/// Obtain list of generic arguments on the path's last segment. -/// -/// Empty, if path contains no segments. -pub fn ty_path_generic_args -(ty_path:&syn::TypePath) -> Vec<&syn::GenericArgument> { - ty_path.path.segments.last().map_or(Vec::new(), path_segment_generic_args) -} - -/// Obtain list of type arguments on the path's last segment. -pub fn ty_path_type_args -(ty_path:&syn::TypePath) -> Vec<&syn::Type> { - ty_path_generic_args(ty_path).iter().filter_map( |generic_arg| { - match generic_arg { - syn::GenericArgument::Type(t) => Some(t), - _ => None, - } - }).collect() -} - -/// Last type argument of the last segment on the type path. -pub fn last_type_arg(ty_path:&syn::TypePath) -> Option<&syn::GenericArgument> { - ty_path_generic_args(ty_path).last().copied() -} - - - -// ===================== -// === Collect Types === -// ===================== - -/// Visitor that accumulates all visited `syn::TypePath`. -#[derive(Default)] -pub struct TypeGatherer<'ast> { - /// Observed types accumulator. - pub types: Vec<&'ast syn::TypePath> -} - -impl<'ast> Visit<'ast> for TypeGatherer<'ast> { - fn visit_type_path(&mut self, node:&'ast syn::TypePath) { - self.types.push(node); - syn::visit::visit_type_path(self, node); - } -} - -/// All `TypePath`s in the given's `Type` subtree. -pub fn gather_all_types(node:&syn::Type) -> Vec<&syn::TypePath> { - let mut type_gather = TypeGatherer::default(); - type_gather.visit_type(node); - type_gather.types -} - -/// All text representations of `TypePath`s in the given's `Type` subtree. -pub fn gather_all_type_reprs(node:&syn::Type) -> Vec { - gather_all_types(node).iter().map(|t| repr(t)).collect() -} - - - -// ======================= -// === Type Dependency === -// ======================= - -/// Naive type equality test by comparing its representation with a string. -pub fn type_matches_repr(ty:&syn::Type, target_repr:&str) -> bool { - repr(ty) == target_repr -} - -/// Naive type equality test by comparing their text representations. -pub fn type_matches(ty:&syn::Type, target_param:&syn::GenericParam) -> bool { - type_matches_repr(ty, &repr(target_param)) -} - -/// Does type depends on the given type parameter. -pub fn type_depends_on(ty:&syn::Type, target_param:&syn::GenericParam) -> bool { - let target_param = repr(target_param); - let relevant_types = gather_all_types(ty); - relevant_types.iter().any(|ty| repr(ty) == target_param) -} - -/// Does enum variant depend on the given type parameter. -pub fn variant_depends_on -(var:&syn::Variant, target_param:&syn::GenericParam) -> bool { - var.fields.iter().any(|field| type_depends_on(&field.ty, target_param)) -} - - - -// =================== -// === WhereClause === -// =================== - -/// Creates a new where clause from provided sequence of where predicates. -pub fn new_where_clause(predicates:impl IntoIterator) -> WhereClause { - let predicates = syn::punctuated::Punctuated::from_iter(predicates); - WhereClause {where_token:Default::default(),predicates} -} - - - -// ============= -// === Tests === -// ============= - -#[cfg(test)] -mod tests { - use super::*; - use proc_macro2::TokenStream; - - fn parse(code:&str) -> T { - syn::parse_str(code).unwrap() - } - - #[test] - fn repr_round_trips() { - let program = "pub fn repr(t: &T) -> String {}"; - let tokens = parse::(program); - let quoted_program = repr(&tokens); - let tokens2 = parse::("ed_program); - // check only second round-trip, first is allowed to break whitespace - assert_eq!(repr(&tokens), repr(&tokens2)); - } - - #[test] - fn fields_list_test() { - let tuple_like = "struct Unnamed(i32, String, T);"; - let proper_struct = "struct Named{i: i32, s: String, t: T}"; - let expected_types = vec!["i32", "String", "T"]; - - fn assert_field_types(program:&str, expected_types:&[&str]) { - let tokens = parse::(program); - let fields = fields_list(&tokens.fields); - let types = fields.iter().map(|f| repr(&f.ty)); - assert_eq!(Vec::from_iter(types), expected_types); - } - - assert_field_types(tuple_like, &expected_types); - assert_field_types(proper_struct, &expected_types); - } - - #[test] - fn type_dependency() { - let param:syn::GenericParam = parse("T"); - let depends = |code| { - let ty:syn::Type = parse(code); - type_depends_on(&ty, ¶m) - }; - - // sample types that depend on `T` - let dependents = vec!{ - "T", - "Option", - "Pair", - "Pair", - "Pair", - "&T", - "&'t mut T", - }; - // sample types that do not depend on `T` - let independents = vec!{ - "Tt", - "Option", - "Pair", - "Pair", - "Pair", - "i32", - "&str", - }; - for dependent in dependents { - assert!(depends(dependent), "{} must depend on {}" - , repr(&dependent), repr(¶m)); - } - for independent in independents { - assert!(!depends(independent), "{} must not depend on {}" - , repr(&independent), repr(¶m)); - } - } - - #[test] - fn collecting_type_path_args() { - fn check(expected_type_args:Vec<&str>, ty_path:&str) { - let ty_path = parse(ty_path); - let args = super::ty_path_type_args(&ty_path); - assert_eq!(expected_type_args.len(), args.len()); - let zipped = expected_type_args.iter().zip(args.iter()); - for (expected,got) in zipped { - assert_eq!(expected, &repr(got)); - } - } - check(vec!["T"] , "std::Option"); - check(vec!["U"] , "std::Option"); - check(vec!["A", "B"], "Either"); - assert_eq!(super::last_type_arg(&parse("i32")), None); - assert_eq!(repr(&super::last_type_arg(&parse("Foo"))), "C"); - } -} diff --git a/lib/rust/enso-optics/Cargo.toml b/lib/rust/enso-optics/Cargo.toml deleted file mode 100644 index b86d36685d..0000000000 --- a/lib/rust/enso-optics/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "enso-optics" -version = "0.1.0" -authors = ["Enso Team "] -edition = "2018" - -description = "A library providing lenses and prisms." -readme = "README.md" -homepage = "https://github.com/enso-org/enso/lib/rust/enso-optics" -repository = "https://github.com/enso-org/enso" -license-file = "../../../LICENSE" - -[lib] -crate-type = ["cdylib", "rlib"] - -[features] - -[dependencies] -enso-prelude = { version = "0.1.0", path = "../enso-prelude" } diff --git a/lib/rust/enso-optics/README.md b/lib/rust/enso-optics/README.md deleted file mode 100644 index 1fb58a2e98..0000000000 --- a/lib/rust/enso-optics/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Enso Optics - -A library providing lenses and prisms. diff --git a/lib/rust/enso-optics/src/lib.rs b/lib/rust/enso-optics/src/lib.rs deleted file mode 100644 index 490c7273a6..0000000000 --- a/lib/rust/enso-optics/src/lib.rs +++ /dev/null @@ -1,540 +0,0 @@ -#![warn(unsafe_code)] -#![warn(missing_copy_implementations)] -#![warn(missing_debug_implementations)] -#![allow(non_snake_case)] -#![allow(non_camel_case_types)] -#![allow(dead_code)] -#![allow(unused_macros)] -#![allow(clippy::option_map_unit_fn)] - -use enso_prelude::*; - -// ================ -// === TypeList === -// ================ - -trait HList {} -impl HList for Nil {} -impl HList for Cons where Head:?Sized, Tail:?Sized {} - -struct Nil; -struct Cons(PhantomData2) where Head:?Sized, Tail:?Sized; - -// === Instances === - -impl -Cons { - pub fn new() -> Self { Self::default() } -} - -impl -Default for Cons { - fn default() -> Self { Self(default()) } -} - -// === Append === - -type Append = >::Result; -trait Appendable { type Result; } - -impl -Appendable for Nil { - type Result = Cons; -} - -impl> -Appendable for Cons { - type Result = Cons>; -} - -// ============= -// === Field === -// ============= - -type Field = >::Result; -trait HasField { type Result; } - -// ============== -// === Getter === -// ============== - -trait Getter: HasField { - fn get (& self) -> & Field; - fn get_mut (&mut self) -> &mut Field; -} - -trait OptGetter: HasField { - fn get (& self) -> Option <& Field>; - fn get_mut (&mut self) -> Option <&mut Field>; -} - -// ================ -// === Resolver === -// ================ - -// === FieldResolver === - -type NestedField = >::Result; -trait FieldResolver { type Result; } - -impl -FieldResolver for Nil { - type Result = T; -} - -impl -FieldResolver for Cons -where T: HasField, Tail: FieldResolver> { - type Result = NestedField, Tail>; -} - -// === Resolver === - -trait Resolver: FieldResolver { - fn resolve (t: & T) -> & NestedField; - fn resolve_mut (t: &mut T) -> &mut NestedField; -} - -trait OptResolver: FieldResolver { - fn resolve (t: & T) -> Option<& NestedField>; - fn resolve_mut (t: &mut T) -> Option<&mut NestedField>; -} - -impl Resolver for Nil { - fn resolve (t: & T) -> & NestedField { t } - fn resolve_mut (t: &mut T) -> &mut NestedField { t } -} - -impl OptResolver for Nil { - fn resolve (t: & T) -> Option<& NestedField> { Some(t) } - fn resolve_mut (t: &mut T) -> Option<&mut NestedField> { Some(t) } -} - -impl Resolver for Cons -where T: Getter, Tail: Resolver> { - fn resolve(t: &T) -> &NestedField { - let head = Getter::::get(t); - >>::resolve(head) - } - fn resolve_mut(t: &mut T) -> &mut NestedField { - let head = Getter::::get_mut(t); - >>::resolve_mut(head) - } -} - -impl OptResolver for Cons - where T: OptGetter, Tail: OptResolver> { - fn resolve(t: &T) -> Option<&NestedField> { - OptGetter::::get(t) - .and_then(|t| >>::resolve(t)) - } - fn resolve_mut(t: &mut T) -> Option<&mut NestedField> { - OptGetter::::get_mut(t) - .and_then(|t| >>::resolve_mut(t)) - } -} - -// ============ -// === Lens === -// ============ - -struct Lens (PhantomData3); -struct OptLens (PhantomData3); - -impl Copy for Lens {} -impl Clone for Lens { - fn clone(&self) -> Self { Lens::new() } -} - -impl Copy for OptLens {} -impl Clone for OptLens { - fn clone(&self) -> Self { OptLens::new() } -} - -impl OptLens { - pub fn resolve(self, t: &Src) -> Option<&NestedField> - where Path: OptResolver { - >::resolve(t) - } - pub fn resolve_mut(self, t: &mut Src) -> Option<&mut NestedField> - where Path: OptResolver { - >::resolve_mut(t) - } -} - -impl Lens { - pub fn resolve(self, t: &Src) -> &NestedField - where Path: Resolver { - >::resolve(&t) - } -} - -impl Lens { - pub fn new() -> Self { default() } -} - -impl Default for Lens { - fn default() -> Self { Self(default()) } -} - -impl OptLens { - pub fn new() -> Self { default() } -} - -impl Default for OptLens { - fn default() -> Self { Self(default()) } -} - -struct BoundLens<'t,Src,Tgt,Path> { - target: &'t Src, - lens: Lens, -} - -struct BoundLensMut<'t,Src,Tgt,Path> { - target: &'t mut Src, - lens: Lens, -} - -struct BoundOptLens<'t,Src,Tgt,Path> { - target: &'t Src, - lens: OptLens, -} - -struct BoundOptLensMut<'t,Src,Tgt,Path> { - target: &'t mut Src, - lens: OptLens, -} - -impl<'t,Src,Tgt,Path> BoundLens<'t,Src,Tgt,Path> { - pub fn new(target: &'t Src) -> Self { - let lens = Lens::new(); - Self { target, lens } - } - - pub fn read(&self) -> &NestedField - where Path: Resolver { - self.lens.resolve(self.target) - } -} - -impl<'t,Src,Tgt,Path> BoundOptLens<'t,Src,Tgt,Path> { - pub fn new(target: &'t Src) -> Self { - let lens = OptLens::new(); - Self { target, lens } - } - - pub fn read(&self) -> Option<&NestedField> - where Path: OptResolver { - self.lens.resolve(self.target) - } -} - -impl<'t,Src:Clone,Tgt,Path> BoundOptLens<'t,Src,Tgt,Path> { - pub fn write(&self, val: NestedField) - where for<'a> Path: OptResolver, - OptLens: Copy { - let mut a = (*self.target).clone(); - a.lens_mut().unsafe_repath::().set(val); - } -} - -impl<'t,Src,Tgt,Path> BoundOptLensMut<'t,Src,Tgt,Path> { - pub fn new(target: &'t mut Src) -> Self { - let lens = OptLens::new(); - Self { target, lens } - } - - pub fn get(&mut self) -> Option<&mut NestedField> - where Path: OptResolver { - self.lens.resolve_mut(self.target) - } - - pub fn set(&mut self, val: NestedField) - where Path: OptResolver { - let r = self.get(); - r.map(|s| *s = val); - } - - pub fn unsafe_repath(self) -> BoundOptLensMut<'t,Src,Tgt,Path2> { - BoundOptLensMut { - target: self.target, - lens: OptLens::new(), - } - } -} - -//////////////////////////////////////// -//////////////////////////////////////// -//////////////////////////////////////// - - -trait HasLens where Self:Sized { - fn lens(&self) -> BoundOptLens<'_, Self, Self, Nil> { - BoundOptLens::new(self) - } - fn lens_mut(&mut self) -> BoundOptLensMut<'_, Self, Self, Nil> { - BoundOptLensMut::new(self) - } -} -impl HasLens for T {} - -macro_rules! mk_lens_field_decl { -($struct_name:ident<$($param:ident),*>{$field_name:ident : $field_type:ty}) => { -paste::item! { - // struct FIELD_bar; - struct []; - - // impl HasField for Foo<> { - // type Result = Bar; - // } - impl<$($param),*> HasField<[]> for $struct_name<$($param),*> { - type Result = $field_type; - } -}}} - -macro_rules! mk_lenses_for { -($struct_name:ident<$($param:ident),*>{$field_name:ident : $field_type:ty}) => { -paste::item! { - - mk_lens_field_decl!($struct_name<$($param),*>{$field_name:$field_type}); - - // impl Getter for Foo { - // fn get(&self) -> &Field { - // &self.bar - // } - // fn get_mut(&mut self) -> &mut Field { - // &mut self.bar - // } - // } - impl<$($param),*> Getter<[]> for $struct_name<$($param),*> { - fn get(&self) -> &Field]> { - &self.$field_name - } - fn get_mut(&mut self) -> &mut Field]> { - &mut self.$field_name - } - } - - // impl OptGetter for Foo { - // fn get(&self) -> Option<&Field> { - // Some(&self.bar) - // } - // fn get_mut(&mut self) -> Option<&mut Field> { - // Some(&mut self.bar) - // } - // } - impl<$($param),*> OptGetter<[]> for $struct_name<$($param),*> { - fn get(&self) -> Option<&Field]>> { - Some(&self.$field_name) - } - fn get_mut(&mut self) - -> Option<&mut Field]>> { - Some(&mut self.$field_name) - } - } - - // impl<'lens_lifetime, LENS_BEGIN, LENS_NEW_PATH> - // BoundOptLensMut<'lens_lifetime, LENS_BEGIN, Foo, LENS_NEW_PATH> - // where LENS_NEW_PATH: Appendable { - // fn bar(self) - // -> BoundOptLensMut - // < 'lens_lifetime - // , LENS_BEGIN - // , Bar - // , Append - // > { - // BoundOptLensMut::new(self.target) - // } - // } - impl<'lens_lifetime, LENS_BEGIN, LENS_NEW_PATH> - BoundOptLensMut<'lens_lifetime, LENS_BEGIN, $struct_name, LENS_NEW_PATH> - where LENS_NEW_PATH: Appendable<[]> { - fn $field_name(self) - -> BoundOptLensMut - < 'lens_lifetime - , LENS_BEGIN - , Field<$struct_name - ,[]> - , Append<[] - , LENS_NEW_PATH> - > { - BoundOptLensMut::new(self.target) - } - } - - impl<'lens_lifetime, LENS_BEGIN, LENS_NEW_PATH> - BoundOptLens<'lens_lifetime, LENS_BEGIN, $struct_name, LENS_NEW_PATH> - where LENS_NEW_PATH: Appendable<[]> { - fn $field_name(self) - -> BoundOptLens - < 'lens_lifetime - , LENS_BEGIN - , Field<$struct_name - ,[]> - , Append<[] - , LENS_NEW_PATH> - > { - BoundOptLens::new(self.target) - } - } -}}; - -($struct_name:ident<$($param:ident),*> :: $cons_name:ident {$field_name:ident : $field_type:ty}) => { -paste::item! { - - mk_lens_field_decl!($struct_name<$($param),*>{$field_name:$field_type}); - - // impl OptGetter for Foo { - // fn get(&self) -> Option<&Field> { - // Some(&self.bar) - // } - // fn get_mut(&mut self) -> Option<&mut Field> { - // Some(&mut self.bar) - // } - // } - impl<$($param),*> OptGetter<[]> for $struct_name<$($param),*> { - fn get(&self) -> Option<&Field]>> { - match self { - $cons_name(ref $field_name) => Some($field_name), - _ => None - } - } - fn get_mut(&mut self) - -> Option<&mut Field]>> { - match self { - $cons_name(ref mut $field_name) => Some($field_name), - _ => None - } - } - } - - // impl<'lens_lifetime, LENS_BEGIN, LENS_NEW_PATH> - // BoundOptLensMut<'lens_lifetime, LENS_BEGIN, Foo, LENS_NEW_PATH> - // where LENS_NEW_PATH: Appendable { - // fn bar(self) - // -> BoundOptLensMut - // < 'lens_lifetime - // , LENS_BEGIN - // , Field> - // , Append - // > { - // BoundOptLensMut::new(self.target) - // } - // } - impl<'lens_lifetime, LENS_BEGIN, LENS_NEW_PATH, $($param),*> - BoundOptLensMut<'lens_lifetime, LENS_BEGIN, $struct_name<$($param),*>, LENS_NEW_PATH> - where LENS_NEW_PATH: Appendable<[]> { - fn $cons_name(self) - -> BoundOptLensMut - < 'lens_lifetime - , LENS_BEGIN - , Field<$struct_name<$($param),*>,[]> - , Append<[], LENS_NEW_PATH> - > { - BoundOptLensMut::new(self.target) - } - } - - impl<'lens_lifetime, LENS_BEGIN, LENS_NEW_PATH, $($param),*> - BoundOptLens<'lens_lifetime, LENS_BEGIN, $struct_name<$($param),*>, LENS_NEW_PATH> - where LENS_NEW_PATH: Appendable<[]> { - fn $cons_name(self) - -> BoundOptLens - < 'lens_lifetime - , LENS_BEGIN - , Field<$struct_name<$($param),*>,[]> - , Append<[], LENS_NEW_PATH> - > { - BoundOptLens::new(self.target) - } - } -}}} - -macro_rules! lens { - ($base:ident . $($seg:ident).*) => { - $base.lens().$($seg()).* - } -} - -macro_rules! lens_mut { - ($base:ident . $($seg:ident).*) => { - $base.lens_mut().$($seg()).* - } -} - - -mk_lenses_for!(Option::Some{val: T}); - - -#[cfg(test)] -mod tests { - use super::*; - - - - #[derive(Debug, PartialEq, Eq)] - struct Foo { - bar: Bar, - } - mk_lenses_for!(Foo<>{bar: Bar}); - - #[derive(Debug, PartialEq, Eq)] - struct Bar { - baz: Option, - } - mk_lenses_for!(Bar<>{baz: Option}); - - #[derive(Debug, PartialEq, Eq)] - struct Baz { - qux: Option, - } - mk_lenses_for!(Baz<>{qux: Option}); - - #[derive(Debug, PartialEq, Eq)] - struct Qux { - quxx: String, - } - mk_lenses_for!(Qux<>{quxx: String}); - - - #[test] - fn deeply_nested() { - let mut foo = Foo { - bar: Bar { - baz: Some(Baz { - qux: Some(Qux { - quxx: "nice".to_owned(), - }), - }), - }, - }; - - lens_mut!(foo.bar.baz.Some.qux.Some.quxx).set("Hello".into()); - assert_eq!(foo, Foo { - bar: Bar { - baz: Some(Baz { - qux: Some(Qux { - quxx: "Hello".to_owned(), - }), - }), - }, - }) - } -} - -pub fn main() { - let mut val: Option> = Some(Some(17)); - - val.lens_mut().Some().Some().set(10); - let lens1 = val.lens().Some().Some(); - let mut val2 = *lens1.target; - let lm = val2.lens_mut(); - let mut lm2 = BoundOptLensMut { - target: lm.target, - lens: lens1.lens, - }; - lm2.set(9); - println!("{:?}", val.lens_mut().Some().Some().get()); - println!("{:?}", val2.lens_mut().Some().Some().get()); -} diff --git a/lib/rust/enso-prelude/Cargo.toml b/lib/rust/enso-prelude/Cargo.toml deleted file mode 100644 index c7fe1bb9b9..0000000000 --- a/lib/rust/enso-prelude/Cargo.toml +++ /dev/null @@ -1,83 +0,0 @@ -[package] -name = "enso-prelude" -version = "0.1.0" -authors = ["Enso Team "] -edition = "2018" - -description = "An augmented standard library in the vein of Haskell's prelude." -readme = "README.md" -homepage = "https://github.com/enso-org/enso/lib/rust/enso-prelude" -repository = "https://github.com/enso-org/enso" -license-file = "../../../LICENSE" - -keywords = ["prelude", "standard-library"] -categories = ["algorithms"] - -publish = true - -[lib] -crate-type = ["cdylib", "rlib"] - -[dependencies] -enso-shapely = { version = "0.1.0" , path = "../enso-shapely/impl" } - -boolinator = "2.4.0" -derivative = "1.0.3" -derive_more = "0.99.2" -enclose = "1.1.8" -failure = "0.1.5" -ifmt = "0.2.0" -itertools = "0.8" -lazy_static = "1.4" -num = "0.2.0" -paste = "0.1" -shrinkwraprs = "0.3.0" -smallvec = "1.0.0" -weak-table = "0.2.3" -wasm-bindgen = { version = "=0.2.58" , features = ["nightly"] } - -# TODO: should be behind a flag, as the `nalgebra` package is pretty big and this crate would be -# also useful for projects which do not require `nalgebra`. -nalgebra = "0.21.1" - -[dependencies.web-sys] -version = "0.3.4" -features = [ - 'CanvasRenderingContext2d', - 'CssStyleDeclaration', - 'Document', - 'Element', - 'EventTarget', - 'KeyboardEvent', - 'HtmlCanvasElement', - 'HtmlCollection', - 'HtmlDivElement', - 'HtmlElement', - 'HtmlImageElement', - 'Location', - 'Node', - 'Url', - 'WebGlBuffer', - 'WebGlFramebuffer', - 'WebGlProgram', - 'WebGlRenderingContext', - 'WebGlShader', - 'WebGlSync', - 'WebGlTexture', - 'WebGl2RenderingContext', - 'WebGlUniformLocation', - 'WebGlUniformLocation', - 'WebGlVertexArrayObject', - 'Window', - 'console', - 'EventTarget', - 'Event', - 'MouseEvent', - 'Performance', - 'WheelEvent', - 'DomRect', - 'AddEventListenerOptions' -] - -[dev-dependencies] -wasm-bindgen-test = "0.2" diff --git a/lib/rust/enso-prelude/README.md b/lib/rust/enso-prelude/README.md deleted file mode 100644 index 9b2283c597..0000000000 --- a/lib/rust/enso-prelude/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Enso Prelude - -The Enso prelude is a library in the style of the Haskell prelude, pulling in a -number of useful foundational features for writing Rust code in the -[Enso](https://github.com/enso-org/enso) project. diff --git a/lib/rust/enso-prelude/src/clone.rs b/lib/rust/enso-prelude/src/clone.rs deleted file mode 100644 index 2653fa8793..0000000000 --- a/lib/rust/enso-prelude/src/clone.rs +++ /dev/null @@ -1,117 +0,0 @@ - -use crate::*; -pub use enso_shapely::CloneRef; - - - -// ================ -// === CloneRef === -// ================ - -/// Clone for internal-mutable structures. This trait can be implemented only if mutating one -/// structure will be reflected in all of its clones. Please note that it does not mean that all the -/// fields needs to provide internal mutability as well. For example, a structure can remember it's -/// creation time and store it as `f32`. As long as it cannot be mutated, the structure can -/// implement `CloneRef`. In order to guide the auto-deriving mechanism, it is advised to wrap all -/// immutable fields in the `Immutable` newtype. -pub trait CloneRef: Sized { - fn clone_ref(&self) -> Self; -} - - -// === Macros === - -#[macro_export] -macro_rules! impl_clone_ref_as_clone { - ([$($bounds:tt)*] $($toks:tt)*) => { - impl <$($bounds)*> CloneRef for $($toks)* { - fn clone_ref(&self) -> Self { - self.clone() - } - } - - impl <$($bounds)*> From<&$($toks)*> for $($toks)* { - fn from(t:&$($toks)*) -> Self { - t.clone_ref() - } - } - }; - - ($($toks:tt)*) => { - impl CloneRef for $($toks)* { - fn clone_ref(&self) -> Self { - self.clone() - } - } - - impl From<&$($toks)*> for $($toks)* { - fn from(t:&$($toks)*) -> Self { - t.clone_ref() - } - } - }; -} - -#[macro_export] -macro_rules! impl_clone_ref_as_clone_no_from { - ([$($bounds:tt)*] $($toks:tt)*) => { - impl <$($bounds)*> CloneRef for $($toks)* { - fn clone_ref(&self) -> Self { - self.clone() - } - } - }; - - ($($toks:tt)*) => { - impl CloneRef for $($toks)* { - fn clone_ref(&self) -> Self { - self.clone() - } - } - }; -} - - -// === Prim Impls === - -impl_clone_ref_as_clone_no_from!(()); -impl_clone_ref_as_clone_no_from!(f32); -impl_clone_ref_as_clone_no_from!(f64); -impl_clone_ref_as_clone_no_from!(i32); -impl_clone_ref_as_clone_no_from!(i64); -impl_clone_ref_as_clone_no_from!(usize); -impl_clone_ref_as_clone_no_from!([T] PhantomData); -impl_clone_ref_as_clone_no_from!([T:?Sized] Rc); -impl_clone_ref_as_clone_no_from!([T:?Sized] Weak); - -impl_clone_ref_as_clone_no_from!(wasm_bindgen::JsValue); -impl_clone_ref_as_clone_no_from!(web_sys::HtmlDivElement); -impl_clone_ref_as_clone_no_from!(web_sys::HtmlElement); -impl_clone_ref_as_clone_no_from!(web_sys::Performance); -impl_clone_ref_as_clone_no_from!(web_sys::WebGl2RenderingContext); -impl_clone_ref_as_clone_no_from!(web_sys::HtmlCanvasElement); -impl_clone_ref_as_clone_no_from!(web_sys::EventTarget); - - -// === Option === - -/// Trait for types that can be internally cloned using `CloneRef`, like `Option<&T>`. -#[allow(missing_docs)] -pub trait ClonedRef { - type Output; - fn cloned_ref(&self) -> Self::Output; -} - -impl ClonedRef for Option<&T> { - type Output = Option; - fn cloned_ref(&self) -> Self::Output { - self.map(|t| t.clone_ref()) - } -} - -impl ClonedRef for Option<&mut T> { - type Output = Option; - fn cloned_ref(&self) -> Self::Output { - self.as_ref().map(|t| t.clone_ref()) - } -} diff --git a/lib/rust/enso-prelude/src/collections.rs b/lib/rust/enso-prelude/src/collections.rs deleted file mode 100644 index 01a70d4b1e..0000000000 --- a/lib/rust/enso-prelude/src/collections.rs +++ /dev/null @@ -1,6 +0,0 @@ -//! This module exports collections which are popular enough to be available everywhere. - -pub use smallvec::SmallVec; -pub use std::collections::BTreeMap; -pub use std::collections::HashMap; -pub use std::collections::HashSet; diff --git a/lib/rust/enso-prelude/src/data.rs b/lib/rust/enso-prelude/src/data.rs deleted file mode 100644 index ba5aacf5b2..0000000000 --- a/lib/rust/enso-prelude/src/data.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! Generic data types and utilities. - -pub mod at_least_one_of_two; -pub mod monoid; -pub mod non_empty_vec; -pub mod semigroup; - -pub use at_least_one_of_two::*; -pub use monoid::*; -pub use non_empty_vec::*; -pub use semigroup::*; diff --git a/lib/rust/enso-prelude/src/data/at_least_one_of_two.rs b/lib/rust/enso-prelude/src/data/at_least_one_of_two.rs deleted file mode 100644 index 49f59bcf88..0000000000 --- a/lib/rust/enso-prelude/src/data/at_least_one_of_two.rs +++ /dev/null @@ -1,55 +0,0 @@ -//! Definition of `AtLeastOneOfTwo`. - - - -// ======================= -// === AtLeastOneOfTwo === -// ======================= - -/// A struct similar to `Option` and `Either`. It can contain the first value, or the second value, -/// or both of them at the same time. -#[derive(Debug,Clone,Copy)] -#[allow(missing_docs)] -pub enum AtLeastOneOfTwo { - First(T1), - Second(T2), - Both(T1,T2) -} - -impl AtLeastOneOfTwo { - /// Checks whether the values are equal. - pub fn same(&self) -> bool { - match self { - Self::Both(t1,t2) => t1 == t2, - _ => false - } - } -} - -impl AtLeastOneOfTwo { - /// Extracts the first value if exists. - pub fn first(&self) -> Option<&T1> { - match self { - Self::Both(t1,_) => Some(t1), - Self::First(t1) => Some(t1), - _ => None - } - } - - /// Extracts the second value if exists. - pub fn second(&self) -> Option<&T2> { - match self { - Self::Both(_,t2) => Some(t2), - Self::Second(t2) => Some(t2), - _ => None - } - } - - /// Extracts both of the value if exist. - pub fn both(&self) -> Option<(&T1,&T2)> { - match self { - Self::Both(t1,t2) => Some((t1,t2)), - _ => None - } - } -} diff --git a/lib/rust/enso-prelude/src/data/monoid.rs b/lib/rust/enso-prelude/src/data/monoid.rs deleted file mode 100644 index ad61b055b4..0000000000 --- a/lib/rust/enso-prelude/src/data/monoid.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! A class for monoids (types with an associative binary operation that has an identity) with -//! various general-purpose instances. - -use super::semigroup::Semigroup; - - - -// =============== -// === Monoid ==== -// =============== - -/// Mutable Monoid definition. -pub trait Monoid : Default + Semigroup { - /// Repeat a value n times. Given that this works on a Monoid it will not fail if you request 0 - /// or fewer repetitions. - fn times_mut(&mut self, n:usize) { - if n == 0 { - *self = Default::default() - } else { - let val = self.clone(); - for _ in 0..n-1 { - self.concat_mut(&val) - } - } - } - - fn times(&self, n:usize) -> Self { - std::iter::repeat(self).take(n).fold(Default::default(),|l,r| l.concat_ref(r)) - } -} - - -// === Default Impls === - -impl Monoid for T where T : Default + Semigroup {} - - - -// ============= -// === Tests === -// ============= - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn option() { - let vec_nop : Vec = vec![]; - let vec_1_2 : Vec = vec![1,2]; - let vec_1_2_times_3 : Vec = vec![1,2,1,2,1,2]; - assert_eq!(vec_1_2.times(0) , vec_nop); - assert_eq!(vec_1_2.times(1) , vec_1_2); - assert_eq!(vec_1_2.times(3) , vec_1_2_times_3); - } -} - - -// TODO: Think what to do with this. It would not be needed if tuples implement Iter. Alternatively -// we could immplement own tuple type. - -//trait Foldable { -// type Item : Monoid; -// fn fold(self) -> Self::Item; -//} -// -// -// -//macro_rules! replace { -// ($a:tt,$b:tt) => {$b}; -//} -// -// -//macro_rules! define_foldable_for_tuple { -// (0$(,$num:tt)*) => { -// impl Foldable for (T,$(replace!{$num,T}),*) { -// type Item = T; -// fn fold(self) -> Self::Item { -// self.0$(.concat(self.$num))* -// } -// } -// -// impl Foldable for &(T,$(replace!{$num,T}),*) { -// type Item = T; -// fn fold(self) -> Self::Item { -// self.0.clone()$(.concat(&self.$num))* -// } -// } -// }; -//} -// -//define_foldable_for_tuple![0]; -//define_foldable_for_tuple![0,1]; -//define_foldable_for_tuple![0,1,2]; -//define_foldable_for_tuple![0,1,2,3]; -//define_foldable_for_tuple![0,1,2,3,4]; -//define_foldable_for_tuple![0,1,2,3,4,5]; -//define_foldable_for_tuple![0,1,2,3,4,5,6]; -//define_foldable_for_tuple![0,1,2,3,4,5,6,7]; -//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8]; -//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9]; -//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10]; -//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10,11]; -//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10,11,12]; -//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10,11,12,13]; -//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]; -//define_foldable_for_tuple![0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; diff --git a/lib/rust/enso-prelude/src/data/non_empty_vec.rs b/lib/rust/enso-prelude/src/data/non_empty_vec.rs deleted file mode 100644 index 553f7946f5..0000000000 --- a/lib/rust/enso-prelude/src/data/non_empty_vec.rs +++ /dev/null @@ -1,303 +0,0 @@ -//! This file contains an implementation of Vec that can't be empty. - -use crate::*; - -use std::vec::Drain; -use std::vec::Splice; -use std::ops::Bound; - - -// =================== -// === NonEmptyVec === -// =================== - -/// A version of [`std::vec::Vec`] that can't be empty. -#[allow(missing_docs)] -#[derive(Clone,Debug,PartialEq)] -pub struct NonEmptyVec { - elems: Vec -} - -impl Deref for NonEmptyVec { - type Target = Vec; - - fn deref(&self) -> &Self::Target { - &self.elems - } -} - -impl NonEmptyVec { - /// Construct a new non-empty vector. - /// - /// The vector will not allocate more than the space required to contain `first` and `rest`. - /// - /// # Examples - /// - /// ``` - /// #![allow(unused_mut)] - /// use enso_prelude::NonEmptyVec; - /// let mut vec: NonEmptyVec = NonEmptyVec::new(0,vec![]); - /// ``` - pub fn new(first:T, rest:Vec) -> NonEmptyVec { - let mut elems = vec![first]; - elems.extend(rest); - NonEmptyVec{elems} - } - - /// Construct a `NonEmptyVec` containing a single element. - /// - /// # Examples - /// - /// ``` - /// use enso_prelude::NonEmptyVec; - /// let vec = NonEmptyVec::singleton(0); - /// assert_eq!(vec.get(0),Some(&0)); - /// assert_eq!(vec.len(),1); - /// ``` - pub fn singleton(first:T) -> NonEmptyVec { - NonEmptyVec::new(first,vec![]) - } - - /// Construct a new, `NonEmptyVec` containing the provided element and with the provided - /// `capacity`. - /// - /// If `capacity` is 0, then the vector will be allocated with capacity for the provided `first` - /// element. The vector will be able to hold exactly `capacity` elements without reallocating. - /// - /// It is important to note that although the returned vector has the *capacity* specified, the - /// vector will have a length of 1. - /// - /// # Panics - /// - /// Panics if `capacity` is not > 0. - /// - /// # Examples - /// - /// ``` - /// use enso_prelude::NonEmptyVec; - /// let mut vec = NonEmptyVec::with_capacity(0, 10); - /// - /// // The vector contains one item, even though it has capacity for more - /// assert_eq!(vec.len(), 1); - /// - /// // These are all done without reallocating... - /// for i in 1..10 { - /// vec.push(i); - /// } - /// - /// // ...but this may make the vector reallocate - /// vec.push(11); - /// ``` - pub fn with_capacity(first:T, capacity:usize) -> NonEmptyVec { - if capacity == 0 { - panic!("Capacity must be greater than zero for a NonEmptyVec."); - } - let mut elems = Vec::with_capacity(capacity); - elems.push(first); - NonEmptyVec{elems} - } - - /// Reserve capacity for at least `additional` more elements to be inserted in the given - /// `Vec`. - /// - /// The collection may reserve more space to avoid frequent reallocations. After calling - /// `reserve`, capacity will be greater than or equal to `self.len() + additional`. Does nothing - /// if capacity is already sufficient. - /// - /// # Panics - /// - /// Panics if the new capacity overflows `usize`. - /// - /// # Examples - /// - /// ``` - /// use enso_prelude::NonEmptyVec; - /// let mut vec = NonEmptyVec::new(0,vec![]); - /// vec.reserve(10); - /// assert!(vec.capacity() >= 11); - /// ``` - pub fn reserve(&mut self, additional:usize) { - self.elems.reserve(additional); - } - - /// Shrinks the capacity of the `NonEmotyVec` as much as possible. - /// - /// It will drop down as close as possible to the length, but the allocator may still inform the - /// vector that there is space for a few more elements. - /// - /// # Examples - /// - /// ``` - /// use enso_prelude::NonEmptyVec; - /// let mut vec = NonEmptyVec::with_capacity(0, 10); - /// assert_eq!(vec.capacity(),10); - /// vec.shrink_to_fit(); - /// assert!(vec.capacity() < 10); - /// ``` - pub fn shrink_to_fit(&mut self) { - self.elems.shrink_to_fit(); - } - - /// Append an element to the back of a collection. - /// - /// # Panics - /// - /// Panics if the number of elements in the vector overflows a `usize`. - /// - /// # Examples - /// - /// ``` - /// use enso_prelude::NonEmptyVec; - /// let mut vec = NonEmptyVec::new(0,vec![1,2]); - /// vec.push(3); - /// assert_eq!(vec.len(),4); - /// ``` - pub fn push(&mut self, value:T) { - self.elems.push(value) - } - - /// Remove an element from the back of the collection, returning it. - /// - /// Will not pop any item if there is only one item left in the vector. - /// - /// # Examples - /// - /// ``` - /// use enso_prelude::NonEmptyVec; - /// let mut vec = NonEmptyVec::new(0,vec![1]); - /// assert!(vec.pop().is_some()); - /// assert!(vec.pop().is_none()); - /// assert_eq!(vec.len(),1); - /// ``` - pub fn pop(&mut self) -> Option { - (self.len() > 1).and_option_from(||self.elems.pop()) - } - - /// Obtain a mutable reference to teh element in the vector at the specified `index`. - /// - /// # Examples - /// - /// ``` - /// use enso_prelude::NonEmptyVec; - /// let mut vec = NonEmptyVec::new(0,vec![1,2]); - /// let reference = vec.get_mut(0); - /// assert!(reference.is_some()); - /// assert_eq!(*reference.unwrap(),0); - /// ``` - pub fn get_mut(&mut self, index:usize) -> Option<&mut T> { - self.elems.get_mut(index) - } - - /// Obtain an immutable reference to the head of the `NonEmptyVec`. - /// - /// # Examples - /// - /// ``` - /// use enso_prelude::NonEmptyVec; - /// let vec = NonEmptyVec::new(0,vec![1,2]); - /// assert_eq!(*vec.first(), 0); - /// ``` - pub fn first(&self) -> &T { - &self.elems.first().expect("The NonEmptyVec always has an item in it.") - } - - /// Obtain a mutable reference to the head of the `NonEmptyVec`. - /// - /// # Examples - /// - /// ``` - /// use enso_prelude::NonEmptyVec; - /// let mut vec = NonEmptyVec::new(0,vec![1,2]); - /// assert_eq!(*vec.first_mut(), 0); - /// ``` - pub fn first_mut(&mut self) -> &mut T { - self.elems.first_mut().expect("The NonEmptyVec always has an item in it.") - } - - /// Obtain an immutable reference to the last element in the `NonEmptyVec`. - /// - /// # Examples - /// - /// ``` - /// use enso_prelude::NonEmptyVec; - /// let vec = NonEmptyVec::new(0,vec![1,2]); - /// assert_eq!(*vec.last(),2) - /// ``` - pub fn last(&self) -> &T { - self.get(self.len() - 1).expect("There is always one element in a NonEmptyVec.") - } - - /// Obtain a mutable reference to the last element in the `NonEmptyVec`. - /// - /// # Examples - /// - /// ``` - /// use enso_prelude::NonEmptyVec; - /// let mut vec = NonEmptyVec::new(0,vec![1,2]); - /// assert_eq!(*vec.last_mut(),2) - /// ``` - pub fn last_mut(&mut self) -> &mut T { - self.get_mut(self.len() - 1).expect("There is always one element in a NonEmptyVec.") - } - - /// Create a draining iterator that removes the specified range in the vector and yields the - /// removed items. - /// - /// It will never remove the root element of the vector. - /// - /// # Panics - /// - /// Panics if the starting point is greater than the end point or if the end point is greater - /// than the length of the vector. - /// - /// # Examples - /// - /// ``` - /// use enso_prelude::NonEmptyVec; - /// let mut vec = NonEmptyVec::new(0,vec![1,2,3,4,5]); - /// let drained:Vec = vec.drain(1..=5).collect(); - /// assert_eq!(drained,[1,2,3,4,5]) - /// ``` - pub fn drain(&mut self, range:R) -> Drain where R:RangeBounds { - if range.contains(&0) { - match range.end_bound() { - Bound::Included(n) => self.elems.drain(1..=*n), - Bound::Excluded(n) => self.elems.drain(1..*n), - Bound::Unbounded => self.elems.drain(1..) - } - } else { - self.elems.drain(range) - } - } - - /// Creates a splicing iterator that replaces the specified range in the vector with the given 4 - /// `replace_with` iterator and yields the removed items. - /// - /// `replace_with` does not need to be the same length as range. The element range is removed - /// even if the iterator is not consumed until the end. - /// - /// It is unspecified how many elements are removed from the vector if the Splice value is leaked. - /// - /// The input iterator replace_with is only consumed when the Splice value is dropped. - /// - /// # Panics - /// - /// Panics if the starting point is greater than the end point or if the end point is greater - /// than the length of the vector. - /// - /// # Examples - /// - /// ``` - /// use enso_prelude::NonEmptyVec; - /// let mut vec = NonEmptyVec::new(0,vec![1,2,3,4,5]); - /// let replacements = [10,20,30,40]; - /// let yielded:Vec<_> = vec.splice(..2,replacements.iter().cloned()).collect(); - /// assert_eq!(vec.as_slice(),&[10,20,30,40,2,3,4,5]); - /// assert_eq!(yielded,&[0,1]) - /// ``` - pub fn splice(&mut self, range:R, replace_with:I) -> Splice<::IntoIter> - where I: IntoIterator, - R: RangeBounds { - self.elems.splice(range,replace_with) - } -} diff --git a/lib/rust/enso-prelude/src/data/semigroup.rs b/lib/rust/enso-prelude/src/data/semigroup.rs deleted file mode 100644 index 3055a26f12..0000000000 --- a/lib/rust/enso-prelude/src/data/semigroup.rs +++ /dev/null @@ -1,143 +0,0 @@ -//! In mathematics, a semigroup is an algebraic structure consisting of a set together with an -//! associative binary operation. A semigroup generalizes a monoid in that there might not exist an -//! identity element. It also (originally) generalized a group (a monoid with all inverses) to a -//! type where every element did not have to have an inverse, thus the name semigroup. - -use std::collections::HashMap; -use std::hash::BuildHasher; -use std::hash::Hash; -use std::iter::Extend; - - - -// ================= -// === Semigroup === -// ================= - -/// Mutable Semigroup definition. Impls should satisfy the associativity law: -/// `x.concat(y.concat(z)) = x.concat(y).concat(z)`, in symbolic form: -/// `x <> (y <> z) = (x <> y) <> z` -pub trait PartialSemigroup : Clone { - /// An associative operation. - fn concat_mut(&mut self, other:T); - - /// An associative operation. - fn concat_ref(&self, other:T) -> Self where Self:Clone { - self.clone().concat(other) - } - - /// An associative operation. - fn concat(mut self, other:T) -> Self { - self.concat_mut(other); - self - } -} - -impl Semigroup for T where T : PartialSemigroup + for<'t> PartialSemigroup<&'t T> {} -pub trait Semigroup : PartialSemigroup + for<'t> PartialSemigroup<&'t Self> { - fn partial_times_mut(&mut self, n:usize) { - let val = self.clone(); - for _ in 0..n-1 { - self.concat_mut(&val) - } - } - - fn partial_times(mut self, n:usize) -> Self { - self.partial_times_mut(n); - self - } -} - - - -// ==================== -// === Stdlib Impls === -// ==================== - -// === Option === - -impl PartialSemigroup<&Option> for Option { - fn concat_mut(&mut self, other:&Self) { - if let Some(r) = other { - match self { - None => *self = Some(r.clone()), - Some(l) => l.concat_mut(r) - } - } - } -} - -impl PartialSemigroup> for Option { - fn concat_mut(&mut self, other:Self) { - if let Some(r) = other { - match self { - None => *self = Some(r), - Some(l) => l.concat_mut(r) - } - } - } -} - - -// === HashMap === - -impl PartialSemigroup<&HashMap> for HashMap -where K : Eq + Hash + Clone, - V : Semigroup, - S : Clone + BuildHasher { - fn concat_mut(&mut self, other:&Self) { - for (key,new_val) in other { - let key = key.clone(); - self.entry(key) - .and_modify(|val| val.concat_mut(new_val)) - .or_insert_with(|| new_val.clone()); - } - } -} - -impl PartialSemigroup> for HashMap - where K : Eq + Hash + Clone, - V : Semigroup, - S : Clone + BuildHasher { - fn concat_mut(&mut self, other:Self) { - for (key,new_val) in other { - self.entry(key) - .and_modify(|val| val.concat_mut(&new_val)) - .or_insert(new_val); - } - } -} - - -// === Vec === - -impl PartialSemigroup<&Vec> for Vec { - fn concat_mut(&mut self, other:&Self) { - self.extend(other.iter().cloned()) - } -} - -impl PartialSemigroup> for Vec { - fn concat_mut(&mut self, other:Self) { - self.extend(other.into_iter()) - } -} - - - -// ============= -// === Tests === -// ============= - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn option() { - assert_eq!(None::>.concat(&None) , None); - assert_eq!(Some(vec![1]).concat(&None) , Some(vec![1])); - assert_eq!(None.concat(&Some(vec![1])) , Some(vec![1])); - assert_eq!(Some(vec![1]).concat(&Some(vec![2])) , Some(vec![1,2])); - } -} diff --git a/lib/rust/enso-prelude/src/lib.rs b/lib/rust/enso-prelude/src/lib.rs deleted file mode 100644 index f0f80f0411..0000000000 --- a/lib/rust/enso-prelude/src/lib.rs +++ /dev/null @@ -1,353 +0,0 @@ -//! This module re-exports a lot of useful stuff. It is not meant to be used -//! by libraries, but it is definitely usefull for bigger projects. It also -//! defines several aliases and utils which may find their place in new -//! libraries in the future. - -#![feature(specialization)] -#![feature(test)] -#![feature(trait_alias)] -#![warn(missing_copy_implementations)] -#![warn(missing_debug_implementations)] -#![warn(unsafe_code)] - -mod clone; -mod collections; -mod data; -mod macros; -mod option; -mod phantom; -mod reference; -mod std_reexports; -mod string; -mod tp; -mod vec; -mod wrapper; - -pub use clone::*; -pub use collections::*; -pub use data::*; -pub use macros::*; -pub use option::*; -pub use phantom::*; -pub use reference::*; -pub use std_reexports::*; -pub use string::*; -pub use tp::*; -pub use vec::*; -pub use wrapper::*; - -pub use boolinator::Boolinator; -pub use derivative::Derivative; -pub use derive_more::*; -pub use enclose::enclose; -pub use failure::Fail; -pub use ifmt::*; -pub use itertools::Itertools; -pub use lazy_static::lazy_static; -pub use num::Num; -pub use paste; -pub use shrinkwraprs::Shrinkwrap; -pub use weak_table::traits::WeakElement; -pub use weak_table::traits::WeakKey; -pub use weak_table::WeakKeyHashMap; -pub use weak_table::WeakValueHashMap; -pub use weak_table; - -use std::cell::UnsafeCell; - - - -// ================= -// === Immutable === -// ================= - -/// A zero-overhead newtype which provides immutable access to its content. Of course this does not -/// apply to internal mutability of the wrapped data. A good use case of this structure is when you -/// want to pass an ownership to a structure, allow access all its public fields, but do not allow -/// their modification. -#[derive(Clone,Copy,Default)] -pub struct Immutable { - data : T -} - -/// Constructor of the `Immutable` struct. -#[allow(non_snake_case)] -pub fn Immutable(data:T) -> Immutable { - Immutable {data} -} - -impl Debug for Immutable { - fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.data.fmt(f) - } -} - -impl Display for Immutable { - fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.data.fmt(f) - } -} - -impl CloneRef for Immutable { - fn clone_ref(&self) -> Self { - Self {data:self.data.clone()} - } -} - -impl AsRef for Immutable { - fn as_ref(&self) -> &T { - &self.data - } -} - -impl std::borrow::Borrow for Immutable { - fn borrow(&self) -> &T { - &self.data - } -} - -impl Deref for Immutable { - type Target = T; - fn deref(&self) -> &Self::Target { - &self.data - } -} - - - -// ============== -// === ToImpl === -// ============== - -/// Provides method `to`, which is just like `into` but allows fo superfish syntax. -pub trait ToImpl: Sized { - fn to

(self) -> P where Self:Into

{ - self.into() - } -} -impl ToImpl for T {} - -// TODO -// This impl should be hidden behind a flag. Not everybody using prelude want to import nalgebra. -impl TypeDisplay for nalgebra::Matrix -where T:nalgebra::Scalar, R:nalgebra::DimName, C:nalgebra::DimName { - fn type_display() -> String { - let cols = ::dim(); - let rows = ::dim(); - let item = type_name::(); - match cols { - 1 => format!("Vector{}<{}>" , rows, item), - _ => format!("Matrix{}x{}<{}>" , rows, cols, item) - } - } -} - -#[macro_export] -macro_rules! clone_boxed { - ( $name:ident ) => { paste::item! { - #[allow(missing_docs)] - pub trait [] { - fn clone_boxed(&self) -> Box; - } - - impl [] for T { - fn clone_boxed(&self) -> Box { - Box::new(self.clone()) - } - } - - impl Clone for Box { - fn clone(&self) -> Self { - self.clone_boxed() - } - } - }} -} - -/// Alias for `for<'t> &'t Self : Into`. -pub trait RefInto = where for<'t> &'t Self : Into; - - - -// ================= -// === CloneCell === -// ================= - -#[derive(Debug)] -pub struct CloneCell { - data : UnsafeCell -} - -impl CloneCell { - pub fn new(elem:T) -> CloneCell { - CloneCell { data:UnsafeCell::new(elem) } - } - - #[allow(unsafe_code)] - pub fn get(&self) -> T where T:Clone { - unsafe {(*self.data.get()).clone()} - } - - #[allow(unsafe_code)] - pub fn set(&self, elem:T) { - unsafe { *self.data.get() = elem; } - } - - #[allow(unsafe_code)] - pub fn take(&self) -> T where T:Default { - let ptr:&mut T = unsafe { &mut *self.data.get() }; - std::mem::take(ptr) - } -} - -impl Clone for CloneCell { - fn clone(&self) -> Self { - Self::new(self.get()) - } -} - -impl Default for CloneCell { - fn default() -> Self { - Self::new(default()) - } -} - - - -// ================= -// === CloneCell === -// ================= - -#[derive(Debug)] -pub struct CloneRefCell { - data : UnsafeCell -} - -impl CloneRefCell { - pub fn new(elem:T) -> CloneRefCell { - CloneRefCell { data:UnsafeCell::new(elem) } - } - - #[allow(unsafe_code)] - pub fn get(&self) -> T where T:CloneRef { - unsafe {(*self.data.get()).clone_ref()} - } - - #[allow(unsafe_code)] - pub fn set(&self, elem:T) { - unsafe { *self.data.get() = elem; } - } - - #[allow(unsafe_code)] - pub fn take(&self) -> T where T:Default { - let ptr:&mut T = unsafe { &mut *self.data.get() }; - std::mem::take(ptr) - } -} - -impl Clone for CloneRefCell { - fn clone(&self) -> Self { - Self::new(self.get()) - } -} - -impl CloneRef for CloneRefCell { - fn clone_ref(&self) -> Self { - Self::new(self.get()) - } -} - -impl Default for CloneRefCell { - fn default() -> Self { - Self::new(default()) - } -} - - - -// ================================ -// === RefCell> Utils === -// ================================ - -pub trait RefcellOptionOps { - fn clear(&self); - fn set(&self, val:T); - fn set_if_none(&self, val:T); -} - -impl RefcellOptionOps for RefCell> { - fn clear(&self) { - *self.borrow_mut() = None; - } - - fn set(&self, val:T) { - *self.borrow_mut() = Some(val); - } - - fn set_if_none(&self, val:T) { - let mut ptr = self.borrow_mut(); - if ptr.is_some() { panic!("The value was already set.") } - *ptr = Some(val) - } -} - - - -// ================================ -// === Strong / Weak References === -// ================================ - -/// Abstraction for a strong reference like `Rc` or newtypes over it. -pub trait StrongRef : CloneRef { - /// Downgraded reference type. - type WeakRef : WeakRef; - /// Creates a new weak reference of this allocation. - fn downgrade(&self) -> Self::WeakRef; -} - -/// Abstraction for a weak reference like `Weak` or newtypes over it. -pub trait WeakRef : CloneRef { - /// Upgraded reference type. - type StrongRef : StrongRef; - /// Attempts to upgrade the weak referenc to a strong one, delaying dropping of the inner value - /// if successful. - fn upgrade(&self) -> Option; -} - -impl StrongRef for Rc { - type WeakRef = Weak; - fn downgrade(&self) -> Self::WeakRef { - Rc::downgrade(&self) - } -} - -impl WeakRef for Weak { - type StrongRef = Rc; - fn upgrade(&self) -> Option { - Weak::upgrade(self) - } -} - - - -// ================== -// === Result Ops === -// ================== - -/// Allows extracting the element from `Result` for any `T`. -#[allow(missing_docs)] -pub trait ResultGet { - type Item; - /// Allows extracting the element from `Result` for any `T`. - fn unwrap_both(self) -> Self::Item; -} - -impl ResultGet for Result { - type Item = T; - fn unwrap_both(self) -> T { - match self { - Ok (t) => t, - Err (t) => t, - } - } -} diff --git a/lib/rust/enso-prelude/src/macros.rs b/lib/rust/enso-prelude/src/macros.rs deleted file mode 100644 index 2864b2ccf0..0000000000 --- a/lib/rust/enso-prelude/src/macros.rs +++ /dev/null @@ -1,194 +0,0 @@ -//! This macro defines set of common macros which are useful across different projects. - - -/// Allows for nicer definition of impls, similar to what Haskell or Scala does. Reduces the needed -/// boilerplate. For example, the following usage: -/// -/// ```compile_fail -/// struct A { name:String }; -/// impls! { From for String { |t| t.name.clone() } } -/// ``` -/// -/// compiles to: -/// ``` -/// struct A { name:String }; -/// impl From for String { -/// fn from(t:A) -> Self { -/// t.name.clone() -/// } -/// } -/// ``` -/// -/// This macro is meant to support many standard traits (like From) and should grow in the future. -/// Currently supported ones are: -/// * From<…> -/// * From + &From<…> -/// * Into + &Into<…> -/// * PhantomFrom<…> -#[macro_export] -macro_rules! impls { - ($([$($impl_params:tt)*])? From<$ty:ty> for $target:ty $(where [$($bounds:tt)*])? { - |$arg:tt| $($result:tt)* - } ) => { - #[allow(clippy::redundant_closure_call)] - impl <$($($impl_params)*)?> From <$ty> for $target $(where $($bounds)*)? { - fn from (arg:$ty) -> Self { - (|$arg:$ty| $($result)*)(arg) - } - } - }; - - ($([$($impl_params:tt)*])? From + &From <$ty:ty> for $target:ty $(where [$($bounds:tt)*])? { - |$arg:tt| $($result:tt)* - } ) => { - #[allow(clippy::redundant_closure_call)] - #[allow(clippy::identity_conversion)] - impl <$($($impl_params)*)?> From <$ty> for $target $(where $($bounds)*)? { - fn from (arg:$ty) -> Self { - (|$arg:$ty| $($result)*)(arg) - } - } - - #[allow(clippy::redundant_closure_call)] - #[allow(clippy::identity_conversion)] - impl <$($($impl_params)*)?> From <&$ty> for $target $(where $($bounds)*)? { - fn from (arg:&$ty) -> Self { - (|$arg:&$ty| $($result)*)(arg) - } - } - }; - - ($([$($impl_params:tt)*])? Into + &Into <$ty:ty> for $target:ty $(where [$($bounds:tt)*])? { - |$arg:tt| $($result:tt)* - } ) => { - #[allow(clippy::redundant_closure_call)] - #[allow(clippy::identity_conversion)] - impl <$($($impl_params)*)?> Into <$ty> for $target $(where $($bounds)*)? { - fn into(self) -> $ty { - (|$arg:Self| $($result)*)(self) - } - } - - #[allow(clippy::redundant_closure_call)] - #[allow(clippy::identity_conversion)] - impl <$($($impl_params)*)?> Into <$ty> for &$target $(where $($bounds)*)? { - fn into(self) -> $ty { - (|$arg:Self| $($result)*)(self) - } - } - }; - - ($([$($impl_params:tt)*])? PhantomFrom<$ty:ty> for $target:ty { - $($result:tt)* - } ) => { - impl <$($($impl_params)*)?> From > for $target { - fn from (_:PhantomData<$ty>) -> Self { - $($result)* - } - } - }; -} - -#[macro_export] -macro_rules! alias { - ($( $(#$meta:tt)* $name:ident = {$($tok:tt)*} )*) => {$( - $(#$meta)* - pub trait $name: $($tok)* {} - impl $name for T {} - )*}; - - (no_docs $( $(#$meta:tt)* $name:ident = {$($tok:tt)*} )*) => {$( - $(#$meta)* - #[allow(missing_docs)] - pub trait $name: $($tok)* {} - impl $name for T {} - )*}; -} - - - -// ============== -// === Lambda === -// ============== - -/// Clones all arguments from the first argument list by using `CloneRef` and defines lambda with -/// arguments from the second argument list (if present). For example, the following usage -/// -/// ```compile_fail -/// f! { (a,b)(c) a + b + c } -/// ``` -/// -/// is equivalent to: -/// -/// ```compile_fail -/// { -/// let a = a.clone_ref(); -/// let b = b.clone_ref(); -/// move |c| { a + b + c } -/// } -/// ``` -#[macro_export] -macro_rules! f { - ([$($name:ident),*] ($($args:tt)*) $($expr:tt)*) => { - { - $(let $name = $name.clone_ref();)* - move |$($args)*| { $($expr)* } - } - }; - - ([$($name:ident),*] $($expr:tt)*) => { - { - $(let $name = $name.clone_ref();)* - move || { $($expr)* } - } - }; - - (($($args:tt)*) $name:ident . $($toks:tt)*) => { - f! { [$name] ($($args)*) $name . $($toks)* } - }; - - (($($args:tt)*) { $name:ident . $($toks:tt)* }) => { - f! { [$name] ($($args)*) { $name . $($toks)* } } - }; - - ($name:ident . $($toks:tt)*) => { - f! { [$name] $name . $($toks)* } - }; -} - -/// Variant of the `f` macro producing a lambda which drops its first argument. -#[macro_export] -macro_rules! f_ { - ([$($name:ident),*] $($expr:tt)*) => { - f! { [$($name),*] (_) $($expr)* } - }; - - ($name:ident . $($toks:tt)*) => { - f_! { [$name] $name . $($toks)* } - }; - - ( { $name:ident . $($toks:tt)* } ) => { - f_! { [$name] { $name . $($toks)* } } - }; -} - -/// A macro for use in situations where the code is unreachable. -/// -/// This macro will panic in debug builds, but in release builds it expands to -/// the unsafe [`std::hint::unreachable_unchecked()`] function, which allows the -/// compiler to optimise more. -#[macro_export] -macro_rules! unreachable_panic { - () => ( - unreachable_panic!("This code was marked as unreachable.") - ); - ($msg:tt) => ( - if cfg!(debug_assertions) { - panic!($msg) - } else { - use std::hint::unreachable_unchecked; - #[allow(unsafe_code)] - unsafe { unreachable_unchecked() } - } - ) -} diff --git a/lib/rust/enso-prelude/src/option.rs b/lib/rust/enso-prelude/src/option.rs deleted file mode 100644 index dea61c1b95..0000000000 --- a/lib/rust/enso-prelude/src/option.rs +++ /dev/null @@ -1,25 +0,0 @@ -//! This module defines utilities for working with the [`std::option::Option`] type. - -/// Adds mapping methods to the `Option` type. -pub trait OptionOps { - type Item; - fn map_ref (&self , f:F) -> Option where F : FnOnce(&Self::Item) -> U; - fn for_each (self , f:F) where F : FnOnce(Self::Item) -> U; - fn for_each_ref (&self , f:F) where F : FnOnce(&Self::Item) -> U; -} - -impl OptionOps for Option { - type Item = T; - - fn map_ref(&self, f:F) -> Option where F : FnOnce(&Self::Item) -> U { - self.as_ref().map(f) - } - - fn for_each(self, f:F) where F : FnOnce(Self::Item) -> U { - if let Some(x) = self { f(x); } - } - - fn for_each_ref(&self, f:F) where F : FnOnce(&Self::Item) -> U { - if let Some(x) = self { f(x); } - } -} diff --git a/lib/rust/enso-prelude/src/phantom.rs b/lib/rust/enso-prelude/src/phantom.rs deleted file mode 100644 index a26921c2ad..0000000000 --- a/lib/rust/enso-prelude/src/phantom.rs +++ /dev/null @@ -1,94 +0,0 @@ -//! This module defines utilities for working with PhantomData. - -use super::std_reexports::*; -use derivative::Derivative; -use shrinkwraprs::Shrinkwrap; - - - -// =================== -// === PhantomData === -// =================== - -/// The following `PhantomData` implementations allow each argument to be non -/// Sized. Unfortunately, this is not equivalent to `PhantomData<(T1,T2,...)>`, -/// as tuple requires each arg to implement `Sized`. -pub type PhantomData2 = PhantomData<(PhantomData , PhantomData)>; -pub type PhantomData3 = PhantomData2, PhantomData>; -pub type PhantomData4 = PhantomData2, PhantomData>; -pub type PhantomData5 = PhantomData2, PhantomData>; -pub type PhantomData6 = PhantomData2, PhantomData>; -pub type PhantomData7 = PhantomData2, PhantomData>; -pub type PhantomData8 = PhantomData2, PhantomData>; -pub type PhantomData9 = PhantomData2, PhantomData>; - - - -// =================== -// === WithPhantom === -// =================== - -/// A wrapper adding a phantom type to a structure. -#[derive(Derivative)] -#[derive(Shrinkwrap)] -#[shrinkwrap(mutable)] -#[derivative(Clone (bound="T:Clone"))] -#[derivative(Default (bound="T:Default"))] -#[derivative(Debug (bound="T:Debug"))] -pub struct WithPhantom { - #[shrinkwrap(main_field)] - pub without_phantom: T, - phantom: PhantomData

-} - -impl WithPhantom { - pub fn new(without_phantom: T) -> Self { - let phantom = PhantomData; - Self { without_phantom, phantom } - } -} - - - -// ========================== -// === PhantomConversions === -// ========================== - -/// A utility for easy driving of type-level computations from value level. Often we've got some -/// type level relations, like a few singleton types, and for each such type we've got an associated -/// value. For example, we can define types `Int` and `Float` and associate with them -/// `WebGlContext::Int` and `WebGlContext::Float` constants encoded as `GlEnum`. In order to convert -/// `Int` or `Float` to the `GlEnum` we do not need the instance of the types, only the information -/// what type it was. So we can define: -/// -/// ```compile_fail -/// impl From> for u32 { -/// from(_:PhantomData>) { -/// GlEnum(WebGlContext::Int) -/// } -/// } -/// ``` -/// -/// And use it like: -/// -/// ```compile_fail -/// let val = GlEnum::from(PhantomData::) -/// ``` -/// -/// Using this utility we can always write the following code instead: -/// -/// ```compile_fail -/// let val = GlEnum::phantom_from::() -/// ``` -pub trait PhantomConversions: Sized { - fn phantom_into

() -> P where Self:PhantomInto

{ - PhantomData::.into() - } - fn phantom_from>() -> Self { - PhantomData::

.into() - } -} -impl PhantomConversions for T {} - -/// Like `Into` but for phantom types. -pub trait PhantomInto = where PhantomData: Into; diff --git a/lib/rust/enso-prelude/src/reference.rs b/lib/rust/enso-prelude/src/reference.rs deleted file mode 100644 index 9e30bee4fe..0000000000 --- a/lib/rust/enso-prelude/src/reference.rs +++ /dev/null @@ -1,78 +0,0 @@ -//! This module defines helpers and utilities for working with references. - -// ============ -// === With === -// ============ - -/// Surprisingly useful function. Consider the following code: -/// -/// ```compile_fail -/// fn init(self) -> Self { -/// let mut data = self.borrow_mut(); -/// ... -/// self -/// } -/// ``` -/// -/// It may not compile telling that the last line moves self out, however, -/// borrow might be used there, when `data` is dropped and runs the destructor. -/// -/// We can use this function to narrow-down the lifetimes. The following code -/// compiles just fine: -/// -/// ```compile_fail -/// fn init(self) -> Self { -/// with(self.borrow_mut(), |mut data| { -/// ... -/// }); -/// self -/// } -/// ``` -pub fn with Out, Out>(t: T, f: F) -> Out { f(t) } - - - -// ============= -// === ToRef === -// ============= - -/// Similar to `AsRef` but more specific and automatically implemented for every type. Allows for -/// conversion `&T` to `&T` (identity) and `T` to `&T` for any type `T`. In contrast, `AsRef` -/// requires explicit impls, so for example you cannot do `let t:&() = ().as_ref()` -pub trait ToRef where T:?Sized { fn to_ref(&self) -> &T; } -impl ToRef for T where T:?Sized { fn to_ref(&self) -> &T { self } } -impl ToRef for &T where T:?Sized { fn to_ref(&self) -> &T { self } } - -// pub trait ToRef = ?Sized + HasRefValue + ToRef__>; - -pub trait HasRefValue where { type RefValue:?Sized; } -impl HasRefValue for T where T:?Sized { default type RefValue=T; } -impl HasRefValue for &T where T:?Sized { type RefValue=T; } - -pub type RefValue = ::RefValue; - - - -// ============= -// === Owned === -// ============= - -/// The owned version of a type. It would be super cool if Rust would allow us to automatically -/// implement it for every type: `Owned<&T> = T` and `Owned = T` if `T` was not a reference. -/// Unfortunately, we need to implement it by hand for every type now. -pub trait AsOwned { - type Owned; -} - -/// Owned type family. -pub type Owned = ::Owned; - -/// Converts type to its owned version. -pub trait IntoOwned = AsOwned + Into>; - - -// === Default Impls === - -impl AsOwned for &T { - type Owned = T; -} diff --git a/lib/rust/enso-prelude/src/std_reexports.rs b/lib/rust/enso-prelude/src/std_reexports.rs deleted file mode 100644 index 008ba2dc2c..0000000000 --- a/lib/rust/enso-prelude/src/std_reexports.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! This module reexports several commonly used types defined in the standard library. - -// === Data === - -pub use std::any::Any; -pub use std::borrow::Cow; -pub use std::hash::Hash; -pub use std::marker::PhantomData; -pub use std::ops::Range; -pub use std::ops::RangeBounds; -pub use std::ops::RangeFrom; -pub use std::ops::RangeFull; -pub use std::ops::RangeInclusive; -pub use std::ops::RangeTo; -pub use std::ops::RangeToInclusive; - -// === Format === - -pub use core::any::type_name; -pub use core::fmt::Debug; -pub use std::fmt::Display; -pub use std::fmt; -pub use std::iter::FromIterator; -pub use std::iter; - - -// === Data Operations === - -pub use std::ops::Deref; -pub use std::ops::DerefMut; -pub use std::ops::Index; -pub use std::ops::IndexMut; - - -// === Conversion === - -pub use std::convert::identity; -pub use std::convert::TryFrom; -pub use std::convert::TryInto; - - -// === References === - -pub use std::cell::Cell; -pub use std::cell::Ref; -pub use std::cell::RefCell; -pub use std::cell::RefMut; -pub use std::rc::Rc; -pub use std::rc::Weak; -pub use std::slice::SliceIndex; -pub use std::slice; - - -// === Operators === - -pub use std::ops::Add; -pub use std::ops::Div; -pub use std::ops::Mul; -pub use std::ops::Neg; -pub use std::ops::Sub; - - -// === Utils === - -pub use std::mem; - -/// Alias for `Default::default()`. -pub fn default() -> T { - Default::default() -} diff --git a/lib/rust/enso-prelude/src/string.rs b/lib/rust/enso-prelude/src/string.rs deleted file mode 100644 index 3525d0024c..0000000000 --- a/lib/rust/enso-prelude/src/string.rs +++ /dev/null @@ -1,247 +0,0 @@ -//! This module defines several useful string variants, including copy-on-write and immutable -//! implementations. - -use std::borrow::Cow; - -use crate::impls; -use crate::clone::*; -use std::ops::Deref; -use std::rc::Rc; -use derive_more::*; - - - -// =========== -// === Str === -// =========== - -/// Abstraction for any kind of string as an argument. Functions defined as -/// `fn test(s: Str) { ... }` can be called with `String`, `&String`, and `&str` without -/// requiring caller to know the implementation details. Moreover, the definition can decide if it -/// needs allocation or not. Calling `s.as_ref()` will never allocate, while `s.into()` will -/// allocate only when necessary. -pub trait Str = Into + AsRef; - - - -// ================= -// === CowString === -// ================= - -// === Definition === - -/// A copy-on-write String implementation. It is a newtype wrapper for `Cow<'static,str>` and -/// provides many useful impls for efficient workflow. Use it whenever you want to store a string -/// but you are not sure if the string will be allocated or not. This way you can store a static -/// slice as long as you can and switch to allocated String on demand. -#[derive(Clone,Debug,Default,Display)] -pub struct CowString(Cow<'static,str>); - - -// === Conversions From CowString === - -impls!{ From <&CowString> for String { |t| t.clone().into() } } -impls!{ From for String { |t| t.0.into() } } - - -// === Conversions To CowString === - -impls!{ From > for CowString { |t| Self(t) } } -impls!{ From <&Cow<'static,str>> for CowString { |t| Self(t.clone()) } } -impls!{ From <&'static str> for CowString { |t| Self(t.into()) } } -impls!{ From for CowString { |t| Self(t.into()) } } -impls!{ From <&String> for CowString { |t| t.to_string().into() } } -impls!{ From <&CowString> for CowString { |t| t.clone() } } - - -// === Instances === - -impl Deref for CowString { - type Target = str; - fn deref(&self) -> &str { - self.0.deref() - } -} - -impl AsRef for CowString { - fn as_ref(&self) -> &str { - self.deref() - } -} - - - -// ================ -// === ImString === -// ================ - -/// Immutable string implementation with a fast clone implementation. -#[derive(Clone,CloneRef,Debug,Default,Eq,Hash,PartialEq)] -pub struct ImString { - content : Rc -} - -impl ImString { - /// Constructor. - pub fn new(content:impl Into) -> Self { - let content = Rc::new(content.into()); - Self {content} - } -} - -impl std::fmt::Display for ImString { - fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f,"{}",self.content) - } -} - -impl Deref for ImString { - type Target = str; - fn deref(&self) -> &Self::Target { - &self.content - } -} - -impl AsRef for ImString { - fn as_ref(&self) -> &ImString { - self - } -} - -impl AsRef for ImString { - fn as_ref(&self) -> &String { - self.content.as_ref() - } -} - -impl AsRef for ImString { - fn as_ref(&self) -> &str { - self.content.as_ref() - } -} - -impl From for ImString { - fn from(t:String) -> Self { - Self::new(t) - } -} - -impl From<&String> for ImString { - fn from(t:&String) -> Self { - Self::new(t) - } -} - -impl From<&&String> for ImString { - fn from(t:&&String) -> Self { - Self::new(*t) - } -} - -impl From<&str> for ImString { - fn from(t:&str) -> Self { - Self::new(t) - } -} - -impl From<&&str> for ImString { - fn from(t:&&str) -> Self { - Self::new(*t) - } -} - -impl PartialEq for ImString { - fn eq(&self, other:&String) -> bool { - self.content.as_ref().eq(other) - } -} - -impl PartialEq for String { - fn eq(&self, other:&ImString) -> bool { - self.eq(other.content.as_ref()) - } -} - - -// === Macros === - -/// Defines a newtype for `ImString`. -#[macro_export] -macro_rules! im_string_newtype { - ($($(#$meta:tt)* $name:ident),* $(,)?) => {$( - $(#$meta)* - #[derive(Clone,CloneRef,Debug,Default,Eq,Hash,PartialEq)] - pub struct $name { - content : ImString - } - - impl $name { - /// Constructor. - pub fn new(content:impl Into) -> Self { - let content = content.into(); - Self {content} - } - } - - impl Deref for $name { - type Target = str; - fn deref(&self) -> &Self::Target { - &self.content - } - } - - impl AsRef<$name> for $name { - fn as_ref(&self) -> &$name { - self - } - } - - impl AsRef for $name { - fn as_ref(&self) -> &ImString { - self.content.as_ref() - } - } - - impl AsRef for $name { - fn as_ref(&self) -> &String { - self.content.as_ref() - } - } - - impl AsRef for $name { - fn as_ref(&self) -> &str { - self.content.as_ref() - } - } - - impl From for $name { - fn from(t:String) -> Self { - Self::new(t) - } - } - - impl From<&String> for $name { - fn from(t:&String) -> Self { - Self::new(t) - } - } - - impl From<&&String> for $name { - fn from(t:&&String) -> Self { - Self::new(t) - } - } - - impl From<&str> for $name { - fn from(t:&str) -> Self { - Self::new(t) - } - } - - impl From<&&str> for $name { - fn from(t:&&str) -> Self { - Self::new(t) - } - } - )*}; -} diff --git a/lib/rust/enso-prelude/src/tp.rs b/lib/rust/enso-prelude/src/tp.rs deleted file mode 100644 index cee94c80f3..0000000000 --- a/lib/rust/enso-prelude/src/tp.rs +++ /dev/null @@ -1,80 +0,0 @@ -//! Type related utilities. - -use super::std_reexports::*; - - -// ================ -// === Anything === -// ================ - -/// Placeholder type used to represent any value type. It is useful to define type-level relations -/// like defining an unit with any quantity, let it be distance or mass. -#[derive(Clone,Copy,Debug,PartialEq)] -pub struct Anything {} - - -// =================== -// === TypeDisplay === -// =================== - -/// Like `Display` trait but for types. However, unlike `Display` it defaults to -/// `impl::any::type_name` if not provided with explicit implementation. -pub trait TypeDisplay { - fn type_display() -> String; -} - -impl TypeDisplay for T { - default fn type_display() -> String { - type_name::().to_string() - } -} - -/// Formats the type for the user-facing output. -pub fn type_display() -> String { - ::type_display() -} - - -// ============= -// === Value === -// ============= - -/// Defines relation between types and values, like between `True` and `true`. -pub trait KnownTypeValue { - - /// The value-level counterpart of this type-value. - type Value; - - /// The value of this type-value. - fn value() -> Self::Value; -} - -pub type TypeValue = ::Value; - - - -// ======================= -// === Type-level Bool === -// ======================= - -/// Type level `true` value. -#[derive(Clone,Copy,Debug)] -pub struct True {} - -/// Type level `false` value. -#[derive(Clone,Copy,Debug)] -pub struct False {} - -impl KnownTypeValue for True { - type Value = bool; - fn value() -> Self::Value { - true - } -} - -impl KnownTypeValue for False { - type Value = bool; - fn value() -> Self::Value { - false - } -} diff --git a/lib/rust/enso-prelude/src/vec.rs b/lib/rust/enso-prelude/src/vec.rs deleted file mode 100644 index 717c808dee..0000000000 --- a/lib/rust/enso-prelude/src/vec.rs +++ /dev/null @@ -1,71 +0,0 @@ -//! This module defines utilities for working with the [`std::vec::Vec`] type. - -use failure::_core::hint::unreachable_unchecked; - - - -// ============== -// === VecOps === -// ============== - -pub trait VecOps { - type Item; - - /// Pushes the provided `item` onto the [`std::vec::Vec`], and then returns an immutable - /// reference to the item. - fn push_and_get(&mut self, item:Self::Item) -> &Self::Item; - - /// Pushes the provided `item` onto the [`std::vec::Vec`], and then returns a mutable reference - /// to the item. - fn push_and_get_mut(&mut self, item:Self::Item) -> &mut Self::Item; -} - -impl VecOps for Vec { - type Item = T; - - fn push_and_get(&mut self, item:Self::Item) -> &Self::Item { - self.push(item); - let item_ix = self.len() - 1; - #[allow(unsafe_code)] - unsafe { self.get(item_ix).unwrap_or_else(||unreachable_unchecked()) } - } - - fn push_and_get_mut(&mut self, item:Self::Item) -> &mut Self::Item { - self.push(item); - let item_ix = self.len() - 1; - #[allow(unsafe_code)] - unsafe { self.get_mut(item_ix).unwrap_or_else(||unreachable_unchecked()) } - } -} - - - -// ============= -// === Tests === -// ============= - -#[cfg(test)] -mod tests { - use super::*; - - struct Test { - pub item: usize - } - - #[test] - fn test_push_and_get() { - let mut vec = Vec::new(); - let item = Test {item:10}; - let item_in_vec = vec.push_and_get(item); - assert_eq!(item_in_vec.item, 10) - } - - #[test] - fn test_push_and_get_mut() { - let mut vec = Vec::new(); - let item = Test {item:10}; - let item_in_vec = vec.push_and_get_mut(item); - item_in_vec.item = 20; - assert_eq!(item_in_vec.item, 20); - } -} diff --git a/lib/rust/enso-prelude/src/wrapper.rs b/lib/rust/enso-prelude/src/wrapper.rs deleted file mode 100644 index 7dd1e06786..0000000000 --- a/lib/rust/enso-prelude/src/wrapper.rs +++ /dev/null @@ -1,133 +0,0 @@ -//! This type defines Wrap / Unwrap utilities. Unwrap is like `Deref` but does not implement -//! `impl<'a, T> Unwrap for &'a T` in order to make it less error prone. `Wrap` is like `pure` in -//! applicative functors – if lifts a value to the specific type. - -use crate::std_reexports::*; - -// =============== -// === Wrapper === -// =============== - -/// Trait for any type which wraps other type. See docs of `Wrapper` to learn more. -pub trait HasContent { - type Content : ?Sized; -} - -/// Accessor for the wrapped value. -pub type Content = ::Content; - -/// Trait which enables `Sized` super-bound on the `Content` type. -pub trait HasSizedContent = HasContent where Content : Sized; - -/// Trait for objects which wrap values. Please note that this implements safe wrappers, so the -/// object - value relation must be bijective. -pub trait Wrapper = Wrap + ContentRef; - -/// Wrapping utility for values. -pub trait Wrap : HasSizedContent { - /// Wraps the value and returns the wrapped type. - fn wrap(t:Self::Content) -> Self; -} - -/// Unwrapping utility for wrapped types. -/// -/// Please note that this trait is very similar to the Deref trait. However, there is a very -/// important difference. Unlike `Deref`, there is no `impl<'a, T> Unwrap for &'a T` defined. The -/// existence of such impl is very error prone when writing complex impls. The `Deref` docs warn -/// about it explicitly: "[...] Because of this, Deref should only be implemented for smart pointers -/// to avoid confusion.". As an example, consider the following code which contains infinite loop: -/// -/// ```compile_fail -/// pub trait HasId { -/// fn id(&self) -> usize; -/// } -/// -/// // Notice the lack of bound `::Target : HasId` -/// impl HasId for T { -/// fn id(&self) -> usize { -/// self.deref().id() -/// } -/// } -/// ``` -/// -/// And the correct version: -/// -/// ```compile_fail -/// pub trait HasId { -/// fn id(&self) -> usize; -/// } -/// -/// // Notice the lack of bound `::Target : HasId` -/// impl HasId for T where ::Target : HasId { -/// fn id(&self) -> usize { -/// self.deref().id() -/// } -/// } -/// ``` -/// -/// Both versions compile fine, but the former loops for ever. -pub trait ContentRef : HasContent { - /// Unwraps this type to get the inner value. - fn content(&self) -> &Self::Content; -} - -/// Runs a function on the reference to the content. -pub trait WithContent : HasSizedContent { - /// Runs a function on the reference to the content. - fn with_content(&self,f:F) -> T where F : FnOnce(&Content) -> T; -} - -/// Unwraps the content by consuming this value. -pub trait Unwrap : HasSizedContent { - /// Unwraps the content by consuming this value. - fn unwrap(self) -> Self::Content; -} - - -// === Utils === - -/// Wraps the value and returns the wrapped type. -pub fn wrap(t:T::Content) -> T { - T::wrap(t) -} - -/// Provides reference to the content of this value. -pub fn content(t:&T) -> &T::Content { - T::content(t) -} - -/// Unwrap the content by consuming this value. -pub fn unwrap(t:T) -> T::Content { - T::unwrap(t) -} - - -// === Default Impls === - -impl WithContent for T { - fn with_content(&self,f:F) -> S - where F : FnOnce(&Content) -> S { - f(self.content()) - } -} - -// TODO: This should be implemented with the marker trait overlapping rules magic. -// impl Unwrap for T -// where ::Target: Unwrap { -// default fn unwrap(&self) -> &Self::Content { -// self.deref().unwrap() -// } -// } - - -// === Impls === - -impl HasContent for Rc { type Content = T; } -impl Wrap for Rc { fn wrap(t:T) -> Self { Rc::new(t) } } -impl ContentRef for Rc { fn content(&self) -> &Self::Content { self.deref() }} - -impl HasContent for String { type Content = char; } -impl Wrap for String { fn wrap(t:char) -> Self { t.to_string() } } - -impl HasContent for Vec { type Content = T; } -impl Wrap for Vec { fn wrap(t:T) -> Self { vec![t] } } diff --git a/lib/rust/enso-shapely/impl/Cargo.toml b/lib/rust/enso-shapely/impl/Cargo.toml deleted file mode 100644 index 3e67558094..0000000000 --- a/lib/rust/enso-shapely/impl/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "enso-shapely" -version = "0.1.0" -authors = ["Enso Team "] -edition = "2018" - -description = "Automated typeclass derivation." -readme = "README.md" -homepage = "https://github.com/enso-org/enso/lib/rust/shapely/impl" -repository = "https://github.com/enso-org/enso" -license-file = "../../../../LICENSE" - -keywords = ["typeclass", "deriving"] -categories = ["algorithms"] - -publish = true - -[lib] -crate-type = ["cdylib", "rlib"] - -[features] -default = [] - -[dependencies] -enso-shapely-macros = { version = "0.1.0" , path = "../macros" } -paste = { version = "0.1" } -derivative = { version = "1.0.3" } -shrinkwraprs = { version = "0.3.0" } - -[dev-dependencies] -enso-prelude = { path = "../../enso-prelude" } -wasm-bindgen-test = "0.2" diff --git a/lib/rust/enso-shapely/impl/README.md b/lib/rust/enso-shapely/impl/README.md deleted file mode 100644 index 1ffc9a72f6..0000000000 --- a/lib/rust/enso-shapely/impl/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Shapely - -This crate provides automatic derivation for useful type classes. diff --git a/lib/rust/enso-shapely/impl/src/cartesian.rs b/lib/rust/enso-shapely/impl/src/cartesian.rs deleted file mode 100644 index a76c911882..0000000000 --- a/lib/rust/enso-shapely/impl/src/cartesian.rs +++ /dev/null @@ -1,45 +0,0 @@ -/// Computes a cartesian product of the provided input. -/// -/// For the following expression: -/// ```compile_fail -/// cartesian!(f [g] [a b c] [x y z]); -/// ``` -/// -/// It expands to: -/// ```compile_fail -/// f! { [g] [ [a x] [a y] [a z] [b x] [b y] [b z] [c x] [c y] [c z] ] } -/// ``` -/// -/// If you provide underscore as second argument, it is skipped in the ouput macro: -/// -/// ```compile_fail -/// cartesian!(f _ [a b c] [x y z]); -/// ``` -/// -/// Expands to: -/// ```compile_fail -/// f! { [ [a x] [a y] [a z] [b x] [b y] [b z] [c x] [c y] [c z] ] } -/// ``` -#[macro_export] -macro_rules! cartesian { - ($f:tt [$($a:tt)*] [$($b:tt)*]) => { - $crate::_cartesian_impl!{ $f [] [$($a)*] [$($b)*] [$($b)*] } - }; -} - -/// Internal helper for `cartesian` macro. -#[macro_export] -macro_rules! _cartesian_impl { - ([[$f:path]] $out:tt [] $b:tt $init_b:tt) => { - $f!{ $out } - }; - ([[$f:path] $args:tt] $out:tt [] $b:tt $init_b:tt) => { - $f!{ $args $out } - }; - ($f:tt $out:tt [$a:tt $($at:tt)*] [] $init_b:tt) => { - $crate::_cartesian_impl!{ $f $out [$($at)*] $init_b $init_b } - }; - ($f:tt [$($out:tt)*] [$a:tt $($at:tt)*] [$b:tt $($bt:tt)*] $init_b:tt) => { - $crate::_cartesian_impl!{ $f [$($out)* [$a $b]] [$a $($at)*] [$($bt)*] $init_b } - }; -} diff --git a/lib/rust/enso-shapely/impl/src/generator.rs b/lib/rust/enso-shapely/impl/src/generator.rs deleted file mode 100644 index eca9732005..0000000000 --- a/lib/rust/enso-shapely/impl/src/generator.rs +++ /dev/null @@ -1,90 +0,0 @@ -//! Helper code meant to be used by the code generated through usage of macros -//! from `enso-shapely-macros` crate. - -pub use enso_shapely_macros::*; - -use derivative::Derivative; -use std::ops::Generator; -use std::ops::GeneratorState; -use std::pin::Pin; -use std::marker::PhantomData; - - - -// ========================== -// === GeneratingIterator === -// ========================== - -/// Iterates over values yielded from the wrapped `Generator`. -#[derive(Debug)] -pub struct GeneratingIterator(pub G); - -impl Iterator for GeneratingIterator -where G: Generator + Unpin { - type Item = G::Yield; - fn next(&mut self) -> Option { - match Pin::new(&mut self.0).resume() { - GeneratorState::Yielded(element) => Some(element), - _ => None, - } - } -} - - - -// ===================== -// === EmptyIterator === -// ===================== - -/// An `Iterator` type that yields no values of the given type `T`. -#[derive(Derivative)] -#[derivative(Debug,Default(bound=""))] -pub struct EmptyIterator(PhantomData); - -impl EmptyIterator { - /// Create a new empty iterator. - pub fn new() -> Self { - Default::default() - } -} - -impl Iterator for EmptyIterator { - type Item = T; - fn next(&mut self) -> Option { - None - } -} - - - -// ============= -// === Tests === -// ============= - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn empty_iterator_works_for_any_type() { - for elem in EmptyIterator::new() { - elem: i32; - } - for elem in EmptyIterator::new() { - elem: String; - } - } - - #[test] - fn generating_iterator_works() { - let generator = || { - yield 0; - yield 1; - yield 2; - }; - let expected_numbers = vec!(0, 1, 2); - let generator_iter = GeneratingIterator(generator); - let collected_result: Vec<_> = generator_iter.collect(); - assert_eq!(collected_result, expected_numbers); - } -} diff --git a/lib/rust/enso-shapely/impl/src/lib.rs b/lib/rust/enso-shapely/impl/src/lib.rs deleted file mode 100644 index 3bfc9e1fc7..0000000000 --- a/lib/rust/enso-shapely/impl/src/lib.rs +++ /dev/null @@ -1,405 +0,0 @@ -// README README README README README README README README README README README -// README README README README README README README README README README README -// README README README README README README README README README README README - -// This library is in a very early stage. It will be refactored and improved -// soon. It should not be reviewed now. - -#![warn(unsafe_code)] -#![warn(missing_copy_implementations)] -#![warn(missing_debug_implementations)] -#![feature(generators, generator_trait)] -#![feature(specialization)] -#![feature(type_ascription)] -#![feature(overlapping_marker_traits)] - -pub mod generator; -pub mod shared; -pub mod singleton; -pub mod cartesian; - -pub use enso_shapely_macros::*; - -pub use generator::EmptyIterator; -pub use generator::GeneratingIterator; - -use shrinkwraprs::Shrinkwrap; - - -/// Replaces the first argument with the second one. It is useful when creating macros which match -/// a pattern and you want to generate as many repetitions of a token as there was matches. For -/// example, when matching `$($name:ident)*`, you may want to generate as many empty tuples as -/// the number of names matched. You can do it by using `$(replace!{$name,()})*`. -#[macro_export] -macro_rules! replace { - ($a:tt,$b:tt) => {$b} -} - -/// Generates a newtype wrapper for the provided types. It also generates a lot of impls, -/// including Copy, Clone, Debug, Default, Display, From, Into, Deref, and DerefMut. -/// -/// For the following input: -/// ```compile_fail -/// newtype_copy! { -/// AttributeIndex(usize) -/// } -/// ``` -/// -/// The following code is generated: -/// ```compile_fail -/// #[derive(Copy, Clone, Debug, Default, Display, From, Into)] -/// pub struct AttributeIndex(usize); -/// impl Deref for AttributeIndex { -/// type Target = usize; -/// fn deref(&self) -> &Self::Target { -/// &self.0 -/// } -/// } -/// impl DerefMut for AttributeIndex { -/// fn deref_mut(&mut self) -> &mut Self::Target { -/// &mut self.0 -/// } -/// } -/// ``` -#[macro_export] -macro_rules! newtype_copy { - ($( $(#$meta:tt)* $name:ident($type:ty); )*) => {$( - $(#$meta)* - #[derive(Copy,Clone,CloneRef,Debug,Default,Display,From,Into)] - pub struct $name($type); - - impl Deref for $name { - type Target = $type; - fn deref(&self) -> &Self::Target { - &self.0 - } - } - - impl DerefMut for $name { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } - } - )*} -} - -#[macro_export] -macro_rules! derive_clone_plus { - ($name:ident) => { - impl> From<&T> for $name { - fn from(t: &T) -> Self { - t.clone().into() - } - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// - -use std::ops::Deref; - -macro_rules! extension_struct { - ($name:ident { $($field:ident : $field_type:ty),* }) => { paste::item! { - - ////// With_NAME_ ////// - - #[derive(Shrinkwrap)] - #[shrinkwrap(mutable)] - struct []($($field_type),*, #[shrinkwrap(main_field)] T); - - ////// Has_NAME_ ////// - - pub trait [] { - $(fn $field(&self) -> &$field_type;)* - } - - impl]> - [] for T { - $(fn $field(&self) -> &$field_type { - []::$field(self) - })* - } - - ////// Has_NAME_Indirect ////// - - pub trait [] {} - - impl - [] for [] {} - - impl - [] for T - where T: Deref, ::Target : [] {} - - ////// Has_NAME_Spec1 ////// - - trait [] { - $(fn $field(&self) -> &$field_type;)* - } - - impl - [] for [] { - $(fn $field(&self) -> &$field_type { - &self.0 - })* - } - - impl]> - [] for T { - $(default fn $field(&self) -> &$field_type { - []::$field(self) - })* - } - - ////// Has_NAME_Spec2 ////// - - trait [] { - $(fn $field(&self) -> &$field_type;)* - } - - impl]> - [] for T { - $(default fn $field(&self) -> &$field_type { - unreachable!(); - })* - } - - impl - [] for T - where T: Deref, ::Target : [] { - $(fn $field(&self) -> &$field_type { - self.deref().$field() - })* - } - }}; -} - - -extension_struct!(Label { - label: String -}); - -extension_struct!(Foo { - t1: String -}); - - - -// ============== -// === WithID === -// ============== - -struct WithID(i32, T); - -impl Deref for WithID { - type Target = T; - fn deref(&self) -> &Self::Target { - &self.1 - } -} - -struct WithID2(i32, T); - -impl Deref for WithID2 { - type Target = T; - fn deref(&self) -> &Self::Target { - &self.1 - } -} - -//// === HasID === -// -//pub trait HasID { -// fn id(&self) -> &i32; -//} -// -//impl HasID for T { -// fn id(&self) -> &i32 { -// HasIDForVariantOrAny::id(self) -// } -//} -// -//// === MarkerCtxForHasID === -// -//pub trait MarkerCtxForHasID {} -// -//impl MarkerCtxForHasID for WithID {} -// -//impl MarkerCtxForHasID for T -//where T: Deref, ::Target : HasID {} -// -// -//// === HasIDForVariantOrAny === -// -//trait HasIDForVariantOrAny { -// fn id(&self) -> &i32; -//} -//impl HasIDForVariantOrAny for WithID { -// fn id(&self) -> &i32 { -// &self.0 -// } -//} -//impl HasIDForVariantOrAny for T { -// default fn id(&self) -> &i32 { -// HasIDForDerefOrAny::id(self) -// } -//} -// -//// === HasIDForDerefOrAny === -// -//trait HasIDForDerefOrAny { -// fn id(&self) -> &i32; -//} -//impl HasIDForDerefOrAny for T -//where T: Deref, ::Target : HasID { -// fn id(&self) -> &i32 { -// self.deref().id() -// } -//} -//impl HasIDForDerefOrAny for T { -// default fn id(&self) -> &i32 { -// unreachable!(); -// } -//} - - - - - -// === HasID === - -pub trait HasID { - fn id(&self) -> &i32; -} - - -////////////////////////////////// - -#[overlappable] -impl HasID for T - where T: Deref, ::Target : HasID { - fn id(&self) -> &i32 { - self.deref().id() - } -} - -impl HasID for T { - fn id(&self) -> &i32 { - VariantOrAny_HasID::id(self) - } -} - -// === MarkerCtx_HasID === - -#[allow(non_camel_case_types)] -pub trait MarkerCtx_HasID {} - -impl MarkerCtx_HasID for T - where T: Deref, ::Target : HasID {} - -// === VariantOrAny_HasID === - -#[allow(non_camel_case_types)] -trait VariantOrAny_HasID { - fn id(&self) -> &i32; -} - -impl VariantOrAny_HasID for T { - default fn id(&self) -> &i32 { - DerefOrAny_HasID::id(self) - } -} - -// === DerefOrAny_HasID === - -#[allow(non_camel_case_types)] -trait DerefOrAny_HasID { - fn id(&self) -> &i32; -} -impl DerefOrAny_HasID for T - where T: Deref, ::Target : HasID { - fn id(&self) -> &i32 { - self.deref().id() - } -} -impl DerefOrAny_HasID for T { - default fn id(&self) -> &i32 { - unreachable!(); - } -} - - -///////////////////////////////////////////// - - -//#[overlapping] -//impl HasID for WithID { -// fn id(&self) -> &i32 { -// &self.0 -// } -//} - -impl MarkerCtx_HasID for WithID {} - -impl VariantOrAny_HasID for WithID { - fn id(&self) -> &i32 { - &self.0 - } -} - -//// NON-CONFLICTING: -// -//trait HasFoo2 { -// fn foo(&self) -> i32; -//} -//impl HasFoo2 for T { -// default fn foo(&self) -> i32 { -// 7 -// } -//} -//impl HasFoo2 for WithID { -// default fn foo(&self) -> i32 { -// 8 -// } -//} -// -//// CONFLICTING -// -//trait HasFoo3 { -// fn foo(&self) -> i32; -//} -//impl HasFoo3 for T -// where T: Deref, -// ::Target: HasFoo3 { -// default fn foo(&self) -> i32 { -// self.deref().foo() -// } -//} -//impl HasFoo3 for WithID { -// default fn foo(&self) -> i32 { -// 8 -// } -//} - - -// ============= -// === Usage === -// ============= - -struct _A(i32); - -type _X = WithLabel>; - -fn _test (t: T) { - println!("{:?}", t.label()); - println!("{:?}", t.id()); -} - -fn _main() { - let v1 = WithLabel("label1".to_string(), WithID(0, _A(1))); - _test(v1); // THIS IS EXAMPLE USE CASE WHICH DOES NOT COMPILE - -// println!("{}", 7.foo()); -} \ No newline at end of file diff --git a/lib/rust/enso-shapely/impl/src/shared.rs b/lib/rust/enso-shapely/impl/src/shared.rs deleted file mode 100644 index d4fe2a7e5e..0000000000 --- a/lib/rust/enso-shapely/impl/src/shared.rs +++ /dev/null @@ -1,381 +0,0 @@ -/// This module implements the `shared` macro, an utility allowing for easy definition of -/// `Rc>` wrappers. - - -/// This macro provides an easy way to define secure `Rc>` wrappers for a given struct. -/// -/// This macro accepts a body which is very similar to normal struct definition. There are a few -/// notable differences: -/// - The first token this macro accepts should be the name of the wrapped structure. -/// - The implementation block does not have a name. It is always implemented for the struct. -/// You are allowed to provide multiple impl blocks. -/// -/// This macro traverses the definition and for each function, it generates a borrowing counterpart. -/// It also handles the `new` function in a special way. Please note, that this macro generates -/// only safe bindings. If your original function returns a reference, the generated code will fail. -/// If you want to return references with some custom guard system, implement that outside of this -/// macro usage. -/// -/// For the given input: -/// ```compile_fail -/// shared! { Uniform -/// -/// #[derive(Clone,Copy,Debug)] -/// pub struct UniformData { -/// value: Value, -/// dirty: bool, -/// } -/// -/// impl { -/// /// Constructor. -/// pub fn new(value:Value) -> Self { -/// let dirty = false; -/// Self {value,dirty} -/// } -/// -/// /// Checks whether the uniform was changed and not yet updated. -/// pub fn check_dirty(&self) -> bool { -/// self.dirty -/// } -/// -/// /// Modifies the value stored by the uniform. -/// pub fn modify(&mut self, f:F) { -/// self.set_dirty(); -/// f(&mut self.value); -/// } -/// }} -/// ``` -/// -/// The following output will be generated: -/// -/// ```compile_fail -/// #[derive(Clone,Copy,Debug)] -/// pub struct UniformData { -/// value: Value, -/// dirty: bool, -/// } -/// -/// impl for UniformData { -/// #[doc = r###"Constructor."###] -/// pub fn new(value:Value) -> Self { -/// let dirty = false; -/// Self {value,dirty} -/// } -/// -/// #[doc = r###"Checks whether the uniform was changed and not yet updated."###] -/// pub fn check_dirty(&self) -> bool { -/// self.dirty -/// } -/// -/// #[doc = r###"Modifies the value stored by the uniform."###] -/// pub fn modify(&mut self, f:F) { -/// self.set_dirty(); -/// f(&mut self.value); -/// } -/// } -/// -/// #[derive(Clone,Copy,Debug)] -/// pub struct Uniform { -/// rc: Rc>> -/// } -/// -/// impl for Uniform { -/// #[doc = r###"Constructor."###] -/// pub fn new(value:Value) -> Self { -/// let rc = Rc::new(RefCell::new(UniformData::new(value))); -/// Self {rc} -/// } -/// -/// #[doc = r###"Checks whether the uniform was changed and not yet updated."###] -/// pub fn check_dirty(&self) -> bool { -/// self.rc.borrow.check_dirty() -/// } -/// -/// #[doc = r###"Modifies the value stored by the uniform."###] -/// pub fn modify(&self, f:F) { -/// self.borrow_mut().modify(f) -/// } -/// } -/// ``` -/// -/// **Note** -/// Both the implementation as well as usage syntax of this macro will be nicer if it was -/// implemented as procedural macro. However, no IDE supports expansion of procedural macros -/// currently, so it was implemented as macro rules instead. -#[macro_export] -macro_rules! shared { - ($name:ident $($in:tt)*) => { - $crate::angles_to_brackets_shallow! { shared_bracket [$name] $($in)* } - } -} - -#[macro_export] -macro_rules! shared_bracket_impl { - ([impl [$($impl_params:tt)*] $name:ident $name_mut:ident $([$($params:tt)*])?] [ - $( - $(#[$($meta:tt)*])* - $acc:vis fn $fn_name:ident - $([$($fn_params:tt)*])? ($($fn_args:tt)*) $(-> $fn_type:ty)? $(where $($wt1:ty : $wt2:path),* )? { - $($fn_body:tt)* - } - )* - ]) => { - impl <$($impl_params)*> $name_mut $(<$($params)*>)? { - $( - $(#[$($meta)*])* - $acc fn $fn_name $(<$($fn_params)*>)* - ($($fn_args)*) $(-> $fn_type)? $(where $($wt1 : $wt2),* )? {$($fn_body)*} - )* - } - - impl <$($impl_params)*> $name $(<$($params)*>)? { - $($crate::shared_bracket_fn! { - $name_mut :: $(#[$($meta)*])* - $acc fn $fn_name [$($($fn_params)*)*] ($($fn_args)*) $(-> $fn_type)? $(where $($wt1 : $wt2),* )? - })* - } - }; -} - -#[macro_export] -macro_rules! shared_bracket_fn { - ( $base:ident :: $(#[$($meta:tt)*])* $acc:vis fn new $([$($params:tt)*])? - ($($arg:ident : $arg_type:ty),*) $(-> $type:ty)? $(where $($wt1:ty : $wt2:path),* )? ) => { - $(#[$($meta)*])* - $acc fn new $(<$($params)*>)* ($($arg : $arg_type),*) $(-> $type)? $(where $($wt1 : $wt2),* )? { - Self { rc: Rc::new(RefCell::new($base::new($($arg),*))) } - } - }; - ( $base:ident :: $(#[$($meta:tt)*])* $acc:vis fn $name:ident $([$($params:tt)*])? - (&self $(,$($arg:ident : $arg_type:ty),+)?) $(-> $type:ty)? $(where $($wt1:ty : $wt2:path),* )? ) => { - $(#[$($meta)*])* - $acc fn $name $(<$($params)*>)* (&self $(,$($arg : $arg_type),*)?) $(-> $type)? $(where $($wt1 : $wt2),* )? { - self.rc.borrow().$name($($($arg),*)?) - } - }; - ( $base:ident :: $(#[$($meta:tt)*])* $acc:vis fn $name:ident $([$($params:tt)*])? - (&mut self $(,$($arg:ident : $arg_type:ty),+)?) $(-> $type:ty)? $(where $($wt1:ty : $wt2:path),* )? ) => { - $(#[$($meta)*])* - $acc fn $name $(<$($params)*>)* (&self $(,$($arg : $arg_type),*)?) $(-> $type)? $(where $($wt1 : $wt2),* )? { - self.rc.borrow_mut().$name($($($arg),*)?) - } - }; -} - -#[macro_export] -macro_rules! shared_bracket_normalized { - ( [$name:ident] [ - $(#[$($meta:tt)*])* - $(##[$($imeta:tt)*])* - pub struct $name_mut:ident $params:tt { - $($(#[$($field_meta:tt)*])* $field:ident : $field_type:ty),* $(,)? - } - - $(impl $([$($impl_params:tt)*])? {$($impl_body:tt)*})* - ]) => { - $crate::shared_struct! { - $(#[$($meta)*])* - $(##[$($imeta)*])* - pub struct $name $name_mut $params { - $($(#[$($field_meta)*])* $field : $field_type),* - } - } - - $($crate::angles_to_brackets_shallow! {shared_bracket_impl - [impl [$($($impl_params)*)?] $name $name_mut $params] $($impl_body)* - })* - }; -} - -#[macro_export] -macro_rules! shared_struct { - ( - $(#[$($meta:tt)*])* - $(##[$($imeta:tt)*])* - pub struct $name:ident $name_mut:ident [$($params:tt)*] { - $($(#[$($field_meta:tt)*])* $field:ident : $field_type:ty),* $(,)? - } - ) => { - $(#[$($meta)*])* - #[derive(CloneRef)] - pub struct $name <$($params)*> { rc: Rc>> } - - $(#[$($meta)*])* - $(#[$($imeta)*])* - pub struct $name_mut <$($params)*> { $($(#[$($field_meta)*])* $field : $field_type),* } - - impl<$($params)*> Clone for $name <$($params)*> { - fn clone(&self) -> Self { - let rc = self.rc.clone(); - Self {rc} - } - } - - paste::item! { - $(#[$($meta)*])* - #[derive(CloneRef)] - pub struct [] <$($params)*> { weak: Weak>> } - - impl<$($params)*> Clone for [] <$($params)*> { - fn clone(&self) -> Self { - let weak = self.weak.clone(); - Self {weak} - } - } - - impl<$($params)*> [] <$($params)*> { - /// Attempts to upgrade the weak pointer to an rc, delaying dropping of the inner - /// value if successful. - pub fn upgrade(&self) -> Option<$name <$($params)*>> { - self.weak.upgrade().map(|rc| $name {rc}) - } - } - - impl<$($params)*> WeakElement for [] <$($params)*> { - type Strong = $name <$($params)*> ; - - fn new(view: &Self::Strong) -> Self { - view.downgrade() - } - - fn view(&self) -> Option { - self.upgrade() - } - } - - impl<$($params)*> $name <$($params)*> { - /// Downgrade the reference to weak ref. - pub fn downgrade(&self) -> [] <$($params)*> { - let weak = Rc::downgrade(&self.rc); - [] {weak} - } - - /// Call operation with borrowed data. Should be use in implementation of wrapper - /// only. - fn with_borrowed(&self, operation:F) -> R - where F : FnOnce(&mut $name_mut<$($params)*>) -> R { - operation(&mut self.rc.borrow_mut()) - } - - /// Wraps given data object into a shared handle. - pub fn new_from_data(data:$name_mut<$($params)*>) -> Self { - Self {rc:Rc::new(RefCell::new(data))} - } - - /// Check if the shared pointer points to the same struct as `other`. - pub fn identity_equals(&self, other:&Self) -> bool { - Rc::ptr_eq(&self.rc,&other.rc) - } - } - } - }; -} - -#[macro_export] -macro_rules! angles_to_brackets_shallow { - ($f:ident $f_arg:tt $($in:tt)*) => { - $crate::_angles_to_brackets_shallow! { $f $f_arg [] [] [] $($in)* } - } -} - -#[macro_export] -macro_rules! _angles_to_brackets_shallow { - ( $f:ident $f_arg:tt [] [$($out:tt)*] [] ) => { $crate::$f! { $f_arg [$($out)*] } }; - ( $f:ident $f_arg:tt [] [$($out:tt)*] [$($cout:tt)*] ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] [$($out)* $($cout)*] [] } }; - ( $f:ident $f_arg:tt [] [$($out:tt)*] [$($cout:tt)*] < $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [.] [$($out)* $($cout)*] [] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] << $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [. .] $out [$($cout)* <] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] <<< $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [. . .] $out [$($cout)* <<] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] <<<< $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [. . . .] $out [$($cout)* <<<] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] <<<<< $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [. . . . .] $out [$($cout)* <<<<] $($rest)* } }; - ( $f:ident $f_arg:tt [$($depth:tt)*] $out:tt [$($cout:tt)*] < $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)* .] $out [$($cout)* <] $($rest)* } }; - ( $f:ident $f_arg:tt [$($depth:tt)*] $out:tt [$($cout:tt)*] << $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)* . .] $out [$($cout)* <<] $($rest)* } }; - ( $f:ident $f_arg:tt [$($depth:tt)*] $out:tt [$($cout:tt)*] <<< $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)* . . .] $out [$($cout)* <<<] $($rest)* } }; - ( $f:ident $f_arg:tt [$($depth:tt)*] $out:tt [$($cout:tt)*] <<<< $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)* . . . .] $out [$($cout)* <<<<] $($rest)* } }; - ( $f:ident $f_arg:tt [$($depth:tt)*] $out:tt [$($cout:tt)*] <<<<< $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)* . . . . .] $out [$($cout)* <<<<<] $($rest)* } }; - ( $f:ident $f_arg:tt [. $($depth:tt)*] $out:tt [$($cout:tt)*] -> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [. $($depth)*] $out [$($cout)* ->] $($rest)* } }; - ( $f:ident $f_arg:tt [.] [$($out:tt)*] $cout:tt > $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] [$($out)* $cout] [] $($rest)* } }; - ( $f:ident $f_arg:tt [. .] [$($out:tt)*] [$($cout:tt)*] >> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] [$($out)* [$($cout)* >]] [] $($rest)* } }; - ( $f:ident $f_arg:tt [. . .] [$($out:tt)*] [$($cout:tt)*] >>> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] [$($out)* [$($cout)* >>]] [] $($rest)* } }; - ( $f:ident $f_arg:tt [. . . .] [$($out:tt)*] [$($cout:tt)*] >>>> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] [$($out)* [$($cout)* >>>]] [] $($rest)* } }; - ( $f:ident $f_arg:tt [. . . . .] [$($out:tt)*] [$($cout:tt)*] >>>>> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] [$($out)* [$($cout)* >>>>]] [] $($rest)* } }; - ( $f:ident $f_arg:tt [. $($depth:tt)*] $out:tt [$($cout:tt)*] > $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)*] $out [$($cout)* >] $($rest)* } }; - ( $f:ident $f_arg:tt [. . $($depth:tt)*] $out:tt [$($cout:tt)*] >> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)*] $out [$($cout)* >>] $($rest)* } }; - ( $f:ident $f_arg:tt [. . . $($depth:tt)*] $out:tt [$($cout:tt)*] >>> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)*] $out [$($cout)* >>>] $($rest)* } }; - ( $f:ident $f_arg:tt [. . . . $($depth:tt)*] $out:tt [$($cout:tt)*] >>>> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)*] $out [$($cout)* >>>>] $($rest)* } }; - ( $f:ident $f_arg:tt [. . . . . $($depth:tt)*] $out:tt [$($cout:tt)*] >>>>> $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [$($depth)*] $out [$($cout)* >>>>>] $($rest)* } }; - - // Function output handling - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt $t24:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 $t24 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt $t24:tt $t25:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 $t24 $t25 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt $t24:tt $t25:tt $t26:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 $t24 $t25 $t26 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt $t24:tt $t25:tt $t26:tt $t27:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 $t24 $t25 $t26 $t27 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt $t24:tt $t25:tt $t26:tt $t27:tt $t28:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 $t24 $t25 $t26 $t27 $t28 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt $t24:tt $t25:tt $t26:tt $t27:tt $t28:tt $t29:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 $t24 $t25 $t26 $t27 $t28 $t29 {$($b)*}] $($rest)* } }; - ( $f:ident $f_arg:tt [] $out:tt [$($cout:tt)*] -> $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $t18:tt $t19:tt $t20:tt $t21:tt $t22:tt $t23:tt $t24:tt $t25:tt $t26:tt $t27:tt $t28:tt $t29:tt $t30:tt {$($b:tt)*} $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg [] $out [$($cout)* -> $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17 $t18 $t19 $t20 $t21 $t22 $t23 $t24 $t25 $t26 $t27 $t28 $t29 $t30 {$($b)*}] $($rest)* } }; - - // Any token handling - ( $f:ident $f_arg:tt $depth:tt $out:tt [$($cout:tt)*] $t:tt $($rest:tt)* ) => { $crate::_angles_to_brackets_shallow! { $f $f_arg $depth $out [$($cout)* $t] $($rest)* } }; -} - -#[macro_export] -macro_rules! shared_bracket { - ([$name:ident] [$($in:tt)*]) => { - $crate::normalize_input! { shared_bracket_normalized [$name] $($in)* } - } -} - -#[macro_export] -macro_rules! normalize_input { - ($f:ident $f_args:tt $($in:tt)*) => { - $crate::_normalize_input! { $f $f_args [] $($in)* } - } -} - -#[macro_export] -macro_rules! _normalize_input { - // Finish. - ( $f:ident $f_args:tt $out:tt ) => { - $crate::$f! { $f_args $out } - }; - - // Structs. - ( $f:ident $f_args:tt [$($out:tt)*] - $(#[$($meta:tt)*])* - pub struct $name:tt $([$($params:tt)*])? {$($body:tt)*} - $($rest:tt)* - ) => { - $crate::_normalize_input! { $f $f_args - [$($out)* - $(#[$($meta)*])* - pub struct $name [$($($params)*)?] {$($body)*} - ] $($rest)* } - }; - - // Any token. - ( $f:ident $f_args:tt [$($out:tt)*] $in:tt $($rest:tt)* ) => { - $crate::_normalize_input! { $f $f_args [$($out)* $in] $($rest)* } - }; -} diff --git a/lib/rust/enso-shapely/impl/src/singleton.rs b/lib/rust/enso-shapely/impl/src/singleton.rs deleted file mode 100644 index 82592050a1..0000000000 --- a/lib/rust/enso-shapely/impl/src/singleton.rs +++ /dev/null @@ -1,143 +0,0 @@ -//! This module defines helpers for defining singletons and associated enum types. A singleton is -//! a type with one possible value. It is used mainly for a type level programming purposes. - -/// Defines singleton types. For the following input: -/// ```compile_fail -/// define_singletons!{ -/// /// A Foo! -/// Foo, -/// /// A Bar! -/// Bar, -/// } -/// ``` -/// -/// It expands to: -/// -/// ``` -/// #[allow(missing_docs)] -/// #[derive(Copy, Clone, Debug)] -/// #[doc = r###"A Foo!"###] -/// pub struct Foo; -/// impl Default for Foo { -/// fn default() -> Self { -/// Self -/// } -/// } -/// #[allow(missing_docs)] -/// #[derive(Copy, Clone, Debug)] -/// #[doc = r###"A Bar!"###] -/// pub struct Bar; -/// impl Default for Bar { -/// fn default() -> Self { -/// Self -/// } -/// } -/// -/// ``` -#[macro_export] -macro_rules! define_singletons { - ( $( $(#$meta:tt)* $name:ident ),* $(,)? ) => {$( - #[allow(missing_docs)] - #[derive(Copy,Clone,Debug,PartialEq,Eq)] - $(#$meta)* - pub struct $name; - - impl Default for $name { - fn default() -> Self { - Self - } - } - )*} -} - -/// Defines an associated enum type for predefined singletons. -/// -/// For the following input: -/// ```compile_fail -/// define_singleton_enum!{ -/// MyEnum { -/// /// A Foo! -/// Foo, -/// /// A Bar! -/// Bar, -/// } -/// } -/// ``` -/// -/// It expands to: -/// -/// ```compile_fail -/// #[allow(missing_docs)] -/// #[derive(Copy, Clone, Debug)] -/// pub enum MyEnum { -/// #[doc = r###"A Foo!"###] -/// Foo, -/// #[doc = r###"A Bar!"###] -/// Bar, -/// } -/// impl From for MyEnum { -/// fn from(_: Foo) -> Self { -/// Self::Foo -/// } -/// } -/// impl From> for MyEnum { -/// fn from(_: PhantomData) -> Self { -/// Self::Foo -/// } -/// } -/// impl From for MyEnum { -/// fn from(_: Bar) -> Self { -/// Self::Bar -/// } -/// } -/// impl From> for MyEnum { -/// fn from(_: PhantomData) -> Self { -/// Self::Bar -/// } -/// } -/// ``` -#[macro_export] -macro_rules! define_singleton_enum_from { - ( - $(#$meta:tt)* - $name:ident { - $( $(#$field_meta:tt)* $field:ident ),* $(,)? - } - ) => { - #[allow(missing_docs)] - #[derive(Copy,Clone,Debug,PartialEq,Eq)] - $(#$meta)* - pub enum $name { - $( $(#$field_meta)* $field ),* - } - - $( - impl From<$field> for $name { - fn from(_:$field) -> Self { - Self::$field - } - } - - impl From> for $name { - fn from(_:PhantomData<$field>) -> Self { - Self::$field - } - } - )* - } -} - -/// Defines singletons and an associated enum type. -/// It expands to the same as `define_singletons` and `define_singleton_enum_from`. -#[macro_export] -macro_rules! define_singleton_enum { - ( - $(#$meta:tt)* - $name:ident { - $( $(#$field_meta:tt)* $field:ident ),* $(,)? - } - ) => { - $crate::define_singletons! { $($(#$field_meta)* $field),* } - $crate::define_singleton_enum_from! { $(#$meta)* $name {$($(#$field_meta)* $field),*}} - } -} diff --git a/lib/rust/enso-shapely/impl/tests/derivation.rs b/lib/rust/enso-shapely/impl/tests/derivation.rs deleted file mode 100644 index 5400c46e79..0000000000 --- a/lib/rust/enso-shapely/impl/tests/derivation.rs +++ /dev/null @@ -1,174 +0,0 @@ -#![feature(generators)] -#![feature(type_alias_impl_trait)] - -use enso_shapely::*; - - - -// ============= -// === Utils === -// ============= - -/// To fail compilation if `T` is not `IntoIterator`. -fn is_into_iterator(){} - -fn to_vector(t: T) -> Vec -where T : IntoIterator, - T::Item: Copy { - t.into_iter().collect() -} - - - -// ===================================== -// === Struct with single type param === -// ===================================== - -#[derive(Iterator, IteratorMut, Eq, PartialEq, Debug)] -pub struct PairTT(T, T); - -#[test] -fn derive_iterator_single_t() { - is_into_iterator::<& PairTT>(); - is_into_iterator::<&mut PairTT>(); - - let get_pair = || PairTT(4, 49); - - // just collect values - let pair = get_pair(); - let collected = pair.iter().copied().collect::>(); - assert_eq!(collected, vec![4, 49]); - - // IntoIterator for &mut Val - let mut pair = get_pair(); - for i in &mut pair { - *i = *i + 1 - } - assert_eq!(pair, PairTT(5, 50)); - - // iter_mut - for i in pair.iter_mut() { - *i = *i + 1 - } - assert_eq!(pair, PairTT(6, 51)); - - // IntoIterator for & Val - let pair = get_pair(); // not mut anymore - let mut sum = 0; - for i in &pair { - sum += i; - } - assert_eq!(sum, pair.0 + pair.1) -} - - - -// =================================== -// === Struct with two type params === -// =================================== - -#[derive(Iterator, IteratorMut, Eq, PartialEq, Debug)] -pub struct PairUV(U,V); - -#[test] -fn two_params() { - // verify that iter uses only the last type param field - let pair = PairUV(5, 10); - assert_eq!(to_vector(pair.iter().copied()), vec![10]); -} - - - -// ====================================== -// === Struct without any type params === -// ====================================== - -#[derive(Iterator, Eq, PartialEq, Debug)] -pub struct Monomorphic(i32); - -#[test] -fn no_params() { - // `derive(Iterator)` is no-op for structures with no type parameters. - // We just make sure that it does not cause compilation error. -} - - - -// ======================== -// === Enumeration Type === -// ======================== - -#[derive(Iterator)] -#[warn(dead_code)] // value is never read and shouldn't be -pub struct Unrecognized{ pub value : String } - -#[derive(Iterator)] -pub enum Foo { - Con1(PairUV), - Con2(PairTT), - Con3(Unrecognized) -} - -#[test] -fn enum_is_into_iterator() { - is_into_iterator::<&Foo>(); -} - -#[test] -fn enum_iter1() { - let v = Foo::Con1(PairUV(4, 50)); - let mut v_iter = v.into_iter(); - assert_eq!(*v_iter.next().unwrap(),50); - assert!(v_iter.next().is_none()); -} -#[test] -fn enum_iter2() { - let v: Foo = Foo::Con2(PairTT(6,60)); - let mut v_iter = v.into_iter(); - assert_eq!(*v_iter.next().unwrap(),6); - assert_eq!(*v_iter.next().unwrap(),60); - assert!(v_iter.next().is_none()); -} -#[test] -fn enum_iter3() { - let v: Foo = Foo::Con3(Unrecognized{value:"foo".into()}); - let mut v_iter = v.into_iter(); - assert!(v_iter.next().is_none()); -} - - - -// ======================= -// === Dependent Types === -// ======================= - -#[derive(Iterator)] -#[derive(IteratorMut)] -pub struct DependentTest { - a:T, - b:(T,U,PairUV), - // is never used, as it doesn't depend on `T` (last param) - #[allow(dead_code)] - c:PairTT, - d:(i32, Option>), -} - -#[test] -fn dependent_test_iter() { - let val = DependentTest{ - a : 1, - b : (2,3,PairUV(4,5)), - c : PairTT(6,6), - d : (7, Some(vec![8,9])), - }; - let mut v_iter = val.into_iter(); - assert_eq!(*v_iter.next().unwrap(), 1); - assert_eq!(*v_iter.next().unwrap(), 2); - // 3 is `U` in tuple - // 4 is `U` in pair - assert_eq!(*v_iter.next().unwrap(), 5); - // 7 is `i32` in tuple - assert_eq!(*v_iter.next().unwrap(), 8); - assert_eq!(*v_iter.next().unwrap(), 9); - assert!(v_iter.next().is_none()); -} diff --git a/lib/rust/enso-shapely/impl/tests/derive_clone_ref.rs b/lib/rust/enso-shapely/impl/tests/derive_clone_ref.rs deleted file mode 100644 index e1e1972947..0000000000 --- a/lib/rust/enso-shapely/impl/tests/derive_clone_ref.rs +++ /dev/null @@ -1,54 +0,0 @@ -// This module contains dead code. Its purpose is making sure that it compiles -#![allow(dead_code)] - -use enso_prelude::*; - -#[derive(Clone,CloneRef)] struct StructUnit; - -#[derive(Clone,CloneRef)] struct StructUnnamedEmpty(); - -#[derive(Clone,CloneRef)] struct StructUnnamed(Rc,Rc); - -#[derive(Clone,CloneRef)] struct StructNamedEmpty{} - -#[derive(Clone,CloneRef)] struct StructNamed{named0:Rc,named1:Rc} - -#[derive(Clone,CloneRef)] enum EnumEmpty {} - -#[derive(Clone,CloneRef)] enum Enum { - VariantUnit, - VariantNamedEmpty {}, - VariantNamed {named0:Rc,named1:Rc}, - VariantUnnamedEmpty(), - VariantUnnamed(Rc,Rc), -} - -#[derive(CloneRef,Derivative)] -#[derivative(Clone(bound=""))] -struct StructUnnamedUnbound(Rc); - -#[derive(CloneRef,Clone)] -#[clone_ref(bound="T:CloneRef")] -struct StructUnnamedBound(T); - -#[derive(CloneRef,Clone)] -#[clone_ref(bound="T:CloneRef,U:CloneRef")] -struct StructUnnamedBoundTwoPatams(T,U); - -#[derive(Clone,CloneRef)] -#[clone_ref(bound="T:Clone+Display")] -struct StructBoundGeneric(Rc); - -#[derive(CloneRef,Derivative)] -#[derivative(Clone(bound=""))] -// Note: CloneRef "knows" about `Display` bound. -struct StructGenericLifetime<'t>(Rc<&'t String>); - -#[derive(CloneRef,Derivative)] -#[derivative(Clone(bound=""))] -struct StructWhereClause(Rc) where T:Debug; - -#[derive(CloneRef,Clone)] -#[clone_ref(bound="T:CloneRef")] -// Here derive macro must correctly merge user-provided bound, generics list bound and where clause. -struct StructVariousBounds(T) where T:Debug; diff --git a/lib/rust/enso-shapely/macros/Cargo.toml b/lib/rust/enso-shapely/macros/Cargo.toml deleted file mode 100644 index 064d7a4c11..0000000000 --- a/lib/rust/enso-shapely/macros/Cargo.toml +++ /dev/null @@ -1,39 +0,0 @@ -[package] -name = "enso-shapely-macros" -version = "0.1.0" -authors = ["Enso Team "] -edition = "2018" - -description = "Automated typeclass derivation." -readme = "README.md" -homepage = "https://github.com/enso-org/enso/lib/rust/shapely/macros/" -repository = "https://github.com/enso-org/enso" -license-file = "../../../../LICENSE" - -keywords = ["typeclass", "deriving", "macro"] -categories = ["algorithms"] - -publish = true - -[lib] -proc-macro = true - -[features] -default = [] - -[dependencies] -enso-macro-utils = { version = "0.1.0" , path = "../../enso-macro-utils" } -proc-macro2 = "1.0" -quote = "1.0" -Inflector = "0.11.4" -itertools = "0.8.1" -boolinator = "2.4.0" - -[dependencies.syn] -version = "1.0" -features = [ - 'extra-traits', 'visit', 'full' -] - -[dev-dependencies] -wasm-bindgen-test = "0.2" diff --git a/lib/rust/enso-shapely/macros/README.md b/lib/rust/enso-shapely/macros/README.md deleted file mode 100644 index f5f3db89e7..0000000000 --- a/lib/rust/enso-shapely/macros/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Shapely Macros - -This crate provides macros for typeclass derivation. diff --git a/lib/rust/enso-shapely/macros/src/derive_clone_ref.rs b/lib/rust/enso-shapely/macros/src/derive_clone_ref.rs deleted file mode 100644 index ee682fa586..0000000000 --- a/lib/rust/enso-shapely/macros/src/derive_clone_ref.rs +++ /dev/null @@ -1,224 +0,0 @@ -use crate::prelude::*; - -use enso_macro_utils::field_names; -use enso_macro_utils::identifier_sequence; -use enso_macro_utils::index_sequence; -use enso_macro_utils::path_matching_ident; -use syn::Attribute; -use syn::DeriveInput; -use syn::Data; -use syn::DataEnum; -use syn::DataStruct; -use syn::Fields; -use syn::Ident; -use syn::Lit; -use syn::Meta; -use syn::MetaNameValue; -use syn::NestedMeta; -use syn::Variant; -use syn::WhereClause; -use syn::WherePredicate; - - - -// ============== -// === Consts === -// ============== - -/// Name of the custom attribute allowing customizing behavior of the generated `CloneRef` -/// implementation. -const CLONE_REF_ATTR:&str = "clone_ref"; - -/// Name of the property within customization attribute that allows defining custom bounds for -/// the generated `CloneRef` implementation. -const BOUND_NAME:&str = "bound"; - - - -// ============================ -// === CloneRef for structs === -// ============================ - -/// `clone_ref` function body for a given `struct` definition. -pub fn body_for_struct(ident:&Ident, data:&DataStruct) -> TokenStream { - match data.fields { - Fields::Unit => - // Foo - quote!( #ident ), - Fields::Unnamed(ref fields) => { - let indices = index_sequence(fields.unnamed.len()); - // Foo(self.0.clone_ref()) - quote!( - #ident(#(self.#indices.clone_ref()),*) - ) - } - Fields::Named(ref fields) => { - let names = field_names(fields); - // Foo { field0 : self.field0.clone_ref() } - quote!( - #ident { - #(#names : self.#names.clone_ref()),* - } - ) - } - } -} - - - -// ========================== -// === CloneRef for enums === -// ========================== - -/// Prepares a match arm for a single variant that `clone_ref`s such value. -pub fn arm_for_variant(data_ident:&Ident,variant:&Variant) -> TokenStream { - let fields = &variant.fields; - let variant_ident = &variant.ident; - match fields { - Fields::Unit => { - // Enum::Var => Enum::Var - quote!( - #data_ident::#variant_ident => #data_ident::#variant_ident - ) - } - Fields::Named(fields) => { - let names = field_names(fields); - // Enum::Var {field0} => Enum::Var {field0 : field0.clone_ref()} - quote!( - #data_ident::#variant_ident { #(#names),* } => - #data_ident::#variant_ident { - #( #names : #names.clone_ref() ),* - } - ) - } - Fields::Unnamed(fields) => { - let names = identifier_sequence(fields.unnamed.len()); - // Enum::Var(field0) => Enum::Var(field0.clone_ref()) - quote!( - #data_ident::#variant_ident(#(#names),*) => - #data_ident::#variant_ident( - #( #names.clone_ref() ),* - ) - ) - } - } -} - -/// `clone_ref` function body for a given `enum` definition. -pub fn body_for_enum(ident:&Ident, data:&DataEnum) -> TokenStream { - if data.variants.is_empty() { - quote!(panic!("There cannot exist value of empty enum, so its clone_ref must not be called.")) - } else { - let make_arm = |variant| arm_for_variant(ident,variant); - let arms = data.variants.iter().map(make_arm); - quote!( - match self { #(#arms),* } - ) - } -} - - - -// ============================ -// === Bounds customization === -// ============================ - -/// Checks if the given attribute is our customization attribute. -pub fn is_clone_ref_customization(attr:&Attribute) -> bool { - path_matching_ident(&attr.path,CLONE_REF_ATTR) -} - -/// Checks if the given Meta name-val pair defines user-provided bounds. -pub fn is_custom_bound(name_val:&MetaNameValue) -> bool { - path_matching_ident(&name_val.path,BOUND_NAME) -} - -/// If this is our customization attribute, we retrieve user-provided bounds for the generated -/// `CloneRef` implementation. -/// -/// Returns `None` is this is third-party attribute. -/// Panics if this is our attribute but the syntax is not correct. -pub fn clone_ref_bounds(attr:&Attribute) -> Option> { - // Silently ignore foreign attributes. Be picky only about our one. - is_clone_ref_customization(attr).then(())?; - - let meta = attr.parse_meta().expect("Failed to parse attribute contents."); - let list = match meta { - Meta::List(ml) => ml.nested, - _ => panic!("Attribute contents does not conform to meta item."), - }; - if list.len() > 1 { - panic!("Only a single entry within `{}` attribute is allowed.",CLONE_REF_ATTR); - } - let bound_value = match list.first() { - Some(NestedMeta::Meta(Meta::NameValue(name_val))) => { - if is_custom_bound(name_val) { - &name_val.lit - } else { - panic!("`{}` attribute can define value only for `{}`.",CLONE_REF_ATTR,BOUND_NAME) - } - } - Some(_) => - panic!("`{}` attribute must contain a single name=value assignment.",CLONE_REF_ATTR), - None => - panic!("`{}` attribute must not be empty.",CLONE_REF_ATTR), - }; - let bound_str = if let Lit::Str(lit_str) = bound_value { - lit_str - } else { - panic!("`{}` value must be a string literal describing `where` predicates.",BOUND_NAME) - }; - let bounds_text = format!("where {}", bound_str.value()); - let bounds = syn::parse_str::(&bounds_text); - let bounds = bounds.unwrap_or_else(|_| { - panic!("Failed to parse user-provided where clause: `{}`.",bounds_text) - }); - let ret = bounds.predicates.into_iter().collect(); - Some(ret) -} - - - -// =================== -// === Entry Point === -// =================== - -/// Derives `CloneRef` implementation, refer to `crate::derive_clone_ref` for details. -pub fn derive -(input:proc_macro::TokenStream) -> proc_macro::TokenStream { - let decl = syn::parse_macro_input!(input as DeriveInput); - let ident = &decl.ident; - let body = match &decl.data { - Data::Struct(data_struct) => body_for_struct(ident,data_struct), - Data::Enum(data_enum) => body_for_enum(ident,data_enum), - Data::Union(_) => - panic!("CloneRef cannot be derived for an untagged union input."), - }; - - let (impl_generics, ty_generics, inherent_where_clause_opt) = &decl.generics.split_for_impl(); - - // Where clause must contain both user-provided bounds and bounds inherent due to type - // declaration-level where clause. - let user_requested_bounds = decl.attrs.iter().filter_map(clone_ref_bounds).flatten(); - let mut where_clause = enso_macro_utils::new_where_clause(user_requested_bounds); - for inherent_where_clause in inherent_where_clause_opt { - where_clause.predicates.extend(inherent_where_clause.predicates.iter().cloned()) - } - - let output = quote!{ - impl #impl_generics CloneRef for #ident #ty_generics - #where_clause { - fn clone_ref(&self) -> Self { - #body - } - } - - impl #impl_generics From<& #ident #ty_generics> for #ident #ty_generics - #where_clause { - fn from(t:& #ident #ty_generics) -> Self { - t.clone_ref() - } - } - }; - output.into() -} diff --git a/lib/rust/enso-shapely/macros/src/derive_iterator.rs b/lib/rust/enso-shapely/macros/src/derive_iterator.rs deleted file mode 100644 index f6178e7b89..0000000000 --- a/lib/rust/enso-shapely/macros/src/derive_iterator.rs +++ /dev/null @@ -1,449 +0,0 @@ -use crate::prelude::*; - -use enso_macro_utils::fields_list; -use enso_macro_utils::field_ident_token; -use enso_macro_utils::type_depends_on; -use enso_macro_utils::type_matches; -use enso_macro_utils::ty_path_type_args; -use enso_macro_utils::variant_depends_on; -use boolinator::Boolinator; -use inflector::Inflector; -use itertools::Itertools; - - - -// ============= -// === IsMut === -// ============= - -/// Describes whether a mutable or immutable iterator is being derived. -#[derive(Clone,Copy,Debug,PartialEq)] -pub enum IsMut { - Mutable, - Immutable, -} - -impl IsMut { - fn is_mut(self) -> bool { - self == IsMut::Mutable - } - - /// Returns `mut` token for mutable iterator derivation. - fn to_token(self) -> Option { - self.is_mut().as_some(::default()) - } - - /// Name of method for generating iterator. - fn iter_method(self) -> TokenStream { - if self.is_mut() { - quote!(iter_mut) - } else { - quote!(iter) - } - } -} - - -// ====================== -// === DependentValue === -// ====================== - -/// A value dependent on out target parameter. -/// -/// Helper methods can be used to generate code yielding values from this. -pub struct DependentValue<'t> { - /// Type of the value (ref-stripped). - pub ty : &'t syn::Type, - /// Tokens yielding the value. - pub value : TokenStream, - /// Parameter type we want to iterate over. - pub target_param: &'t syn::GenericParam, - /// Are the value yielded as reference. - pub through_ref : bool -} - -impl<'t> DependentValue<'t> { - /// Returns Some when type is dependent and None otherwise. - pub fn try_new - (ty: &'t syn::Type, value:TokenStream, target_param:&'t syn::GenericParam) - -> Option> { - if type_depends_on(ty, target_param) { - Some(DependentValue{ty,value,target_param,through_ref:false}) - } else { - None - } - } - - /// Collects dependent sub-values from the tuple value. - pub fn collect_tuple - (tuple:&'t syn::TypeTuple, target_param:&'t syn::GenericParam) - -> Vec> { - tuple.elems.iter().enumerate().filter_map(|(ix,ty)| { - let ix = syn::Index::from(ix); - let ident = quote!(t.#ix); - DependentValue::try_new(ty,ident,target_param) - }).collect() - } - - /// Generates code yielding all values of target type accessible from this - /// value. - pub fn yield_value(&self, is_mut:IsMut) -> TokenStream { - match self.ty { - syn::Type::Tuple(tuple) => self.yield_tuple_value(tuple, is_mut), - syn::Type::Path(path) => { - if type_matches(&self.ty, &self.target_param) { - self.yield_direct_value(is_mut) - } else { - self.yield_dependent_ty_path_value(path,is_mut) - } - } - _ => - panic!("Don't know how to yield value of type {} from type {}" - , repr(&self.target_param), repr(&self.ty)), - } - } - - /// Code yielding value that directly matches the target parameter type. - pub fn yield_direct_value - (&self, is_mut:IsMut) -> TokenStream { - let value = &self.value; - let opt_mut = is_mut.to_token(); - let opt_ref = (!self.through_ref).as_some(quote!( & #opt_mut )); - - // yield &mut value; - quote!( yield #opt_ref #value; ) - } - - /// Code yielding values from tuple dependent on the target parameter type. - pub fn yield_tuple_value - (&self, ty:&syn::TypeTuple,is_mut:IsMut) - -> TokenStream { - let value = &self.value; - let mut_kwd = is_mut.to_token(); - let subfields = DependentValue::collect_tuple(ty, self.target_param); - let yield_sub = subfields.iter().map(|f| { - f.yield_value(is_mut) - }).collect_vec(); - - // yield &mut t.0; - // yield &mut t.2; - quote!( { - let t = & #mut_kwd #value; - #(#yield_sub)* - }) - } - - /// Obtain the type of iterator-yielded value. - /// - /// Panics when given a type which is not supported for derivation, like - /// having dependent type on the non-last position. - pub fn type_path_elem_type(&self, ty_path:&'t syn::TypePath) -> &syn::Type { - let mut type_args = ty_path_type_args(ty_path); - let last_arg = match type_args.pop() { - Some(arg) => arg, - None => panic!("Type {} has no segments!", repr(&ty_path)) - }; - - // Last and only last type argument is dependent. - for non_last_segment in type_args { - assert!(!type_depends_on(non_last_segment, self.target_param) - , "Type {} has non-last argument {} that depends on {}" - , repr(ty_path) - , repr(non_last_segment) - , repr(self.target_param) - ); - } - assert!(type_depends_on(last_arg, self.target_param)); - last_arg - } - - /// Code yielding values from data dependent on the target parameter type. - pub fn yield_dependent_ty_path_value - (&self, ty_path:&'t syn::TypePath, is_mut:IsMut) - -> TokenStream { - let opt_mut = is_mut.to_token(); - let elem_ty = self.type_path_elem_type(ty_path); - let elem = quote!(t); - - let elem_info = DependentValue{ - value : elem.clone(), - target_param : self.target_param, - ty : elem_ty, - through_ref : true, - }; - let yield_elem = elem_info.yield_value(is_mut); - let value = &self.value; - let iter_method = if is_mut.is_mut() { - quote!(iter_mut) - } else { - quote!(iter) - }; - - quote! { - for #opt_mut #elem in #value.#iter_method() { - #yield_elem - } - } - } - - /// Describe relevant fields of the struct definition. - pub fn collect_struct - (data:&'t syn::DataStruct, target_param:&'t syn::GenericParam) - -> Vec> { - let fields = fields_list(&data.fields); - let dep_field = fields.iter().enumerate().filter_map(|(i,f)| { - let ident = field_ident_token(f,i.into()); - let value = quote!(t.#ident); - DependentValue::try_new(&f.ty,value,target_param) - }); - dep_field.collect() - } -} - -/// Parts of derivation output that are specific to enum- or struct- target. -pub struct OutputParts<'ast> { - pub iterator_tydefs : TokenStream, - pub iter_body : TokenStream, - pub iterator_params : Vec<&'ast syn::GenericParam>, -} - -/// Common data used when generating derived Iterator impls. -/// -/// Examples are given for `pub struct Foo { foo: T }` -pub struct DerivingIterator<'ast> { - pub data : &'ast syn::Data, // { foo: T } - pub ident : &'ast syn::Ident, // Foo - pub params : Vec<&'ast syn::GenericParam>, // - pub t_iterator : syn::Ident, // FooIterator{Mut} - pub iterator : syn::Ident, // foo_iterator{_mut} - pub target_param : &'ast syn::GenericParam, // T - pub is_mut : IsMut, // are we mutable iterator? -} - -impl DerivingIterator<'_> { - pub fn new<'ast> - ( decl :&'ast syn::DeriveInput - , target_param:&'ast syn::GenericParam - , is_mut :IsMut - ) -> DerivingIterator<'ast> { - let mut_or_not = if is_mut.is_mut() { "Mut" } else { "" }; - let data = &decl.data; - let params = decl.generics.params.iter().collect(); - let ident = &decl.ident; - let t_iterator = format!("{}Iterator{}", ident, mut_or_not); - let iterator = t_iterator.to_snake_case(); - let t_iterator = syn::Ident::new(&t_iterator, Span::call_site()); - let iterator = syn::Ident::new(&iterator , Span::call_site()); - DerivingIterator { - data, - ident, - params, - t_iterator, - iterator, - target_param, - is_mut, - } - } - - /// Handles all enum-specific parts. - pub fn prepare_parts_enum(&self, data:&syn::DataEnum) -> OutputParts { - let opt_mut = &self.is_mut.to_token(); - let t_iterator = &self.t_iterator; - let ident = &self.ident; - let target_param = &self.target_param; - let iterator_params = vec!(self.target_param); - let iterator_tydefs = quote!( - // type FooIterator<'t, U> = - // Box + 't>; - // type FooIteratorMut<'t, U> = - // Box + 't>; - type #t_iterator<'t, #(#iterator_params),*> = - Box + 't>; - ); - // For types that use target type parameter, refer to their - // `IntoIterator` implementation. Otherwise, use `EmptyIterator`. - let arms = data.variants.iter().map(|var| { - let con = &var.ident; - let iter = if variant_depends_on(var, target_param) { - quote!(elem.into_iter()) - } else { - quote!(enso_shapely::EmptyIterator::new()) - }; - quote!(#ident::#con(elem) => Box::new(#iter)) - }); - - // match t { - // Foo::Con1(elem) => Box::new(elem.into_iter()), - // Foo::Con2(elem) => Box::new(enso-shapely::EmptyIterator::new()), - // } - let iter_body = quote!( match t { #(#arms,)* } ); - OutputParts{iterator_tydefs,iter_body,iterator_params} - } - - /// Handles all struct-specific parts. - pub fn prepare_parts_struct(&self, data:&syn::DataStruct) -> OutputParts { - let opt_mut = &self.is_mut.to_token(); - let t_iterator = &self.t_iterator; - let target_param = &self.target_param; - let iterator_params = self.params.clone(); - let iterator_tydefs = quote!( - // type FooIterator<'t, T> = impl Iterator; - // type FooIteratorMut<'t, T> = impl Iterator; - type #t_iterator<'t, #(#iterator_params),*> = - impl Iterator; - ); - let matched_fields = DependentValue::collect_struct(data, target_param); - let yield_fields = matched_fields.iter().map(|field| { - field.yield_value(self.is_mut) - }).collect_vec(); - - // enso-shapely::EmptyIterator::new() - let empty_body = quote! { enso_shapely::EmptyIterator::new() }; - - // enso-shapely::GeneratingIterator(move || { - // yield &t.foo; - // }) - // enso-shapely::GeneratingIterator(move || { - // yield &mut t.foo; - // }) - let body = quote! { - enso_shapely::GeneratingIterator - (move || { #(#yield_fields)* }) - }; - - let iter_body = if matched_fields.is_empty() { - empty_body - } else { - body - }; - OutputParts{iterator_tydefs,iter_body,iterator_params} - } - - /// Handles common (between enum and struct) code and assembles it all - /// into a final derivation output. - #[allow(clippy::cognitive_complexity)] - pub fn assemble_output(&self, parts:OutputParts) -> TokenStream { - let iterator_tydefs = &parts.iterator_tydefs; - let iter_body = &parts.iter_body; - let iterator_params = &parts.iterator_params; - let opt_mut = &self.is_mut.to_token(); - let iterator = &self.iterator; - let t_iterator = &self.t_iterator; - let params = &self.params; - let ident = &self.ident; - let target_param = &self.target_param; - let iter_method = &self.is_mut.iter_method(); - - quote!{ - #iterator_tydefs - - // pub fn foo_iterator<'t, T> - // (t: &'t Foo) -> FooIterator<'t, T> { - // enso-shapely::GeneratingIterator(move || { - // yield &t.foo; - // }) - // } - // pub fn foo_iterator_mut<'t, T> - // (t: &'t mut Foo) -> FooIteratorMut<'t, T> { - // enso-shapely::GeneratingIterator(move || { - // yield &t.foo; - // }) - // } - pub fn #iterator<'t, #(#params),*> - (t: &'t #opt_mut #ident<#(#params),*>) - -> #t_iterator<'t, #(#iterator_params),*> { - #iter_body - } - - // impl<'t, T> - // IntoIterator for &'t Foo { - // type Item = &'t T; - // type IntoIter = FooIterator<'t, T>; - // fn into_iter(self) -> FooIterator<'t, T> { - // foo_iterator(self) - // } - // } - // - // impl<'t, T> - // IntoIterator for &'t mut Foo { - // type Item = &'t mut T; - // type IntoIter = FooIteratorMut<'t, T>; - // fn into_iter(self) -> FooIteratorMut<'t, T> { - // foo_iterator_mut(self) - // } - // } - impl<'t, #(#params),*> - IntoIterator for &'t #opt_mut #ident<#(#params),*> { - type Item = &'t #opt_mut #target_param; - type IntoIter = #t_iterator<'t, #(#iterator_params),*>; - fn into_iter(self) -> #t_iterator<'t, #(#iterator_params),*> { - #iterator(self) - } - } - - // impl Foo { - // pub fn iter(&self) -> FooIterator<'_, T> { - // #foo_iterator(self) - // } - // pub fn iter_mut(&mut self) -> FooIteratorMut<'_, T> { - // #foo_iterator_mut (self) - // } - // } - impl<#(#params),*> #ident<#(#params),*> { - pub fn #iter_method - (& #opt_mut self) -> #t_iterator<'_, #(#iterator_params),*> { - #iterator(self) - } - } - } - } - - /// Generates the code that derives desired iterator. - pub fn output(&self) -> TokenStream { - let parts = match self.data { - syn::Data::Struct(data) => self.prepare_parts_struct(data), - syn::Data::Enum (data) => self.prepare_parts_enum (data), - _ => - panic!("Only Structs and Enums can derive(Iterator)!"), - }; - self.assemble_output(parts) - } -} - -/// Common implementation for deriving iterator through `derive(Iterator)` and -/// `derive(IteratorMut)`. -pub fn derive -(input:proc_macro::TokenStream, is_mut:IsMut) -> proc_macro::TokenStream { - let decl = syn::parse_macro_input!(input as syn::DeriveInput); - let params = &decl.generics.params.iter().collect::>(); - let output = match params.last() { - Some(last_param) => { - let der = DerivingIterator::new(&decl,last_param,is_mut); - der.output() - } - None => - TokenStream::new(), - }; - output.into() -} - -// Note [Expansion Example] -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// In order to make the definition easier to read, an example expansion of the -// following definition was provided for each quotation: -// -// #[derive(Iterator)] -// pub struct Foo { foo: T } -// -// When different output is generated for mutable and immutable content, both -// expansions are presented. -// -// For examples that are enum-specific rather than struct-specific, the -// following definition is assumed: -// -// #[derive(Iterator)] -// pub enum Foo { -// Con1(Bar), -// Con2(Baz), -// } - diff --git a/lib/rust/enso-shapely/macros/src/lib.rs b/lib/rust/enso-shapely/macros/src/lib.rs deleted file mode 100644 index 458755d75f..0000000000 --- a/lib/rust/enso-shapely/macros/src/lib.rs +++ /dev/null @@ -1,98 +0,0 @@ -//! This crate defines a custom derive macro `Iterator`. Should not be used -//! directly, but only through `enso-shapely` crate, as it provides utilities -//! necessary for the generated code to compile. - -#![feature(bool_to_option)] -#![feature(exact_size_is_empty)] -#![warn(missing_docs)] -#![warn(trivial_casts)] -#![warn(trivial_numeric_casts)] -#![warn(unused_import_braces)] -#![warn(unused_qualifications)] -#![warn(unsafe_code)] -#![warn(missing_copy_implementations)] -#![warn(missing_debug_implementations)] - -extern crate proc_macro; - -mod derive_clone_ref; -mod derive_iterator; -mod overlappable; - -mod prelude { - pub use enso_macro_utils::repr; - pub use proc_macro2::Span; - pub use proc_macro2::TokenStream; - pub use quote::quote; -} - -use crate::derive_iterator::IsMut; - -/// For `struct Foo` or `enum Foo` provides: -/// * `IntoIterator` implementations for `&'t Foo`, `iter` and `into_iter` -/// methods. -/// -/// The iterators will: -/// * for structs: go over each field that declared type is same as the -/// struct's last type parameter. -/// * enums: delegate to current constructor's nested value's iterator. -/// -/// Enums are required to use only a single element tuple-like variant. This -/// limitation should be lifted in the future. -/// -/// Any dependent type stored in struct, tuple or wrapped in enum should have -/// dependency only in its last type parameter. All dependent types that are not -/// tuples nor directly the yielded type, are required to provide `iter` method -/// that returns a compatible iterator (possible also derived). -/// -/// Caller must have the following features enabled: -/// ``` -/// #![feature(generators)] -/// #![feature(type_alias_impl_trait)] -/// ``` -/// -/// When used on type that takes no type parameters, like `struct Foo`, does -/// nothing but yields no errors. -#[proc_macro_derive(Iterator)] -pub fn derive_iterator -(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - derive_iterator::derive(input,IsMut::Immutable) -} - -/// Same as `derive(Iterator)` but generates mutable iterator. -/// -/// It is separate, as some types allow deriving immutable iterator but ont the -/// mutable one. -#[proc_macro_derive(IteratorMut)] -pub fn derive_iterator_mut -(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - derive_iterator::derive(input,IsMut::Mutable) -} - -/// Derives `CloneRef` implementation for given type. It performs `clone_ref` on every member -/// field. The input type must implement `Clone` and its every field must implement `CloneRef`. -/// -/// For generic types no bounds are introduced in the generated implementation. To customize this -/// behavior user might add `#[clone_ref(bound="…")]` attribute. Then the generated implementation -/// will use the provided bounds. -/// -/// Moreover, for a given struct `X` this macro generates also `impl From<&X> for X` which uses -/// `CloneRef` under the hood. The semantics of `CloneRef` makes each object to naturally provide -/// transformation from reference to an owned type. -/// -/// Supported inputs are structs (unit, named, unnamed), enums (with unit, named, unnamed and no -/// variants at all). Unions are currently not supported. -#[proc_macro_derive(CloneRef, attributes(clone_ref))] -pub fn derive_clone_ref -(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - derive_clone_ref::derive(input) -} - -#[allow(missing_docs)] -#[proc_macro_attribute] -pub fn overlappable -( attrs : proc_macro::TokenStream - , input : proc_macro::TokenStream -) -> proc_macro::TokenStream { - overlappable::overlappable(attrs,input) -} diff --git a/lib/rust/enso-shapely/macros/src/overlappable.rs b/lib/rust/enso-shapely/macros/src/overlappable.rs deleted file mode 100644 index 6565cdf3e1..0000000000 --- a/lib/rust/enso-shapely/macros/src/overlappable.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::prelude::*; - -use proc_macro2::Ident; - -pub fn overlappable -( attrs : proc_macro::TokenStream - , input : proc_macro::TokenStream -) -> proc_macro::TokenStream { - let _attrs: TokenStream = attrs.into(); - let decl = syn::parse_macro_input!(input as syn::ItemImpl); -// let mut path = decl.trait_.unwrap().1.clone(); -// let path = path.segments.last_mut().iter().map(|ident| { -// Ident::new(&format!("MarketCtx_{}", repr(ident)) , Span::call_site()); -// }); - - let mut marker_ctx_impl = decl; - let mut trait_ = marker_ctx_impl.trait_.as_mut(); - trait_.iter_mut().for_each(|t| { - let path = &mut t.1; - path.segments.last_mut().iter_mut().for_each(|s| { - let rr = repr(&s); - s.ident = Ident::new(&format!("MarketCtx_{}", rr) , Span::call_site()); - }); - }); - -// let mut marker_ctx_impl = decl.clone(); -// let path = &mut marker_ctx_impl.trait_.as_mut().unwrap().1; -// path.segments.last_mut().iter_mut().for_each(|s| { -// let rr = repr(&s); -// s.ident = Ident::new(&format!("MarketCtx_{}", rr) , Span::call_site()); -// }); - -// let name = repr(path); - -// let marker_ctx_impl = syn::ItemImpl { -// .. decl -// }; - - - let _output_tmp = quote! { - #marker_ctx_impl - }; - let output = quote! { - - }; -// println!("------------------"); -// println!("{}", output_tmp); - output.into() -} - diff --git a/lib/rust/flexer/Cargo.toml b/lib/rust/flexer/Cargo.toml index a7578d224c..7799368921 100644 --- a/lib/rust/flexer/Cargo.toml +++ b/lib/rust/flexer/Cargo.toml @@ -22,10 +22,10 @@ test = true bench = true [dependencies] -enso-logger = { path = "../enso-logger", version = "0.1.0" } -enso-prelude = { path = "../enso-prelude", version = "0.1.0" } -lazy-reader = { path = "../lazy-reader", version = "0.1.0" } -enso-macro-utils = { path = "../enso-macro-utils", version = "0.1.0" } +enso-logger = { version = "0.1.1" } +enso-prelude = { version = "0.1.3" } +enso-lazy-reader = { version = "0.1.0" } +enso-macro-utils = { version = "0.1.1" } itertools = "0.8" proc-macro2 = "1.0.19" diff --git a/lib/rust/flexer/src/automata/dfa.rs b/lib/rust/flexer/src/automata/dfa.rs index ef51a276d5..ccaec8489e 100644 --- a/lib/rust/flexer/src/automata/dfa.rs +++ b/lib/rust/flexer/src/automata/dfa.rs @@ -4,6 +4,8 @@ use crate::automata::alphabet; use crate::automata::state; use crate::data::matrix::Matrix; + + // ===================================== // === Deterministic Finite Automata === // ===================================== diff --git a/lib/rust/flexer/src/automata/nfa.rs b/lib/rust/flexer/src/automata/nfa.rs index 2c970b1441..8c4d3db608 100644 --- a/lib/rust/flexer/src/automata/nfa.rs +++ b/lib/rust/flexer/src/automata/nfa.rs @@ -222,6 +222,8 @@ impl From<&NFA> for DFA { } } + + // =========== // == Tests == // =========== diff --git a/lib/rust/lazy-reader/Cargo.toml b/lib/rust/lazy-reader/Cargo.toml deleted file mode 100644 index 52ce2baad4..0000000000 --- a/lib/rust/lazy-reader/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "lazy-reader" -version = "0.1.0" -authors = ["Enso Team "] -edition = "2018" - -description = "An efficient buffered reader." -readme = "README.md" -homepage = "https://github.com/enso-org/enso/lib/rust/lazy-reader" -repository = "https://github.com/enso-org/enso" -license-file = "../../../LICENSE" - -keywords = ["read", "UTF"] - -publish = false - -[lib] -name = "lazy_reader" -crate-type = ["cdylib", "rlib"] -test = true -bench = true - -[dependencies] -itertools = "0.8" -enso-prelude = { path = "../enso-prelude", version = "0.1.0" } diff --git a/lib/rust/lazy-reader/src/decoder.rs b/lib/rust/lazy-reader/src/decoder.rs deleted file mode 100644 index 63171783f5..0000000000 --- a/lib/rust/lazy-reader/src/decoder.rs +++ /dev/null @@ -1,196 +0,0 @@ -#![allow(unsafe_code)] - -//! This module exports various UTF decoders for decoding UTF32 characters. - -use std::fmt::Debug; - - - -// =============== -// === Decoder === -// =============== - -/// The error for an invalid character. -#[derive(Debug,Clone,Copy)] -pub struct InvalidChar(); - -/// Trait for decoding UTF32 characters. -pub trait Decoder { - /// The input of the decoder. - type Word : Default + Copy + Debug; - /// The maximum amount of words needed to decode one symbol. - const MAX_CODEPOINT_LEN: usize; - - /// Decodes the first symbol from the slice and returns it with its length (in words). - /// - /// This function can panic if `words.len() < MAX_CODEPOINT_LEN`. - fn decode(words:&[Self::Word]) -> Char; -} - - -// === Char === - -/// The result of `decoder.decode`. -#[derive(Debug,Clone,Copy,PartialEq)] -pub struct Char { - /// The decoded character. - pub char: Result, - /// The number of words read. - pub size: usize, -} - -impl Char { - /// Check if the character represents the end of file. - pub fn is_eof(&self) -> bool { - match self.char { - Ok(_) => false, - Err(crate::Error::EOF) => true, - Err(_) => false - } - } -} - - - -// ===================== -// === UTF-8 Decoder === -// ===================== - -/// Decoder for UTF-8. -/// -/// For more info on UTF-8 and the algorithm used see [UTF-8](https://en.wikipedia.org/wiki/UTF-8). -#[derive(Debug,Copy,Clone)] -pub struct DecoderUTF8(); - - -// === Trait Impls === - -impl Decoder for DecoderUTF8 { - type Word = u8; - - const MAX_CODEPOINT_LEN: usize = 4; - - fn decode(words: &[u8]) -> Char { - let size = match !words[0] >> 4 { - 0 => 4, - 1 => 3, - 2 | 3 => 2, - _ => 1, - }; - - let mut char = (words[0] << size >> size) as u32; - for word in &words[1..size] { - char = char << 6 | (word & 0b_0011_1111) as u32; - } - - Char{char:std::char::from_u32(char).ok_or_else(InvalidChar),size} - } -} - - - -// ====================== -// === UTF-16 Decoder === -// ====================== - -/// Decoder for UTF-16. -/// -/// For more info on UTF-16 and the algorithm used see [UTF-16](https://en.wikipedia.org/wiki/UTF-16). -#[derive(Debug,Copy,Clone)] -pub struct DecoderUTF16(); - - -// === Trait Impls === - -impl Decoder for DecoderUTF16 { - type Word = u16; - - const MAX_CODEPOINT_LEN: usize = 2; - - fn decode(words: &[u16]) -> Char { - if words[0] < 0xD800 || 0xDFFF < words[0] { - let char = Ok(unsafe{std::char::from_u32_unchecked(words[0] as u32)}); - return Char{char,size:1}; - } - let char = (((words[0] - 0xD800) as u32) << 10 | (words[1] - 0xDC00) as u32) + 0x1_0000; - - Char{char:std::char::from_u32(char).ok_or_else(InvalidChar), size:2} - } -} - - - -// ====================== -// === UTF-32 Decoder === -// ====================== - -/// Trivial decoder for UTF-32 (`char`). -#[derive(Debug,Copy,Clone)] -pub struct DecoderUTF32(); - - -// === Trait Impls === - -impl Decoder for DecoderUTF32 { - type Word = char; - - const MAX_CODEPOINT_LEN: usize = 1; - - fn decode(words: &[char]) -> Char { - Char{char:Ok(words[0]), size:1} - } -} - - - -// ============= -// === Tests === -// ============= - -#[cfg(test)] -mod tests { - use super::*; - use itertools::Itertools; - - - - #[test] - fn test_utf8() { - let string = "a.b^c! #𤭢界んにち𤭢#𤭢"; - let mut buf = string.as_bytes(); - let mut str = String::from(""); - while !buf.is_empty() { - let char = DecoderUTF8::decode(buf); - str.push(char.char.unwrap()); - buf = &buf[char.size..]; - } - assert_eq!(str, string); - } - - #[test] - fn test_utf16() { - let string = "a.b^c! #𤭢界んにち𤭢#𤭢"; - let buffer = string.encode_utf16().collect_vec(); - let mut buf = &buffer[..]; - let mut str = String::from(""); - while !buf.is_empty() { - let char = DecoderUTF16::decode(buf); - str.push(char.char.unwrap()); - buf = &buf[char.size..]; - } - assert_eq!(str, string); - } - - #[test] - fn test_utf32() { - let string = "a.b^c! #𤭢界んにち𤭢#𤭢".chars().collect_vec(); - let mut buf = &string[..]; - let mut str = vec![]; - while !buf.is_empty() { - let char = DecoderUTF32::decode(buf); - str.push(char.char.unwrap()); - buf = &buf[char.size..]; - } - assert_eq!(str, string); - } -} diff --git a/lib/rust/lazy-reader/src/lib.rs b/lib/rust/lazy-reader/src/lib.rs deleted file mode 100644 index 7609fb7d7a..0000000000 --- a/lib/rust/lazy-reader/src/lib.rs +++ /dev/null @@ -1,568 +0,0 @@ -#![feature(test)] -#![deny(unconditional_recursion)] -#![warn(missing_copy_implementations)] -#![warn(missing_debug_implementations)] -#![warn(missing_docs)] -#![warn(trivial_casts)] -#![warn(trivial_numeric_casts)] -#![warn(unsafe_code)] -#![warn(unused_import_braces)] - -//! This module exports a reader that is able to process large textual inputs in constant memory. - -pub mod decoder; - -use enso_prelude::*; - -use crate::decoder::Char; -use crate::decoder::InvalidChar; -use decoder::Decoder; - - - -// ============ -// === Read === -// ============ - -/// Trait for reading input data into a buffer. -/// -/// Compared to `std::io::Read` this reader supports multiple input encodings. -pub trait Read { - /// The type of the data in the buffer. - type Item; - - /// Fills the buffer and returns amount of elements read. - /// - /// In case it isn't possible to fill the whole buffer (i.e. if an error like EOF is - /// encountered), the buffer will be filled with all the data read before encountering such an - /// error. - fn read(&mut self,buffer:&mut [Self::Item]) -> usize; -} - - -// === Trait Impls === - -impl Read for R { - type Item = u8; - - fn read(&mut self,mut buffer:&mut [u8]) -> usize { - let length = buffer.len(); - while !buffer.is_empty() { - match self.read(buffer) { - Err(_) => break, - Ok (0) => break, - Ok (n) => { - buffer = &mut buffer[n..]; - } - } - } - length - buffer.len() - } -} - - - -// ============= -// === Error === -// ============= - -/// Set of errors returned by lazy reader. -#[derive(Debug,Clone,Copy,PartialEq,Eq)] -pub enum Error { - /// End Of Input. - EOF, - /// Couldn't decode character. - InvalidChar, - /// The lexer has found no matching rule in the current state. - EndOfGroup, -} - -impl Error { - /// The `u32` value that corresponds to EOF. - pub const END_OF_FILE:u32 = u32::max_value(); - /// The `u32` value that corresponds to an invalid unicode character. - pub const INVALID_CHAR:u32 = 0xFFFF; - /// The `u32` value corresponding to the end of group. - pub const END_OF_GROUP:u32 = u32::max_value() - 1; -} - - -// === Trait Impls === - -impl From> for decoder::Char { - fn from(char:Char) -> Self { - let size = char.size; - let char = match char.char { - Ok(char) => Ok(char), - Err(_) => Err(Error::InvalidChar), - }; - decoder::Char{char,size} - } -} - -impl From> for u32 { - fn from(char:decoder::Char) -> Self { - match char.char { - Ok (char) => char as u32, - Err(Error::EOF) => Error::END_OF_FILE, - Err(Error::InvalidChar) => Error::INVALID_CHAR, - Err(Error::EndOfGroup) => Error::END_OF_GROUP, - } - } -} - - - -// ================== -// === BookmarkId === -// ================== - -/// Strongly typed identifier of `Bookmark` -#[derive(Debug,Clone,Copy,PartialEq)] -pub struct BookmarkId { - #[allow(missing_docs)] - id: usize -} - -impl BookmarkId { - /// Creates a new bookmark handle using the specified identifier. - pub fn new(id:usize) -> BookmarkId { - BookmarkId{id} - } -} - - - -// ================== -// === LazyReader === -// ================== - -/// The behaviour needed by the lazy reader interface. -pub trait LazyReader { - /// Read the next character from input. - fn next_char(&mut self, bookmarks:&mut BookmarkManager) -> Result; - /// Advance along the input without returning the character. - fn advance_char(&mut self, bookmarks:&mut BookmarkManager); - /// Get the current character from the reader. - fn character(&self) -> decoder::Char; - /// Check if the reader has finished reading. - /// - /// A reader is finished when it has no further input left to read, and when it does not need to - /// rewind to any point. - fn finished(&self, bookmarks:&BookmarkManager) -> bool; - /// Check if the reader is empty. - fn empty(&self) -> bool; - /// Fill the buffer with words from the input. - fn fill(&mut self, bookmarks:&mut BookmarkManager); - /// Get the maximum possible rewind for the reader. - fn max_possible_rewind_len(&self, bookmarks:&BookmarkManager) -> usize; - /// Append the provided character to the reader's result. - fn append_result(&mut self, char:char); - /// Return `self.result` and sets the internal result to empty. - fn pop_result(&mut self) -> String; - /// Get the reader's current offset in the buffer. - fn offset(&self) -> usize; - /// Get an immutable reference to the reader's result. - fn result(&self) -> &String; - /// Get a mutable reference to the reader's result. - fn result_mut(&mut self) -> &mut String; - /// Get the current length of the reader's buffer. - fn buffer_len(&self) -> usize; - /// Set the buffer offset to the specified value. - fn set_offset(&mut self, off:usize); - /// Truncate the current match to the provided length. - fn truncate_match(&mut self, len:usize); -} - -/// The default size of the buffer. -pub const BUFFER_SIZE: usize = 32768; - - - -// ============== -// === Reader === -// ============== - -/// A buffered reader able to efficiently read big inputs in constant memory. -/// -/// It supports various encodings via `Decoder` and also bookmarks which allow it to return -/// back to a character at specific offset. -#[derive(Debug,Clone,PartialEq)] -pub struct Reader { - /// The reader that holds the input. - pub reader: Read, - /// The buffer that stores the input data. - pub buffer: Vec, - /// The string representation of data that has been read. - pub result: String, - /// The buffer offset of the current element read. - pub offset: usize, - /// The number of elements stored in buffer. - pub length: usize, - /// The last character read. - pub character: decoder::Char, -} - -impl> Reader { - /// Creates a new instance of the reader. - pub fn new(reader:R, _decoder:D) -> Self { - let mut reader = Reader:: { - reader, - buffer : vec![D::Word::default(); BUFFER_SIZE], - result : String::from(""), - offset : 0, - length : 0, - character : decoder::Char{char:Err(Error::EOF), size:0}, - }; - reader.length = reader.reader.read(&mut reader.buffer[..]); - reader - } -} - - -// === Trait Impls === - -impl> LazyReader for Reader { - fn next_char(&mut self, bookmarks:&mut BookmarkManager) -> Result { - if self.empty() { self.character.char = Err(Error::EOF); return Err(Error::EOF) } - - if self.offset >= self.buffer.len() - D::MAX_CODEPOINT_LEN { - self.fill(bookmarks); - } - - self.character = D::decode(&self.buffer[self.offset..]).into(); - self.offset += self.character.size; - - self.character.char - } - - fn advance_char(&mut self, bookmarks:&mut BookmarkManager) { - let _ = self.next_char(bookmarks); - } - - fn character(&self) -> Char { - self.character - } - - fn finished(&self, _bookmarks:&BookmarkManager) -> bool { - let rewinded = self.max_possible_rewind_len(_bookmarks) != 0; - self.empty() && rewinded - } - - fn empty(&self) -> bool { - self.length < self.buffer.len() && self.length <= self.offset - } - - fn fill(&mut self, bookmarks:&mut BookmarkManager) { - let len = self.buffer.len(); - let words = len - self.offset; - self.offset = self.max_possible_rewind_len(bookmarks); - if self.offset == len { - panic!("Rewind won't be possible. Buffer is too small.") - } - - bookmarks.decrease_bookmark_offsets(len - self.offset); - for i in 1..=self.offset { - self.buffer[self.offset - i] = self.buffer[len - i]; - } - self.length = self.offset + self.reader.read(&mut self.buffer[self.offset..]); - self.offset -= words; - } - - fn max_possible_rewind_len(&self, bookmarks:&BookmarkManager) -> usize { - if let Some(offset) = bookmarks.min_offset() { - return self.buffer_len() - offset - } - D::MAX_CODEPOINT_LEN - } - - fn append_result(&mut self,char:char) { - self.result.push(char); - } - - fn pop_result(&mut self) -> String { - let str = self.result.clone(); - self.result.truncate(0); - str - } - - fn offset(&self) -> usize { - self.offset - } - - fn result(&self) -> &String { - &self.result - } - - fn result_mut(&mut self) -> &mut String { - &mut self.result - } - - fn buffer_len(&self) -> usize { - self.buffer.len() - } - - fn set_offset(&mut self, off: usize) { - self.offset = off; - } - - fn truncate_match(&mut self, len: usize) { - self.result.truncate(len); - } -} - - - -// ================ -// === Bookmark === -// ================ - -/// Bookmarks a specific character in buffer, so that `LazyReader` can return to it when needed. -#[derive(Debug,Clone,Copy,Default,PartialEq)] -pub struct Bookmark { - /// The position of the bookmarked character in the `reader.buffer`. - offset: usize, - /// The length of `reader.result` up to the bookmarked character. - length: usize, - /// Whether or not the bookmark has been set by the user. - set:bool -} - - - -// ======================= -// === BookmarkManager === -// ======================= - -/// Contains and manages bookmarks for a running lexer. -/// -/// Some of its operations operate on a specific [`Reader`]. It is undefined behaviour to not pass -/// the same reader to all calls for a given bookmark manager. -#[allow(missing_docs)] -#[derive(Clone,Debug,PartialEq)] -pub struct BookmarkManager { - bookmarks: Vec, - /// The bookmark used by the flexer to mark the end of the last matched segment of the input. - pub matched_bookmark: BookmarkId, - /// A bookmark used by the flexer to deal with overlapping rules that may fail later. - pub rule_bookmark: BookmarkId, -} - -#[allow(missing_docs)] -impl BookmarkManager { - /// Create a new bookmark manager, with no associated bookmarks. - pub fn new() -> BookmarkManager { - let mut bookmarks = Vec::new(); - let matched_bookmark = BookmarkManager::make_bookmark(&mut bookmarks); - let rule_bookmark = BookmarkManager::make_bookmark(&mut bookmarks); - BookmarkManager {bookmarks,matched_bookmark,rule_bookmark} - } - - /// Create a new bookmark in the manager, returning a handle to it. - fn make_bookmark(bookmarks:&mut Vec) -> BookmarkId { - bookmarks.push(Bookmark::default()); - BookmarkId::new(bookmarks.len() - 1) - } - - /// Add a bookmark to the manager, returning a handle to that bookmark. - pub fn add_bookmark(&mut self) -> BookmarkId { - BookmarkManager::make_bookmark(&mut self.bookmarks) - } - - /// Bookmarks the current position in `reader` using `bookmark`. - pub fn bookmark(&mut self, bookmark:BookmarkId, reader:&mut R) { - self.bookmarks[bookmark.id].offset = reader.offset() - reader.character().size; - self.bookmarks[bookmark.id].length = reader.result().len(); - self.bookmarks[bookmark.id].set = true - } - - /// Unsets a bookmark. - pub fn unset(&mut self, bookmark:BookmarkId) { - self.bookmarks[bookmark.id].offset = 0; - self.bookmarks[bookmark.id].length = 0; - self.bookmarks[bookmark.id].set = false - } - - /// Decrease the offset for all bookmarks by the specified `amount` in preparation for - /// truncating the reader's buffer. - pub fn decrease_bookmark_offsets(&mut self, amount:usize) { - for bookmark in self.bookmarks.iter_mut() { - if bookmark.set { - bookmark.offset -= amount - } - } - } - - /// Rewind the reader to the position marked by `bookmark`. - pub fn rewind(&mut self, bookmark:BookmarkId, reader:&mut R) { - let bookmark = self.bookmarks.get(bookmark.id).expect("Bookmark must exist."); - reader.set_offset(bookmark.offset); - reader.truncate_match(bookmark.length); - reader.advance_char(self); - } - - /// Obtains the minimum offset from the start of the buffer for any bookmark. - pub fn min_offset(&self) -> Option { - self.bookmarks.iter().filter_map(|b| b.set.and_option(Some(b.offset))).min() - } -} - - -// === Trait Impls === - -impl Default for BookmarkManager { - fn default() -> Self { - BookmarkManager::new() - } -} - - - -// ============= -// === Tests === -// ============= - -#[cfg(test)] -mod tests { - extern crate test; - - use super::*; - use decoder::*; - - use test::Bencher; - - // ================ - // === Repeater === - // ================ - - /// Struct that holds state of `Reader` that repeats an input n times. - #[derive(Debug, Clone)] - struct Repeat { - /// The input to be repeated. - buffer: Vec, - /// The current offset of element currently read from buffer. - offset: usize, - /// How many more times the input should be repeated. - repeat: usize, - } - - /// Creates a reader that repeats an input n times. - fn repeat(input:Vec, repeat:usize) -> impl Read { - Repeat { buffer:input, repeat, offset: 0 } - } - - - // === Trait Impls === - - impl Read for Repeat { - type Item = T; - - fn read(&mut self, mut buffer:&mut [Self::Item]) -> usize { - if self.repeat == 0 { return 0 } - - let len = self.buffer.len(); - let read = buffer.len(); - - if read < len - self.offset { - buffer.copy_from_slice(&self.buffer[self.offset..self.offset + read]); - self.offset += read; - return read - } - - buffer[..len - self.offset].copy_from_slice(&self.buffer[self.offset..]); - buffer = &mut buffer[len - self.offset..]; - - let repeat = std::cmp::min(buffer.len() / len, self.repeat - 1); - self.repeat = self.repeat - repeat - 1; - for _ in 0..repeat { - buffer[..len].copy_from_slice(&self.buffer[..]); - buffer = &mut buffer[len..]; - } - - if self.repeat == 0 { - return len - self.offset + repeat * len - } - buffer.copy_from_slice(&self.buffer[..buffer.len()]); - self.offset = buffer.len(); - read - } - } - - - - // ============= - // === Utils === - // ============= - - /// Constructs an _empty_ bookmark manager for testing purposes. - pub fn bookmark_manager() -> BookmarkManager { - BookmarkManager::new() - } - - - - // ============= - // === Tests === - // ============= - - #[test] - fn test_repeater_with_small_buffer() { - let mut repeater = repeat(vec![1, 2, 3], 1); - let mut buffer = [0; 2]; - assert_eq!(repeater.read(&mut buffer), 2); - assert_eq!(&buffer, &[1, 2]); - assert_eq!(repeater.read(&mut buffer), 1); - assert_eq!(&buffer, &[3, 2]) - } - - #[test] - fn test_repeater_with_big_buffer() { - let mut repeater = repeat(vec![1, 2], 3); - let mut buffer = [0; 5]; - assert_eq!(repeater.read(&mut buffer), 5); - assert_eq!(&buffer, &[1, 2, 1, 2, 1]); - assert_eq!(repeater.read(&mut buffer), 1); - assert_eq!(&buffer, &[2, 2, 1, 2, 1]) - } - - #[test] - fn test_reader_small_input() { - let mut mgr = bookmark_manager(); - let str = "a.b^c! #𤭢界んにち𤭢#𤭢"; - let mut reader = Reader::new(str.as_bytes(), DecoderUTF8()); - let mut result = String::from(""); - while let Ok(char) = reader.next_char(&mut mgr) { - result.push(char); - } - assert_eq!(&result, str); - } - - #[test] - fn test_reader_big_input() { - let mut mgr = bookmark_manager(); - let str = "a.b^c! #𤭢界んにち𤭢#𤭢".repeat(10_000); - let mut reader = Reader::new(str.as_bytes(), DecoderUTF8()); - let mut result = String::from(""); - while let Ok(char) = reader.next_char(&mut mgr) { - mgr.bookmark(mgr.matched_bookmark,&mut reader); - result.push(char); - } - assert_eq!(&result, &str); - assert_eq!(reader.buffer.len(), BUFFER_SIZE); - } - - #[bench] - fn bench_reader(bencher:&mut Bencher) { - let run = || { - let mut mgr = bookmark_manager(); - let str = repeat("Hello, World!".as_bytes().to_vec(), 10_000_000); - let mut reader = Reader::new(str, DecoderUTF8()); - let mut count = 0; - while reader.next_char(&mut mgr) != Err(Error::EOF) { - count += 1; - } - count - }; - bencher.iter(run); - } -} diff --git a/lib/rust/lexer/definition/Cargo.toml b/lib/rust/lexer/definition/Cargo.toml index 14b8bc653d..3a37663861 100644 --- a/lib/rust/lexer/definition/Cargo.toml +++ b/lib/rust/lexer/definition/Cargo.toml @@ -13,6 +13,6 @@ bench = true [dependencies] flexer = { path = "../../flexer", version = "0.1.0" } -enso-prelude = { path = "../../enso-prelude", version = "0.1.0" } +enso-prelude = { version = "0.1.3" } uuid = { version = "0.8.1" , features = ["serde","v4","wasm-bindgen"] } diff --git a/lib/rust/lexer/generation/Cargo.toml b/lib/rust/lexer/generation/Cargo.toml index 3ec4129086..2dddfa86d2 100644 --- a/lib/rust/lexer/generation/Cargo.toml +++ b/lib/rust/lexer/generation/Cargo.toml @@ -13,7 +13,7 @@ bench = true [dependencies] flexer = { path = "../../flexer", version = "0.1.0" } -enso-prelude = { path = "../../enso-prelude", version = "0.1.0" } +enso-prelude = { version = "0.1.3" } lexer-definition = { path = "../definition", version = "0.1.0" } [build-dependencies]