tylisp 0.1.0

A domain-specific language for expressing complex type bounds
Documentation
//! Marker traits to ease integration with traditional Rust code

use crate::engine::Eval;
use ::typenum as tn;

/// An expression that evaluates to `True`
pub trait Pass: Eval<Result=tn::True> {}
impl<T> Pass for T where T:Eval<Result=tn::True> {}


/// An expression that evaluates to `False`
pub trait Fail: Eval<Result=tn::False> {}
impl<T> Fail for T where T:Eval<Result=tn::False> {}

pub trait List: internal::List {
    type Head;
    type Tail: internal::List;
    type IsEOL;
    const LEN: usize;

    fn split(self)->(<Self as List>::Head, <Self as List>::Tail);

    fn head(&self)->&Self::Head;
    fn tail(&self)->&Self::Tail;

    fn into_iter_as<X>(self)->Self::ListIter where Self:ListOf<X> {
        self.list_of_iter()
    }
}

pub trait ListOf<X>: List + Sized {
    type ListIter: Iterator<Item=X>;
    fn list_of_iter(self)->Self::ListIter;
}

impl<X> ListOf<X> for crate::HNil {
    type ListIter = std::iter::Empty<X>;
    fn list_of_iter(self)->Self::ListIter {
        std::iter::empty()
    }
}

impl<H,T,X> ListOf<X> for crate::HCons<H,T>
where T: ListOf<X>, H:Into<X> {
    type ListIter = std::iter::Chain<std::iter::Once<X>, T::ListIter>;
    fn list_of_iter(self)->Self::ListIter {
        std::iter::once(self.head.into()).chain(self.tail.list_of_iter())
    }
}

pub struct RefIter<'a,X:?Sized>(&'a dyn ListOfRefs<X>);

impl<'a,X:?Sized> Iterator for RefIter<'a,X> {
    type Item = &'a X;
    fn next(&mut self)->Option<&'a X> {
        let result = self.0.head_ref();
        self.0 = self.0.tail_ref();
        result
    }
}

pub trait ListOfRefs<X:?Sized> {
    fn iter(&self)->RefIter<'_,X> where Self:Sized { RefIter(self) }
    fn head_ref(&self)->Option<&X>;
    fn tail_ref(&self)->&dyn ListOfRefs<X>;
}

impl<X:?Sized> ListOfRefs<X> for crate::HNil {
    fn head_ref(&self)->Option<&X> { None }
    fn tail_ref(&self)->&dyn ListOfRefs<X> { self }
}

impl<H,T,X:?Sized> ListOfRefs<X> for crate::HCons<H,T>
where T: ListOfRefs<X>, H:AsRef<X> {
    fn head_ref(&self)->Option<&X> { Some(self.head.as_ref()) }
    fn tail_ref(&self)->&dyn ListOfRefs<X> { &self.tail }
}

impl<T> List for T where T:internal::List {
    type Head = <Self as internal::List>::IHead;
    type Tail = <Self as internal::List>::ITail;
    type IsEOL = <Self as internal::List>::IIsEOL;
    const LEN:usize = <Self as internal::List>::ILEN;

    #[inline(always)]
    fn split(self)->(<Self as List>::Head, <Self as List>::Tail) { self.i_split() }
    #[inline(always)]
    fn head(&self)->&Self::Head { self.i_head() }
    #[inline(always)]
    fn tail(&self)->&Self::Tail { self.i_tail() }
}

mod internal {
    pub trait List {
        type IHead;
        type ITail: List;
        type IIsEOL;
        const ILEN:usize;

        fn i_split(self)->(Self::IHead, Self::ITail);
        fn i_head(&self)->&Self::IHead;
        fn i_tail(&self)->&Self::ITail;
    }

    impl List for crate::HNil {
        type IHead = Self;
        type ITail = Self;
        type IIsEOL = ::typenum::True;
        const ILEN:usize = 0;

        #[inline(always)]
        fn i_split(self)->(Self,Self) { (crate::HNil, crate::HNil) }
        #[inline(always)]
        fn i_head(&self)->&Self::IHead { self }
        #[inline(always)]
        fn i_tail(&self)->&Self::ITail { self }
    }

    impl<H,T:List> List for crate::HCons<H,T>
    {
        type IHead = H;
        type ITail = T;
        type IIsEOL = ::typenum::False;
        const ILEN: usize = 1+T::ILEN;

        #[inline(always)]
        fn i_split(self)->(H,T) { let crate::HCons { head: h, tail: t} = self; (h,t) }
        #[inline(always)]
        fn i_head(&self)->&Self::IHead { &self.head }
        #[inline(always)]
        fn i_tail(&self)->&Self::ITail { &self.tail }
    }
}