tylisp/ops/
list.rs

1use crate::{HCons,HNil,ops::*,marker_traits::List,ops::rc::*};
2
3//use frunk::indices::{Here,There};
4use typenum as tn;
5
6#[derive(Debug,Default)]
7pub struct Missing;
8literal!{ Missing }
9
10#[derive(Debug,Default)]
11pub struct Here;
12
13#[derive(Debug,Default)]
14pub struct There<T>(T);
15
16non_calc_literal!{ Here; {T} There<T> }
17
18#[derive(Debug,Default)]
19pub struct EmptyP;
20defun!{ EmptyP {
21    (L:List) { _:L } => {Ret, @L::IsEOL };
22}}
23
24#[derive(Debug,Default)]
25pub struct Tail;
26defun!{ Tail {
27    (L:List) { l:L } => {Ret, @L::Tail = l.split().1 };
28}}
29
30#[derive(Debug,Default)]
31pub struct Head;
32defun!{ Head {
33    (L:List) { l:L } => {Ret, @L::Head = l.split().0 };
34}}
35
36#[derive(Debug,Default)]
37pub struct Cons;
38defun!{ Cons {
39    (H,T) { h:H, t:T } => {Ret, @HCons<H,T> = HCons{head:h, tail:t}};
40}}
41
42#[derive(Debug,Default)]
43pub struct Map;
44defun!{ Map {
45    (Func, L:List) { _:Func, list:L } {
46        let (h,t) = list.split();
47    } => {If, {EmptyP, @L}, HNil,
48              {Cons, {Func, @L::Head = h},
49                     {Map, Func, @L::Tail = t}}};
50}}
51
52/// An adapter that maps a tylisp function over a Rust iterator
53pub struct MapIter<Func,I>(I, std::marker::PhantomData<Func>);
54impl<Func,I:Iterator> MapIter<Func,I> {
55    pub fn new(iter:I)->Self { MapIter(iter, std::marker::PhantomData) }
56}
57
58impl<Func:Eval, I:Iterator> Iterator for MapIter<Func,I>
59    where sexpr!{Func::Result, @I::Item}: Calc<sexpr!{(), I::Item}>
60{
61    type Item=calc_ty!{Func::Result, @I::Item=it};
62    fn next(&mut self)->Option<Self::Item> {
63        self.0.next().map(|it| calc!{Func::Result, @I::Item=it})
64    }
65}
66
67
68#[derive(Debug,Default)]
69pub struct FoldL;
70defun!{ FoldL {
71    (Func,Acc,L:List) {_:Func, acc:Acc, list:L} {
72        let (h,t) = list.split();
73        let acc = Rc::new(acc);
74    } => {If, {EmptyP, @L},
75              {UnwrapRc, @Rc<Acc> = acc.clone()},
76              {FoldL, Func,
77                      {Func, {UnwrapRc, @Rc<Acc> = acc},
78                              @L::Head = h},
79                      @L::Tail = t}};
80}}
81
82#[derive(Debug,Default)]
83pub struct FoldR;
84defun!{ FoldR {
85    (Func,L:List,Init) {_:Func, list:L, init:Init} {
86        let (h,t) = list.split();
87        let init = Rc::new(init);
88    } => {If, {EmptyP, @L},
89              {UnwrapRc, @Rc<Init> = init.clone()},
90              {Func, @L::Head = h,
91                      {FoldR, Func,
92                              @L::Tail = t,
93                              {UnwrapRc, @Rc<Init> = init}}}};
94}}
95
96#[derive(Debug,Default)]
97pub struct MapRef;
98defun!{ MapRef {
99    ('a, Func, L:List) { _:Func, list:&'a L } =>
100        {If, {EmptyP, @L}, HNil,
101             {Cons, {Func, @ &'a L::Head = &list.head()},
102                    {MapRef, Func, @ &'a L::Tail = &list.tail()}}};
103}}
104
105#[derive(Debug,Default)]
106pub struct Filter;
107defun!{ Filter {
108    (Func, L:List) { _:Func, list:L } {
109        let (h,t) = list.split();
110    } => {If, {EmptyP, @L}, HNil,
111              {{If, {Func, @L::Head},
112                    @Prepend<L::Head> = Prepend(h),
113                    Ret},
114               {Filter, Func, @L::Tail = t}}};
115}}
116
117#[derive(Debug,Default)]
118pub struct Without;
119defun!{ Without {
120    (L:List, Needle:LispId) {_:Needle, l:L} => {Filter, {Partial, IsNot, @Needle}, @L=l};
121}}
122
123#[derive(Debug,Default)]
124pub struct DifferP;
125defun_nocalc!{() DifferP {
126    (H, T:List) { {_:H; _:T}, {} } => {Ret, @tn::True};
127    (H, T:List) { {}, {_:H; _:T} } => {Ret, @tn::True};
128    ()          { {}, {} }           => {Ret, @tn::False};
129    (H1, T1:List, H2, T2:List) { {_:H1; _:T1}, {_:H2; _:T2} }
130    => {If, {Is, @H1, @H2},
131            {DifferP, @T1, @T2},
132            @tn::True};
133}}
134
135
136#[derive(Debug,Default)]
137pub struct BuildList;
138defun!{ BuildList {
139    (Args:List) {; args:Args } => { Ret, @Args = args };
140}}
141
142pub trait CollatedBy<Test> {
143    type Passed;
144    type Failed;
145    fn collate(self)->(Self::Passed, Self::Failed);
146}
147
148impl<T> CollatedBy<T> for HNil {
149    type Passed = HNil;
150    type Failed = HNil;
151    fn collate(self)->(Self::Passed, Self::Failed) { (HNil, HNil) }
152}
153
154impl<H,T,Test,Step> CollatedBy<Test> for HCons<H,T>
155where sexpr!{Test, @H}: Eval<Result = Step>,
156      Step: CollateStep<Test, H, T>
157{
158    type Passed = Step::Passed;
159    type Failed = Step::Failed;
160    fn collate(self)->(Self::Passed, Self::Failed) {
161        Step::collate_step(self.head, self.tail)
162    }
163}
164
165pub trait CollateStep<Test, H, T> {
166    type Passed;
167    type Failed;
168    fn collate_step(h:H, t:T)->(Self::Passed, Self::Failed);
169}
170
171impl<Test, H, T> CollateStep<Test, H, T> for tn::True
172where T:CollatedBy<Test> {
173    type Passed = HCons<H, T::Passed>;
174    type Failed = T::Failed;
175    fn collate_step(h:H, t:T)->(Self::Passed, Self::Failed) {
176        let (pass, fail) = t.collate();
177        (sexpr_val!{h; pass}, fail)
178    }
179}
180
181impl<Test, H, T> CollateStep<Test, H, T> for tn::False
182where T:CollatedBy<Test> {
183    type Passed = T::Passed;
184    type Failed = HCons<H, T::Failed>;
185    fn collate_step(h:H, t:T)->(Self::Passed, Self::Failed) {
186        let (pass, fail) = t.collate();
187        (pass, sexpr_val!{h; fail})
188    }
189}
190
191use std::marker::PhantomData;
192/*
193impl<Pass,Fail,Test,T> CollatedBy<Test> for T
194where sexpr!{Collate, PhantomData<Test>, @T=self}: Calc<sexpr!{(),(),T}, Result=sexpr!{Pass,Fail}> {
195    type Passed = Pass;
196    type Failed = Fail;
197    fn collate(self)->(Self::Passed, Self::Failed) {
198        let sexpr_pat!{p:Pass, f:Fail} = calc!{Collate, PhantomData<Test>, @T=self};
199        (p,f)
200    }
201}
202*/
203
204#[derive(Debug,Default)]
205pub struct Collate;
206defun!{ Collate {
207    (Test, L:CollatedBy<Test>) { _:Test, list:L } {
208        let (pass, fail) = list.collate();
209    } => {BuildList, @L::Passed = pass, @L::Failed = fail};
210}}
211
212/*
213defun!{ Collate {
214     (Test, L:List) {test:Test, list:L } => {Collate, @Test=test, @L = list, HNil, HNil};
215     (Test, L:List, Pass:List, Fail:List) {test:Test, list:L, pass:Pass, fail:Fail} {
216        let pass = Rc::new(pass);
217        let fail = Rc::new(fail);
218     } =>
219        {If, {EmptyP, @L},
220             {BuildList, {Reverse, {UnwrapRc, @Rc<Pass> = pass.clone()}},
221                         {Reverse, {UnwrapRc, @Rc<Fail> = fail.clone()}}},
222             {CollateInner, {Phantom, {Test, @L::Head}},
223                            @Test=test,
224                            @L = list,
225                            {UnwrapRc, @Rc<Pass> = pass},
226                            {UnwrapRc, @Rc<Fail> = fail}}};
227}}
228*/
229/*
230
231#[derive(Debug,Default)]
232pub struct CollateDone;
233#[derive(Debug,Default)]
234pub struct CollateCont;
235
236literal!{CollateDone}
237literal!{CollateCont}
238
239#[derive(Debug,Default)]
240pub struct CollateStatus<Pass,Fail>{
241    pass:Pass,
242    fail:Fail,
243}
244*/
245/*
246defun!{@self (Pass, Fail) CollateStatus<Pass,Fail> {
247    (Pass,Fail,T) {_:CollateDone; _:T} =>
248        {BuildList, {Reverse, @Pass = self.pass}, {Reverse, @Fail = self.fail}};
249    (Pass,Fail,Test,L:List) {_:CollateCont, test:Test, list:L } => 
250        {CollateInner, {Phantom, {Test, @L::Head}}, @Test = test, @L = list, @Pass = self.pass, @Fail = self.fail};
251}}
252*/
253/*
254#[derive(Debug,Default)]
255pub struct CollateInner;
256defun!{ CollateInner {
257    (Test,Head,Tail,Pass:List,Fail:List) {_:std::marker::PhantomData<tn::True>, test:Test, {h:Head;t:Tail}, pass:Pass, fail:Fail} =>
258        {Collate, @Test=test, @Tail=t, {Cons, @Head=h, @Pass=pass}, @Fail=fail};
259    (Test,Head,Tail,Pass:List,Fail:List) {_:std::marker::PhantomData<tn::False>, test:Test, {h:Head;t:Tail}, pass:Pass, fail:Fail} =>
260        {Collate, @Test=test, @Tail=t, @Pass=pass, {Cons, @Head=h, @Fail=fail}};
261}}
262*/
263    
264
265/*/#[derive(Debug,Default)]
266pub struct Reverse;
267defun!{ Reverse {
268    (L) { L } => { Reverse, @L, {} };
269    (Old, New) { Old, New } =>
270        {If, { EmptyP, @Old},
271             @New, 
272             { Reverse, {Tail, @Old}, {Cons, {Head, @Old}, @New}}
273        };
274}}
275*/
276/*
277#[derive(Debug,Default)]
278pub struct Rev2;
279defun!{ Rev2 {
280    (L) { L } => { Rev2, @L, {} }
281        | l |    {    (l):L     };
282
283    (L) { {}, L } => { Ret, @L }
284        |  _, l |    {   (l):L };
285
286    (H,T,L) { {H;T}, L } => {Rev2, @T, {   @H;    @L} }
287            | {h;t}, l | => {   (t):T,  (h):H, (l):L  };
288}}
289*/
290
291#[cfg(test)]
292#[derive(Debug,Default)]
293pub struct RecTest;
294
295#[cfg(test)]
296defun!{ RecTest {
297    ()    { _:HNil, x:u32 } => { Ret, @u32 = x };
298    (H,T) { {_:H; t:T}, x:u32 } => { RecTest, @T = t, @u32 = x+1 };
299}}
300
301
302
303pub type Reverse = Rev4;
304
305#[derive(Debug,Default)]
306pub struct Rev4;
307defun!{ Rev4 {
308    (L:List) { l:L } => {Rev4, @L = l, {}};
309    (Old: List, New:List) { old:Old, new:New }
310        {let (h,t) = old.split();
311         let new = Rc::new(new);} =>
312        {If, {EmptyP, @Old},
313             {UnwrapRc, @Rc<New> = new.clone()},
314             {Rev4, @Old::Tail = t, {Cons, @Old::Head = h, {UnwrapRc, @Rc<New> = new} }}};
315}}
316
317#[derive(Debug,Default)]
318pub struct RevCont<In>(In);
319
320#[derive(Debug,Default)]
321pub struct Rev5;
322defun!{ Rev5 {
323    (L:List) { l:L } => {Rev5, @L = l, {}};
324    (Old:List, New:List) {old: Old, new:New} =>
325        {{If, {EmptyP, @Old}, Ret, @RevCont<Old> = RevCont(old)},
326         @New = new};
327}}
328
329defun!{@self (In) RevCont<In> {
330    (In:List, Out) { out:Out } { let (h,t) = self.0.split(); } =>
331        {Rev5, @In::Tail = t, {Cons, @In::Head = h, @Out = out}};  
332}}
333
334mod internal { #[derive(Debug,Default)]
335pub struct WrapMissing; }
336
337defun_nocalc!{() internal::WrapMissing {
338    (Idx) { _:Idx } => {If, {Is, Missing, @Idx},
339                            Missing,
340                            There<Idx>};
341}}
342
343#[derive(Debug,Default)]
344pub struct Find;
345defun!{ Find {
346    (Needle) { _:Needle, {} } => {Ret, Missing};
347    (Needle, H, T) { _:Needle, { _:H; _:T} } =>
348        {If, {Is, Needle, @H},
349             Here,
350             {internal::WrapMissing, {Find, Needle, @T}}
351        };
352}}
353
354#[derive(Debug,Default)]
355pub struct Any;
356defun_nocalc!{() Any {
357    (Pred, Haystack) { _:Pred, _:Haystack }
358    => {logic::Not, {Is, Missing, {FindPred, @Pred, @Haystack}}};
359}}
360
361#[derive(Debug,Default)]
362pub struct Contains;
363defun_nocalc!{() Contains {
364    (Haystack, Item) { _:Haystack, _:Item }
365    => {Any, {Partial, Is, @Item}, @Haystack};
366}}
367
368#[derive(Debug,Default)]
369pub struct All;
370defun_nocalc!{() All {
371    (Pred, Haystack) {_:Pred, _:Haystack }
372    => {logic::Not, {Any, {logic::Invert, Pred}, @Haystack}};
373}}
374
375#[derive(Debug,Default)]
376pub struct SupersetP;
377defun_nocalc!{() SupersetP {
378    (A,B) {a:A, b:B} => {All, {Partial, Contains, @A}, @B};
379}}
380
381#[derive(Debug,Default)]
382pub struct SubsetP;
383defun_nocalc!{() SubsetP {
384    (A,B) {a:A, b:B} => {SupersetP, @B, @A};
385}}
386
387#[derive(Debug,Default)]
388pub struct FindPred;
389defun_nocalc!{() FindPred {
390    (Pred) { _:Pred, {} } => {Ret, Missing};
391    (Pred, H, T) { _:Pred, { _:H; _:T }} =>
392        {If, {@Pred, @H},
393             tn::U0,
394             {internal::WrapMissing, {FindPred, @Pred, @T}}
395        };
396}}
397
398#[derive(Debug,Default)]
399pub struct Concat;
400defun!{ Concat {
401    (A:List, B:List) { a:A , b:B }
402    => {{If, {EmptyP, @A}, Ret, @ConcatCont<A> = ConcatCont(a)}, @B = b};
403}}
404
405#[derive(Debug,Default)]
406pub struct ConcatCont<L>(L);
407
408defun!{@self (H,T) ConcatCont<HCons<H,T>> {
409    (H,T,Accum) {accum:Accum} =>
410        {Cons, @H = self.0.head,
411               {Concat, @T = self.0.tail, @Accum = accum}};
412}}
413
414#[derive(Debug,Default)]
415pub struct Union;
416defun!{ Union {
417    (A:List, B:List) { a:A, b:B }
418        { let (h,t) = a.split();
419          let b = Rc::new(b);
420        }
421    => { If, {EmptyP, @A},
422             {UnwrapRc, @Rc<B> = b.clone()},
423             {Union, @A::Tail = t,
424                     {If, {Is, Missing, {Find, @A::Head, @B}},
425                          {Cons, @A::Head = h, {UnwrapRc, @Rc<B> = b.clone()}},
426                          {UnwrapRc, @Rc<B> = b}}}};
427}}
428
429#[derive(Debug,Default)]
430pub struct Intersect;
431defun!{ Intersect {
432    (A,B) { _:PhantomData<A>, b:B } => {Filter, {Partial, Contains, @A}, @B=b };
433}}
434
435#[derive(Debug,Default)]
436pub struct Remove;
437defun!{ Remove {
438    (A,B) { _:PhantomData<A>, b:B } =>
439        {Head, {Tail, {Collate, {Partial, Contains, @A}, @B=b }}};
440}}
441
442#[derive(Debug,Default)]
443pub struct SetInsert;
444
445defun!{ SetInsert {
446    (X: LispId, L:List) { x:X, l:L }
447    => {{ If, {Is, Missing, {Find, @X, @L}},
448              @Prepend<X> = Prepend(x),
449              Ret},
450        @L = l};
451}}
452
453#[derive(Debug,Default)]
454pub struct Prepend<T>(pub T);
455
456defun!{ @self (X) Prepend<X> {
457    (X, Tail) { tail:Tail } => {Cons, @X = self.0, @Tail = tail};
458}}
459
460#[test]
461fn test_reverse() {
462    type TestReverse = eval!{ Reverse, @{&'static str, u32, ()} };
463//    assert_eq!(Rev3.calc(frunk::hlist!["hello", 4u32, ()]), frunk::hlist![(), 4u32, "hello"]);
464    assert_eq!( calc!{RecTest, @sexpr!{_,_,_} = sexpr_val!{4,5,6}, @u32 = 0}, 3);
465
466    assert_eq!( calc!{Reverse, @TestReverse = sexpr_val!{(), 4, "hello"}}, sexpr_val!{"hello", 4, ()});
467
468    fn rev<List>(list:List)->calc_ty!{Reverse, @List = list} 
469    where sexpr!{Reverse, @List}: crate::engine::Calc<sexpr!{(), List}>
470    {
471        calc!{Reverse, @List = list}
472    }
473
474    struct A;
475    struct B;
476
477    rev::<_>(sexpr_val!{A,B});
478}
479
480#[cfg(test)]
481macro_rules! assert_type_eq {
482    ($a:ty, $b:ty) => { let _: ::core::marker::PhantomData<$a>=
483        <::core::marker::PhantomData<$b> as ::core::default::Default>::default();
484    }
485}
486
487#[test]
488fn test_find() {
489    #[derive(Debug,Default,Clone)] struct A;
490    #[derive(Debug,Default,Clone)] struct B;
491    #[derive(Debug,Default,Clone)] struct C;
492    #[derive(Debug,Default,Clone)] struct D;
493    literal!{A; B; C; D};
494    assert_type_eq!{ Missing, eval!{ Find, B, @{}}};
495    assert_type_eq!{ Missing, eval!{ internal::WrapMissing, Missing}};
496
497    assert_type_eq!{ Here,  eval!{ Find, B, @{B}}};
498    assert_type_eq!{ There<Here>,  eval!{ Find, B, @{A,B,C}} };
499    assert_type_eq!{ Missing, eval!{ Find, D, @{A,B,C}} };
500
501    //fn get_ref<Needle, Haystack>(list: &Haystack)->&Needle
502    //    where Haystack: ::frunk::hlist::Selector<
503    //        Needle, 
504    //        eval!{Find, @Needle, @Haystack}
505    //    >,
506    //    sexpr!{Find, @Needle, @Haystack}: Eval
507    //{
508    //    list.get()
509    //}
510
511    //let _:&B = get_ref(&::frunk::hlist![A,B,C,B]);
512
513    // Produces compile error 
514    // let _:&D = get_ref(&::frunk::hlist![A,B,C]);
515}
516
517#[test]
518fn test_concat() {
519    #[derive(Debug,Default,Eq,PartialEq)] struct A;
520    #[derive(Debug,Default,Eq,PartialEq)] struct B;
521    #[derive(Debug,Default,Eq,PartialEq)] struct C;
522    #[derive(Debug,Default,Eq,PartialEq)] struct D;
523    literal!{A; B; C; D};
524
525    assert_type_eq!{ sexpr!{A,B,C,D}, eval!{ Concat, @{A,B}, @{C,D}}};
526
527    fn concat<L1,L2>(a:L1, b:L2)-> <sexpr!{Concat, @L1, @L2} as Calc<sexpr!{(), L1, L2}>>::Result
528    where sexpr!{Concat, @L1, @L2}: Calc<sexpr!{(), L1, L2}> {
529        calc!{Concat, @L1=a, @L2=b}
530    }
531
532    assert_eq!(sexpr_val!{A,B,C,D}, concat(sexpr_val!{A,B}, sexpr_val!{C,D}));
533}
534
535#[test]
536fn test_map() {
537    type Arg = sexpr!{u32, f64};
538    let arg:Arg = sexpr_val!{3, 7.4};
539
540    let _: sexpr!{Rc<u32>, Rc<f64>} = calc!{Map, WrapRc, @Arg = arg.clone()};
541    let _: sexpr!{&u32, &f64} = calc!{MapRef, Ret, @ &Arg = &arg};
542
543}
544
545#[test]
546fn test_filter() {
547    #[derive(Debug,Default,Eq,PartialEq)] struct A;
548    #[derive(Debug,Default,Eq,PartialEq)] struct B;
549    #[derive(Debug,Default,Eq,PartialEq)] struct C;
550    #[derive(Debug,Default,Eq,PartialEq)] struct D;
551    #[derive(Debug,Default,Eq,PartialEq)] struct IsConsonant;
552
553    literal!{A; B; C; D};
554
555    use crate::ops::logic::Not;
556
557    defun!{ IsConsonant {
558        (T) { _:T } => {Not, {Is, @T, @A}};
559    }}
560
561    assert_type_eq!(sexpr!{B,C,D}, eval!{Filter, IsConsonant, @sexpr!{A,B,C,D}});
562    assert_type_eq!(sexpr!{B,C,D}, eval!{Filter, IsConsonant, @sexpr!{B,C,A,D}});
563    
564    let _: sexpr!{B,C,D} = calc!{Filter, IsConsonant, @sexpr!{A,B,C,D} = sexpr_val!{A,B,C,D}};
565    let _: sexpr!{B,C,D} = calc!{Filter, IsConsonant, @sexpr!{B,C,A,D} = sexpr_val!{B,C,A,D}};
566}
567
568#[test]
569fn test_any_all() {
570    #[derive(Debug,Default,Eq,PartialEq)] struct A;
571    #[derive(Debug,Default,Eq,PartialEq)] struct B;
572    #[derive(Debug,Default,Eq,PartialEq)] struct C;
573    #[derive(Debug,Default,Eq,PartialEq)] struct D;
574    #[derive(Debug,Default,Eq,PartialEq)] struct IsConsonant;
575
576    literal!{A; B; C; D};
577
578    use crate::ops::logic::Not;
579
580    defun!{ IsConsonant {
581        (T) { _:T } => {Not, {Is, @T, @A}};
582    }}
583
584    assert_type_eq!(tn::True, eval!{Any, IsConsonant, @sexpr!{A,B,C,D}});
585    assert_type_eq!(tn::True, eval!{Any, {logic::Invert, IsConsonant}, @sexpr!{A,B,C,D}});
586
587    assert_type_eq!(tn::False, eval!{Any, IsConsonant, @sexpr!{A,A,A,A}});
588    assert_type_eq!(tn::False, eval!{Any, {logic::Invert, IsConsonant}, @sexpr!{B,C,D}});
589
590    assert_type_eq!(tn::False, eval!{All, IsConsonant, @sexpr!{A,B,C,D}});
591    assert_type_eq!(tn::False, eval!{All, {logic::Invert, IsConsonant}, @sexpr!{A,B,C,D}});
592
593    assert_type_eq!(tn::True, eval!{All, {logic::Invert, IsConsonant}, @sexpr!{A,A,A,A}});
594    assert_type_eq!(tn::True, eval!{Any, IsConsonant, @sexpr!{B,C,D}});
595}
596
597#[test]
598fn test_without() {
599    #[derive(Debug,Default,Eq,PartialEq)] struct A;
600    #[derive(Debug,Default,Eq,PartialEq)] struct B;
601    #[derive(Debug,Default,Eq,PartialEq)] struct C;
602    #[derive(Debug,Default,Eq,PartialEq)] struct D;
603
604    literal!{A; B; C; D};
605
606    assert_type_eq!(sexpr!{B,C,D}, eval!{Without, @A, @sexpr!{A,B,C,D}});
607    assert_type_eq!(sexpr!{B,C,D}, eval!{Without, @A, @sexpr!{B,C,A,D}});
608    
609    let _: sexpr!{B,C,D} = calc!{Without, {Phantom, @A}, @sexpr!{A,B,C,D} = sexpr_val!{A,B,C,D}};
610    let _: sexpr!{B,C,D} = calc!{Without, {Phantom, @A}, @sexpr!{B,C,A,D} = sexpr_val!{B,C,A,D}};
611}
612
613#[test]
614fn test_collate_and_any() {
615    #[derive(Debug,Default,Eq,PartialEq)] struct A(u32);
616    #[derive(Debug,Default,Eq,PartialEq)] struct B;
617    #[derive(Debug,Default,Eq,PartialEq)] struct C;
618
619    literal!{A; B; C};
620
621    use crate::ops::Partial;
622
623    assert_type_eq!(sexpr!{{A,A}, {B,C}}, eval!{Collate, {Phantom, {Partial, Is, @A}}, @sexpr!{A,B,A,C}});
624    
625    let orig = sexpr_val!{A(1),B,A(2),C};
626    let (a,not_a) = CollatedBy::<partial!{Is, @A}>::collate(orig);
627
628    assert_eq!(a, sexpr_val!{A(1), A(2)});
629    assert_eq!(not_a, sexpr_val!{B,C});
630
631    assert_type_eq!(typenum::True,  eval!{Any, {Partial, Is, @A}, @{B,A,C}});
632    assert_type_eq!(typenum::False, eval!{Any, {Partial, Is, @A}, @{B,B,C}});
633}
634
635#[test]
636fn test_contains() {
637    #[derive(Debug,Default,Eq,PartialEq)] struct A;
638    #[derive(Debug,Default,Eq,PartialEq)] struct B;
639    #[derive(Debug,Default,Eq,PartialEq)] struct C;
640
641    literal!{A; B; C};
642
643    use crate::ops::Partial;
644
645    assert_type_eq!(typenum::True, eval!{Contains, @{A,B,A,C}, A});
646    assert_type_eq!(typenum::False, eval!{Contains, @{A,A,A,C}, B});
647    
648    assert_type_eq!(typenum::True, eval!{All, {Partial, Contains, @{A,B,A,C}}, @{A,B}});
649    assert_type_eq!(typenum::False, eval!{All, {Partial, Contains, @{A,A,A,C}}, @{A,B}});
650
651    assert_type_eq!(typenum::True, eval!{SupersetP, @{A,B,A,C}, @{A,B}});
652    assert_type_eq!(typenum::False, eval!{SubsetP, @{A,B,A,C}, @{A,B}});
653
654    assert_type_eq!(typenum::True, eval!{SubsetP, @{A,B}, @{A,B,A,C}});
655    assert_type_eq!(typenum::False, eval!{SupersetP, @{A,B}, @{A,C}});
656}
657
658#[test]
659fn test_union() {
660    #[derive(Debug,Default,Eq,PartialEq)] struct A;
661    #[derive(Debug,Default,Eq,PartialEq)] struct B;
662    #[derive(Debug,Default,Eq,PartialEq)] struct C;
663
664    literal!{A; B; C};
665
666    use tn::Unsigned;
667    assert_eq!{3, <eval!{Union, @sexpr!{A,B}, @sexpr!{A,C}} as List>::LEN};
668    assert_eq!{2, <eval!{Union, @sexpr!{A,B}, @sexpr!{B,A}} as List>::LEN};
669    assert_eq!{2, <eval!{Union, @sexpr!{A,B}, @sexpr!{   }} as List>::LEN};
670    assert_eq!{2, <eval!{Union, @sexpr!{   }, @sexpr!{B,A}} as List>::LEN};
671    assert_eq!{2, <eval!{Union, @sexpr!{C  }, @sexpr!{A  }} as List>::LEN};
672    assert_eq!{0, <eval!{Union, @sexpr!{   }, @sexpr!{   }} as List>::LEN};
673
674    let _:sexpr!{_,_,_} = calc!{Union, {BuildList, A, B}, {BuildList, A, C}};
675
676    let _:sexpr!{A,B} = calc!{Union, {BuildList, A}, {BuildList, B}};
677    let _:sexpr!{A,B} = calc!{Union, {BuildList}, {BuildList, A, B}};
678}
679
680#[test]
681fn test_intersection() {
682    #[derive(Debug,Default,Eq,PartialEq)] struct A;
683    #[derive(Debug,Default,Eq,PartialEq)] struct B;
684    #[derive(Debug,Default,Eq,PartialEq)] struct C;
685
686    literal!{A; B; C};
687
688    use tn::Unsigned;
689    assert_eq!{1, <eval!{Intersect, {Phantom, @{A,B}}, @{A,C}} as List>::LEN};
690    assert_eq!{2, <eval!{Intersect, {Phantom, @{A,B}}, @{B,A}} as List>::LEN};
691    assert_eq!{0, <eval!{Intersect, {Phantom, @{A,B}}, @{   }} as List>::LEN};
692    assert_eq!{0, <eval!{Intersect, {Phantom, @{   }}, @{B,A}} as List>::LEN};
693    assert_eq!{0, <eval!{Intersect, {Phantom, @{C  }}, @{A  }} as List>::LEN};
694    assert_eq!{0, <eval!{Intersect, {Phantom, @{   }}, @{   }} as List>::LEN};
695
696    let _:sexpr!{A} = calc!{Intersect, {Phantom, @{A, B}}, {BuildList, A, C}};
697
698    let _:sexpr!{A,B} = calc!{Intersect, {Phantom, @{A, B}}, {BuildList, A, B}};
699    let _:sexpr!{A,B} = calc!{Intersect, {Phantom, @{B, A}}, {BuildList, A, B}};
700}
701
702#[test]
703fn test_remove() {
704    #[derive(Debug,Default,Eq,PartialEq)] struct A;
705    #[derive(Debug,Default,Eq,PartialEq)] struct B;
706    #[derive(Debug,Default,Eq,PartialEq)] struct C;
707
708    literal!{A; B; C};
709
710    use tn::Unsigned;
711    assert_eq!{1, <eval!{Remove, {Phantom, @{A,B}}, @{A,C}} as List>::LEN};
712    assert_eq!{0, <eval!{Remove, {Phantom, @{A,B}}, @{B,A}} as List>::LEN};
713    assert_eq!{0, <eval!{Remove, {Phantom, @{A,B}}, @{   }} as List>::LEN};
714    assert_eq!{2, <eval!{Remove, {Phantom, @{   }}, @{B,A}} as List>::LEN};
715    assert_eq!{1, <eval!{Remove, {Phantom, @{C  }}, @{A  }} as List>::LEN};
716    assert_eq!{0, <eval!{Remove, {Phantom, @{   }}, @{   }} as List>::LEN};
717
718    let _:sexpr!{C} = calc!{Remove, {Phantom, @{A, B}}, {BuildList, A, C}};
719
720    let _:sexpr!{}  = calc!{Remove, {Phantom, @{A, B}}, {BuildList, A, B}};
721    let _:sexpr!{}  = calc!{Remove, {Phantom, @{B, A}}, {BuildList, A, B}};
722}
723#[test]
724fn test_set_insert() {
725    #[derive(Debug,Default,Eq,PartialEq)] struct A;
726    #[derive(Debug,Default,Eq,PartialEq)] struct B;
727    #[derive(Debug,Default,Eq,PartialEq)] struct C;
728
729    literal!{A; B; C};
730
731    use tn::Unsigned;
732    assert_eq!{2, <eval!{SetInsert, @A, @sexpr!{A,C}} as List>::LEN};
733    assert_eq!{2, <eval!{SetInsert, @A, @sexpr!{B,A}} as List>::LEN};
734    assert_eq!{3, <eval!{SetInsert, @A, @sexpr!{B,C}} as List>::LEN};
735
736    let _:sexpr!{A,B,C} = calc!{SetInsert, @A = A, {BuildList, B, C}};
737    let _:sexpr!{B,C} = calc!{SetInsert, @B = B, {BuildList, B, C}};
738}
739
740#[test]
741fn test_map_iter() {
742    #[derive(Debug,Default)] struct Double;
743    defun!{ Double {
744        (T:Copy) { x:T } => {arith::Add, @T=x, @T=x};
745    }}
746
747    assert_eq!(6, calc!{Double, @u32=3});
748    let init: Vec<u32> = vec![3,5,7];
749    let result: Vec<_> = MapIter::<Double,_>::new(init.into_iter()).collect();
750    assert_eq!(vec![6,10,14], result);
751}
752
753#[test]
754fn test_fold() {
755    assert_type_eq!{tn::U10, eval!{FoldL, arith::Add, tn::U0, @{tn::U1, tn::U2, tn::U3, tn::U4}}};
756    assert_type_eq!{tn::U10, eval!{FoldR, arith::Add, @{tn::U1, tn::U2, tn::U3, tn::U4}, tn::U0}};
757
758
759    assert_eq!{10, calc!{FoldL, arith::Add, @u32=0, {BuildList, @u32=1, @u32=2, @u32=3, @u32=4}}};
760    assert_eq!{10, calc!{FoldR, arith::Add, {BuildList, @u32=1, @u32=2, @u32=3, @u32=4}, @u32=0}};
761
762    #[derive(Debug,Default)] struct Count;
763    defun!{ Count {
764        (X, Y, Z) { x:X, y:Y, _:Z } => {arith::Add, @X=x, @Y=y};
765    }};
766
767    assert_type_eq!{tn::U4, eval!{FoldL, {Partial, Count, @tn::U1}, @tn::U0, {BuildList, @u32=1, @u32=2, @u32=3, @u32=4}}};
768}
769
770#[test]
771fn test_differ() {
772    #[derive(Debug,Default,Eq,PartialEq)] struct A;
773    #[derive(Debug,Default,Eq,PartialEq)] struct B;
774    #[derive(Debug,Default,Eq,PartialEq)] struct C;
775    #[derive(Debug,Default,Eq,PartialEq)] struct D;
776
777    literal!{A; B; C; D};
778    
779    use tn::{True,False};
780    assert_type_eq!{False, eval!{DifferP, @{}, @{}}};
781    assert_type_eq!{False, eval!{DifferP, @{A}, @{A}}};
782    assert_type_eq!{False, eval!{DifferP, @{A, B, C}, @{A, B, C}}};
783    assert_type_eq!{True,  eval!{DifferP, @{A, D, C}, @{A, B, C}}};
784    assert_type_eq!{True,  eval!{DifferP, @{A}, @{A, B}}};
785    assert_type_eq!{True,  eval!{DifferP, @{B}, @{A, B}}};
786    assert_type_eq!{True,  eval!{DifferP, @{A, B}, @{A}}};
787    assert_type_eq!{True,  eval!{DifferP, @{A, B}, @{B}}};
788}