pub mod list;
pub mod logic;
pub mod rc;
pub mod arith;
#[cfg(feature = "const")] pub mod set;
mod if_impl;
pub use if_impl::{If,Cond};
use crate::{LispId, engine::*};
use typenum as tn;
use std::default::Default;
#[derive(Debug,Default)]
pub struct Is;
defun!{ Is {} }
#[cfg(not(feature = "const"))]
impl<L,R> FunCall< sexpr!{L, R} > for Is
where L: LispId,
R: LispId,
L::Id: tn::IsEqual<R::Id>,
<L::Id as tn::IsEqual<R::Id>>::Output: Default,
{
type Result = <L::Id as tn::IsEqual<R::Id>>::Output;
}
#[cfg(feature = "const")]
impl<L,R> FunCall< sexpr!{L, R} > for Is
where L:LispId,
R:LispId,
IdIsEqual<L::Id, R::Id>: AsTypeBool
{
type Result = <IdIsEqual<L::Id, R::Id> as AsTypeBool>::TypeBool;
}
pub struct IdIsEqual<L,R>(std::marker::PhantomData<(L,R)>);
#[cfg(feature = "const")]
impl<const LID:u128, const RID:u128> AsTypeBool
for IdIsEqual<crate::ConstId<LID>, crate::ConstId<RID>>
where ConstBool<{LID == RID}>: AsTypeBool {
type TypeBool = <ConstBool<{LID == RID}> as AsTypeBool>::TypeBool;
}
pub trait AsTypeBool {
type TypeBool: tn::marker_traits::Bit;
}
impl AsTypeBool for ConstBool<true> {
type TypeBool = tn::True;
}
impl AsTypeBool for ConstBool<false> {
type TypeBool = tn::False;
}
pub struct ConstBool<const X:bool>;
impl<T> FunCalc<T> for Is where Is: FunCall<T>, <Is as FunCall<T>>::Result: Default {
type Result = <Is as FunCall<T>>::Result;
#[inline(always)]
fn calc(self, _:T)->Self::Result { Default::default() }
}
#[derive(Debug,Default)]
pub struct IsNot;
defun_nocalc!{() IsNot {
(L,R) {_:L, _:R} => {logic::Not, {Is, @L, @R}};
}}
#[test]
fn test_is() {
#[derive(Debug,Default)] struct A;
#[derive(Debug,Default)] struct B;
literal!{A; B}
let _: eval!{If, {Is, A, B}, A, B } = B;
let _: eval!{If, {Is, tn::True, tn::True}, A, B} = A;
let _: eval!{If, {Is, A, A}, A, B} = A;
let _: eval!{If, {Is, B, B}, A, B} = A;
fn assert_b<X:LispId>() where sexpr!{If, {Is, @X, B}, A, B}: Eval<Result = A> {
}
assert_b::<B>();
}
#[test]
fn test_is_not() {
#[derive(Debug,Default)] struct A;
#[derive(Debug,Default)] struct B;
literal!{A; B}
let _: eval!{If, {IsNot, A, B}, A, B } = A;
let _: eval!{If, {IsNot, tn::True, tn::True}, A, B} = B;
}
#[test]
fn test_partial() {
#[derive(Debug,Default)] struct A;
#[derive(Debug,Default)] struct B;
literal!{A; B}
let _: eval!{If, {{Partial, Is, A}, B}, A, B } = B;
let _: eval!{If, {Is, tn::True, tn::True}, A, B} = A;
}
#[derive(Debug,Default)]
pub struct Ret;
literal!{Ret}
impl Call for Ret { type Conv=cc::Func; }
impl<T,U> FunCall < sexpr!{T; U} > for Ret {
type Result = T;
}
impl<T,U> FunCalc < sexpr!{T; U} > for Ret {
type Result = T;
fn calc(self, sexpr_pat!{x:T; _:U}: sexpr!{T; U})-> T {
x
}
}
#[derive(Debug,Default)]
pub struct Partial;
defmacro!{Partial {
(Prefix) {; Prefix} => {Ret, @PartialImpl<Prefix>};
}}
impl<Prefix, QPrefix>
SynCalc< Prefix, QPrefix > for Partial
{
type Result = PartialImpl<Prefix>;
#[inline(always)]
fn syn_calc(self, _:QPrefix)->Self::Result {
PartialImpl(std::marker::PhantomData)
}
}
#[derive(Debug,Default)]
pub struct Phantom;
defmacro!{Phantom {}}
impl<Arg:Eval> SynCall<sexpr!{Arg}> for Phantom {
type Result = std::marker::PhantomData<Arg::Result>;
}
impl<Arg:Eval,QArg> SynCalc<sexpr!{Arg},QArg> for Phantom {
type Result = std::marker::PhantomData<Arg::Result>;
#[inline(always)]
fn syn_calc(self, _:QArg)->Self::Result { std::marker::PhantomData }
}
#[derive(Debug,Default)]
pub struct Quote;
defun_nocalc!{() Quote {
(Arg) {_:Arg} => {Ret, @crate::Quote<Arg>};
}}
#[derive(Debug)]
pub struct PartialImpl<Prefix>(std::marker::PhantomData<Prefix>);
defun_nocalc!{(Prefix) PartialImpl<Prefix> {}}
impl<T> Default for PartialImpl<T> {
#[inline(always)]
fn default()->Self { PartialImpl(std::marker::PhantomData) }
}
impl<T> From<()> for PartialImpl<T> {
#[inline(always)]
fn from(_:())->Self { Default::default() }
}
impl<Prefix, Tail> FunCall< Tail > for PartialImpl<Prefix>
where sexpr!{list::Concat, @Prefix, {list::Map, Quote, @Tail}}: Eval,
eval!{list::Concat, @Prefix, {list::Map, Quote, @Tail}}: Eval
{
type Result = <eval!{list::Concat, @Prefix, {list::Map, Quote, @Tail}} as Eval>::Result;
}