1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
//! A port of Haskell's [Uniplate](https://hackage.haskell.org/package/uniplate) in Rust.
//!
//!
//! # Examples
//!
//! ## A Calculator Input Language
//!
//! Consider the AST of a calculator input language:
//!
//! ```
//! pub enum AST {
//! Int(i32),
//! Add(Box<AST>,Box<AST>),
//! Sub(Box<AST>,Box<AST>),
//! Div(Box<AST>,Box<AST>),
//! Mul(Box<AST>,Box<AST>)
//! }
//!```
//!
//! Using uniplate, one can implement a single function for this AST that can be used in a whole
//! range of traversals.
//!
//! While this does not seem helpful in this toy example, the benefits amplify when the number of
//! enum variants increase, and the different types contained in their fields increase.
//!
//!
//! The below example implements [`Uniplate`](uniplate::Uniplate) for this language AST, and uses uniplate methods to
//! evaluate the encoded equation.
//!
//!```
//! use uniplate::uniplate::{Uniplate, UniplateError};
//!
//! #[derive(Clone,Eq,PartialEq,Debug)]
//! pub enum AST {
//! Int(i32),
//! Add(Box<AST>,Box<AST>),
//! Sub(Box<AST>,Box<AST>),
//! Div(Box<AST>,Box<AST>),
//! Mul(Box<AST>,Box<AST>)
//! }
//!
//! // In the future would be automatically derived.
//! impl Uniplate for AST {
//! fn uniplate(&self) -> (Vec<AST>, Box<dyn Fn(Vec<AST>) -> Result<AST, UniplateError> +'_>) {
//! let context: Box<dyn Fn(Vec<AST>) -> Result<AST, UniplateError>> = match self {
//! AST::Int(i) => Box::new(|_| Ok(AST::Int(*i))),
//! AST::Add(_, _) => Box::new(|exprs: Vec<AST>| Ok(AST::Add(Box::new(exprs[0].clone()),Box::new(exprs[1].clone())))),
//! AST::Sub(_, _) => Box::new(|exprs: Vec<AST>| Ok(AST::Sub(Box::new(exprs[0].clone()),Box::new(exprs[1].clone())))),
//! AST::Div(_, _) => Box::new(|exprs: Vec<AST>| Ok(AST::Div(Box::new(exprs[0].clone()),Box::new(exprs[1].clone())))),
//! AST::Mul(_, _) => Box::new(|exprs: Vec<AST>| Ok(AST::Mul(Box::new(exprs[0].clone()),Box::new(exprs[1].clone()))))
//! };
//!
//! let children: Vec<AST> = match self {
//! AST::Add(a,b) => vec![*a.clone(),*b.clone()],
//! AST::Sub(a,b) => vec![*a.clone(),*b.clone()],
//! AST::Div(a,b) => vec![*a.clone(),*b.clone()],
//! AST::Mul(a,b) => vec![*a.clone(),*b.clone()],
//! _ => vec![]
//! };
//!
//! (children,context)
//! }
//! }
//!
//! pub fn my_rule(e: AST) -> AST{
//! match e {
//! AST::Int(a) => AST::Int(a),
//! AST::Add(a,b) => {match (&*a,&*b) { (AST::Int(a), AST::Int(b)) => AST::Int(a+b), _ => AST::Add(a,b) }}
//! AST::Sub(a,b) => {match (&*a,&*b) { (AST::Int(a), AST::Int(b)) => AST::Int(a-b), _ => AST::Sub(a,b) }}
//! AST::Mul(a,b) => {match (&*a,&*b) { (AST::Int(a), AST::Int(b)) => AST::Int(a*b), _ => AST::Mul(a,b) }}
//! AST::Div(a,b) => {match (&*a,&*b) { (AST::Int(a), AST::Int(b)) => AST::Int(a/b), _ => AST::Div(a,b) }}
//! }
//! }
//! pub fn main() {
//! let ast = AST::Add(
//! Box::new(AST::Int(1)),
//! Box::new(AST::Mul(
//! Box::new(AST::Int(2)),
//! Box::new(AST::Div(
//! Box::new(AST::Add(Box::new(AST::Int(1)),Box::new(AST::Int(2)))),
//! Box::new(AST::Int(3))
//! )))));
//!
//! let new_ast = ast.transform(my_rule);
//! assert!(new_ast.is_ok());
//! println!("{:?}",new_ast);
//! assert_eq!(new_ast.unwrap(), AST::Int(3));
//! }
//! ```
//!
//! ....MORE DOCS TO COME....
//!
//! # Acknowledgements / Related Work
//!
//! *This crate implements programming constructs from the following Haskell libraries and
//! papers:*
//!
//! * [Uniplate](https://hackage.haskell.org/package/uniplate).
//!
//! * Neil Mitchell and Colin Runciman. 2007. Uniform boilerplate and list processing. In
//! Proceedings of the ACM SIGPLAN workshop on Haskell workshop (Haskell '07). Association for
//! Computing Machinery, New York, NY, USA, 49–60. <https://doi.org/10.1145/1291201.1291208>
//! [(free copy)](https://www.cs.york.ac.uk/plasma/publications/pdf/MitchellRuncimanHW07.pdf)
//!
//! * Huet G. The Zipper. Journal of Functional Programming. 1997;7(5):549–54. <https://doi.org/10.1017/S0956796897002864>
//! [(free copy)](https://www.cambridge.org/core/services/aop-cambridge-core/content/view/0C058890B8A9B588F26E6D68CF0CE204/S0956796897002864a.pdf/zipper.pdf)
pub mod biplate;
mod tree;
pub mod uniplate;
pub use tree::Tree;
#[doc(hidden)]
pub mod test_common;