1use crate::{HCons,HNil,ops::*,marker_traits::List,ops::rc::*};
2
3use 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
52pub 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#[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#[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, ()} };
463assert_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 }
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}