diff --git a/src/curry.rs b/src/curry.rs new file mode 100644 index 0000000..7ee04d8 --- /dev/null +++ b/src/curry.rs @@ -0,0 +1,63 @@ +use crate::term::*; + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\ + +impl TypeTerm { + /// transform term to have at max 2 entries in Application list + pub fn curry(mut self) -> TypeTerm { + match self { + TypeTerm::App(args) => { + if args.len() >= 2 { + let mut old_args = args.into_iter(); + let mut new_args = vec![ + old_args.next().unwrap(), + old_args.next().unwrap() + ]; + + for x in old_args { + new_args = vec![ + TypeTerm::App(new_args), + x + ]; + } + + TypeTerm::App(new_args) + } else { + TypeTerm::App(args) + } + } + + TypeTerm::Ladder(rungs) => { + TypeTerm::Ladder(rungs.into_iter().map(|r| r.curry()).collect()) + } + + _ => self + } + } + + /// summarize all curried applications into one vec + pub fn decurry(mut self) -> Self { + match self { + TypeTerm::App(mut args) => { + if args.len() > 0 { + let mut a0 = args.remove(0).decurry(); + match a0 { + TypeTerm::App(sub_args) => { + for (i,x) in sub_args.into_iter().enumerate() { + args.insert(i, x); + } + } + other => { args.insert(0, other); } + } + } + TypeTerm::App(args) + } + TypeTerm::Ladder(args) => { + TypeTerm::Ladder(args.into_iter().map(|a| a.decurry()).collect()) + } + _ => self + } + } +} + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\ diff --git a/src/lib.rs b/src/lib.rs index 1f1ffcb..0319a0c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ pub mod dict; pub mod term; pub mod lexer; pub mod parser; +pub mod curry; #[cfg(test)] mod test; diff --git a/src/test/curry.rs b/src/test/curry.rs index 1e6b676..8ad1cdf 100644 --- a/src/test/curry.rs +++ b/src/test/curry.rs @@ -1,6 +1,58 @@ +use { + crate::{term::*, dict::*, parser::*}, + std::str::FromStr +}; + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\ #[test] fn test_curry() { - // todo + assert_eq!( + TypeTerm::from_str("").unwrap().curry(), + TypeTerm::from_str("< C>").unwrap() + ); + assert_eq!( + TypeTerm::from_str("").unwrap().curry(), + TypeTerm::from_str("<< C> D>").unwrap() + ); + assert_eq!( + TypeTerm::from_str("").unwrap().curry(), + TypeTerm::from_str("<<<<<<<<< C> D> E> F> G> H> I> J> K>").unwrap() + ); + + assert_eq!( + TypeTerm::from_str("").unwrap().curry(), + TypeTerm::from_str("< C>").unwrap() + ); + assert_eq!( + TypeTerm::from_str(" ~ K").unwrap().curry(), + TypeTerm::from_str("< C~Y~Z > ~ K").unwrap() + ); } +#[test] +fn test_decurry() { + assert_eq!( + TypeTerm::from_str("< C>").unwrap().decurry(), + TypeTerm::from_str("").unwrap() + ); + assert_eq!( + TypeTerm::from_str("<< C> D>").unwrap().decurry(), + TypeTerm::from_str("").unwrap(), + ); + assert_eq!( + TypeTerm::from_str("<<<<<<<<< C> D> E> F> G> H> I> J> K>").unwrap().decurry(), + TypeTerm::from_str("").unwrap() + ); + + assert_eq!( + TypeTerm::from_str("< C>").unwrap().decurry(), + TypeTerm::from_str("").unwrap() + ); + assert_eq!( + TypeTerm::from_str("< C~Y>~K").unwrap().decurry(), + TypeTerm::from_str(" ~K").unwrap() + ); +} + +//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\