1use crate::{Quote,HNil,HCons};
2
3pub fn calc<Expr,Quotes>(q:Quotes)->Expr::Result
4where Expr:Calc<Quotes> {
5 <Expr as Calc<Quotes>>::calc(q)
6}
7
8pub trait Eval {
10 type Result;
11}
12
13pub trait Calc<Quotes> {
18 type Result;
19 fn calc(q:Quotes)->Self::Result;
20}
21
22impl<T> Eval for Quote<T> {
23 type Result = T;
24}
25
26impl<T:Eval> Eval for std::marker::PhantomData<T> {
27 type Result = T::Result;
28}
29
30impl<T,U> Calc<U> for std::marker::PhantomData<T> {
31 type Result = Self;
32 #[inline(always)]
33 fn calc(_:U)->Self { std::marker::PhantomData }
34}
35
36impl<Src: Into<Dest>, Dest> Calc<Src> for Quote<Dest> {
37 type Result = Dest;
38 #[inline(always)]
39 fn calc(t:Src)->Dest { t.into() }
40}
41
42pub trait EvalList {
44 type Result;
45}
46macro_rules! eval_list { ($exprs:ty) => { <$exprs as EvalList>::Result }}
47
48pub trait CalcList<Quotes> {
49 type Result;
50 fn calc_list(q:Quotes)->Self::Result;
51}
52
53impl EvalList for HNil {
54 type Result = HNil;
55}
56
57impl CalcList<HNil> for HNil {
58 type Result = HNil;
59 #[inline(always)]
60 fn calc_list(_:HNil)->HNil { HNil }
61}
62
63impl<H:Eval, T:EvalList> EvalList for HCons<H,T> {
64 type Result = HCons<H::Result, eval_list!{T}>;
65}
66
67impl<QH, QT, H, T> CalcList<HCons<QH,QT>> for HCons<H,T>
68where H: Calc<QH>,
69 T: CalcList< QT > {
70 type Result = HCons<H::Result, T::Result>;
71 #[inline(always)]
72 fn calc_list(q: HCons<QH,QT>) -> HCons<H::Result, T::Result> {
73 HCons { head: H::calc(q.head),
74 tail: T::calc_list(q.tail)
75 }
76 }
77}
78
79impl<H:Eval, T> Eval for HCons<H,T>
80where H::Result: Call,
81 <H::Result as Call>::Conv: CallImpl<H::Result, T> {
82 type Result = <<H::Result as Call>::Conv as CallImpl<H::Result, T>>::Result;
83}
84
85impl<H:Calc<QH>, T, QH, QT> Calc<HCons<QH,QT>> for HCons<H,T>
86where H::Result: Call,
87 <H::Result as Call>::Conv: CalcImpl<H::Result, T, QT>,
88{
89 type Result = <<H::Result as Call>::Conv as CalcImpl<H::Result, T, QT>>::Result;
90 #[inline(always)]
91 fn calc(q:HCons<QH, QT>)->Self::Result {
92 let func = H::calc(q.head);
93 <H::Result as Call>::Conv::calc_impl(func, q.tail)
94 }
95}
96
97pub mod cc {
99 pub struct Func;
101
102 pub struct Syntax;
104}
105
106pub trait Call {
114 type Conv;
118}
119
120pub trait FunCall< Args >: Call<Conv=cc::Func> {
128 type Result;
129}
130
131pub trait FunCalc< Args >: Sized {
132 type Result;
133 fn calc(self, args:Args)->Self::Result;
134}
135
136pub trait SynCall< Args >: Call<Conv=cc::Syntax> {
140 type Result;
141}
142
143pub trait CallImpl<F, Args> {
146 type Result;
147}
148
149pub trait CalcImpl<F, Args, Q> {
150 type Result;
151 fn calc_impl(func:F, q:Q)->Self::Result;
152}
153
154impl<F, Args:EvalList> CallImpl<F, Args> for cc::Func
155where F:FunCall< eval_list!{Args} > {
156 type Result = <F as FunCall< eval_list!{Args}>>::Result;
157}
158
159impl<F, Args:CalcList<Q>, Q> CalcImpl<F, Args, Q> for cc::Func
160where F: FunCalc< Args::Result > {
161 type Result = <F as FunCalc< Args::Result >>::Result;
162 #[inline(always)]
163 fn calc_impl(func:F, q:Q)->Self::Result {
164 let args = Args::calc_list(q);
165 func.calc(args)
166 }
167}
168
169impl<F, Args> CallImpl<F, Args> for cc::Syntax
170where F:SynCall< Args > {
171 type Result = <F as SynCall< Args>>::Result;
172}
173
174impl<F, Args, Q> CalcImpl<F, Args, Q> for cc::Syntax
175where F:SynCalc< Args, Q > {
176 type Result = <F as SynCalc<Args, Q>>::Result;
177 #[inline(always)]
178 fn calc_impl(func:F, quotes:Q)->Self::Result {
179 func.syn_calc(quotes)
180 }
181}
182
183pub trait SynCalc< Args, Q > {
184 type Result;
185 fn syn_calc(self, quotes:Q) -> Self::Result;
186}