tylisp/
marker_traits.rs

1//! Marker traits to ease integration with traditional Rust code
2
3use crate::engine::Eval;
4use ::typenum as tn;
5
6/// An expression that evaluates to `True`
7pub trait Pass: Eval<Result=tn::True> {}
8impl<T> Pass for T where T:Eval<Result=tn::True> {}
9
10
11/// An expression that evaluates to `False`
12pub trait Fail: Eval<Result=tn::False> {}
13impl<T> Fail for T where T:Eval<Result=tn::False> {}
14
15pub trait List: internal::List {
16    type Head;
17    type Tail: internal::List;
18    type IsEOL;
19    const LEN: usize;
20
21    fn split(self)->(<Self as List>::Head, <Self as List>::Tail);
22
23    fn head(&self)->&Self::Head;
24    fn tail(&self)->&Self::Tail;
25
26    fn into_iter_as<X>(self)->Self::ListIter where Self:ListOf<X> {
27        self.list_of_iter()
28    }
29}
30
31pub trait ListOf<X>: List + Sized {
32    type ListIter: Iterator<Item=X>;
33    fn list_of_iter(self)->Self::ListIter;
34}
35
36impl<X> ListOf<X> for crate::HNil {
37    type ListIter = std::iter::Empty<X>;
38    fn list_of_iter(self)->Self::ListIter {
39        std::iter::empty()
40    }
41}
42
43impl<H,T,X> ListOf<X> for crate::HCons<H,T>
44where T: ListOf<X>, H:Into<X> {
45    type ListIter = std::iter::Chain<std::iter::Once<X>, T::ListIter>;
46    fn list_of_iter(self)->Self::ListIter {
47        std::iter::once(self.head.into()).chain(self.tail.list_of_iter())
48    }
49}
50
51pub struct RefIter<'a,X:?Sized>(&'a dyn ListOfRefs<X>);
52
53impl<'a,X:?Sized> Iterator for RefIter<'a,X> {
54    type Item = &'a X;
55    fn next(&mut self)->Option<&'a X> {
56        let result = self.0.head_ref();
57        self.0 = self.0.tail_ref();
58        result
59    }
60}
61
62pub trait ListOfRefs<X:?Sized> {
63    fn iter(&self)->RefIter<'_,X> where Self:Sized { RefIter(self) }
64    fn head_ref(&self)->Option<&X>;
65    fn tail_ref(&self)->&dyn ListOfRefs<X>;
66}
67
68impl<X:?Sized> ListOfRefs<X> for crate::HNil {
69    fn head_ref(&self)->Option<&X> { None }
70    fn tail_ref(&self)->&dyn ListOfRefs<X> { self }
71}
72
73impl<H,T,X:?Sized> ListOfRefs<X> for crate::HCons<H,T>
74where T: ListOfRefs<X>, H:AsRef<X> {
75    fn head_ref(&self)->Option<&X> { Some(self.head.as_ref()) }
76    fn tail_ref(&self)->&dyn ListOfRefs<X> { &self.tail }
77}
78
79impl<T> List for T where T:internal::List {
80    type Head = <Self as internal::List>::IHead;
81    type Tail = <Self as internal::List>::ITail;
82    type IsEOL = <Self as internal::List>::IIsEOL;
83    const LEN:usize = <Self as internal::List>::ILEN;
84
85    #[inline(always)]
86    fn split(self)->(<Self as List>::Head, <Self as List>::Tail) { self.i_split() }
87    #[inline(always)]
88    fn head(&self)->&Self::Head { self.i_head() }
89    #[inline(always)]
90    fn tail(&self)->&Self::Tail { self.i_tail() }
91}
92
93mod internal {
94    pub trait List {
95        type IHead;
96        type ITail: List;
97        type IIsEOL;
98        const ILEN:usize;
99
100        fn i_split(self)->(Self::IHead, Self::ITail);
101        fn i_head(&self)->&Self::IHead;
102        fn i_tail(&self)->&Self::ITail;
103    }
104
105    impl List for crate::HNil {
106        type IHead = Self;
107        type ITail = Self;
108        type IIsEOL = ::typenum::True;
109        const ILEN:usize = 0;
110
111        #[inline(always)]
112        fn i_split(self)->(Self,Self) { (crate::HNil, crate::HNil) }
113        #[inline(always)]
114        fn i_head(&self)->&Self::IHead { self }
115        #[inline(always)]
116        fn i_tail(&self)->&Self::ITail { self }
117    }
118
119    impl<H,T:List> List for crate::HCons<H,T>
120    {
121        type IHead = H;
122        type ITail = T;
123        type IIsEOL = ::typenum::False;
124        const ILEN: usize = 1+T::ILEN;
125
126        #[inline(always)]
127        fn i_split(self)->(H,T) { let crate::HCons { head: h, tail: t} = self; (h,t) }
128        #[inline(always)]
129        fn i_head(&self)->&Self::IHead { &self.head }
130        #[inline(always)]
131        fn i_tail(&self)->&Self::ITail { &self.tail }
132    }
133}