mod unwrap_expr;
pub use unwrap_expr::*;
use std::marker::PhantomData;
use internal::*;
use crate::r#type::*;
pub struct ExprWrapper<K: Kind + ?Sized> {
k: PhantomData<K>,
}
impl<K: Kind + ?Sized> Kind for ExprWrapper<K> {}
impl<K: KindWithDefault> EqualityComparableKind for ExprWrapper<K> {
type Eq<X: Expr<ExprWrapper<K>>, Y: Expr<ExprWrapper<K>>> = Equals<Type,
WrapType<UnwrapExpr<K, X>>,
WrapType<UnwrapExpr<K, Y>>
>;
}
impl<K: KindWithDefault> KindWithDebugForm for ExprWrapper<K> {
type DebugForm<E: Expr<ExprWrapper<K>>> = WrapExpr<ExprWrapper<K>, WrapExpr<K, UnwrapExpr<K, E>>>;
}
impl<K: KindWithDefault> KindWithDefault for ExprWrapper<K> {
type Default = WrapExpr<K, K::Default>;
}
meta!{
pub struct WrapExpr<
K: Kind,
E: Expr<K>
>: Expr<ExprWrapper<K>> {
type Eval = WrapExprWrapperValue<K, WrapExprValue<K, E>>;
}
}
mod internal {
pub use crate::*;
pub use super::*;
pub trait ExprWrapperValue<K: Kind> {
type UnconstrainedImpl;
}
meta!{
pub struct WrapExprWrapperValue<
K: Kind,
E: ExprWrapperValue<K>
>: Value<ExprWrapper<K>> {
type UnconstrainedImpl = <E as ExprWrapperValue<K>>::UnconstrainedImpl;
}
pub struct WrapExprValue<
K: Kind,
E: Expr<K>
>: ExprWrapperValue<K> {
type UnconstrainedImpl = E;
}
}
}
#[cfg(test)]
#[allow(dead_code)]
mod tests {
use crate::*;
use crate::list::*;
use crate::r#type::*;
use crate::expr_wrapper::*;
use crate::bool::*;
#[test]
fn equals() {
meta_assert_eq!(ExprWrapper<List<Type>>, WrapExpr<List<Type>, EmptyList<Type>>, WrapExpr<List<Type>, EmptyList<Type>>);
meta_assert_not_eq!(ExprWrapper<Bool>, WrapExpr<Bool, And<True, True>>, WrapExpr<Bool, True>);
}
#[test]
fn default() {
meta_assert_eq!(ExprWrapper<List<Type>>, Default<ExprWrapper<List<Type>>>, WrapExpr<List<Type>, EmptyList<Type>>);
}
#[test]
fn debug_form() {
meta_assert_eq!(ExprWrapper<ExprWrapper<Type>>, DebugForm<ExprWrapper<Type>, WrapExpr<Type, WrapType<i32>>>, WrapExpr<ExprWrapper<Type>, WrapExpr<Type, WrapType<i32>>>);
}
}