lyte 0.1.0

Rust-like typesystem created for the Lumina project
Documentation
use super::{Type, TypeData, TypeKind, TypesBuf};

pub trait TypeVisitor<D: TypeData> {
    fn map_types<F: FnMut(D::Meta, &TypeKind<D>, TypesBuf<D>) -> Type<D>>(&self, f: F) -> Self
    where
        Self: Sized;

    fn map_constr<F: FnMut(D::Meta, &TypeKind<D>) -> TypeKind<D>>(&self, mut f: F) -> Self
    where
        Self: Sized,
    {
        self.map_types(|meta, constr, params| Type {
            constr: f(meta.clone(), constr),
            meta,
            params,
        })
    }
}

impl<D: TypeData> Type<D> {
    pub fn map_constr<
        O: TypeData<Meta = D::Meta>,
        F: FnMut(D::Meta, &TypeKind<D>) -> TypeKind<O>,
    >(
        &self,
        f: &mut F,
    ) -> Type<O> {
        self.map_type(&mut |meta, constr, params| Type {
            constr: f(meta.clone(), constr),
            meta,
            params,
        })
    }

    pub fn map_type<O: TypeData, F: FnMut(D::Meta, &TypeKind<D>, Vec<Type<O>>) -> Type<O>>(
        &self,
        f: &mut F,
    ) -> Type<O> {
        let params = self.params.iter().map(|t| t.map_type(f)).collect();
        f(self.meta.clone(), &self.constr, params)
    }

    pub fn into_map_constr<O: TypeData<Meta = D::Meta>, F: FnMut(TypeKind<D>) -> TypeKind<O>>(
        self,
        f: &mut F,
    ) -> Type<O> {
        self.into_map_type(&mut |meta, constr, params| Type {
            meta,
            constr: f(constr),
            params,
        })
    }

    pub fn into_map_type<
        O: TypeData<Meta = D::Meta>,
        F: FnMut(D::Meta, TypeKind<D>, Vec<Type<O>>) -> Type<O>,
    >(
        self,
        f: &mut F,
    ) -> Type<O> {
        let params = self
            .params
            .into_iter()
            .map(|t| t.into_map_type(f))
            .collect();
        f(self.meta, self.constr, params)
    }

    pub fn substitute_self_and_meta(&self, impltor: &Type<D>, or_meta: D::Meta) -> Type<D> {
        self.map_type(&mut |_, constr, params| match constr {
            TypeKind::Self_ => {
                let mut type_ = impltor.clone();
                type_.params.extend(params);
                type_
            }
            _ => Type {
                constr: constr.clone(),
                params,
                meta: or_meta.clone(),
            },
        })
    }
}