xref: /aosp_15_r20/external/google-fruit/include/fruit/impl/meta/eval.h (revision a65addddcf69f38db5b288d787b6b7571a57bb8f)
1*a65addddSAndroid Build Coastguard Worker /*
2*a65addddSAndroid Build Coastguard Worker  * Copyright 2014 Google Inc. All rights reserved.
3*a65addddSAndroid Build Coastguard Worker  *
4*a65addddSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*a65addddSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*a65addddSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*a65addddSAndroid Build Coastguard Worker  *
8*a65addddSAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
9*a65addddSAndroid Build Coastguard Worker  *
10*a65addddSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*a65addddSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*a65addddSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*a65addddSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*a65addddSAndroid Build Coastguard Worker  * limitations under the License.
15*a65addddSAndroid Build Coastguard Worker  */
16*a65addddSAndroid Build Coastguard Worker 
17*a65addddSAndroid Build Coastguard Worker #ifndef FRUIT_META_EVAL_H
18*a65addddSAndroid Build Coastguard Worker #define FRUIT_META_EVAL_H
19*a65addddSAndroid Build Coastguard Worker 
20*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/basics.h>
21*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/errors.h>
22*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/logical_operations.h>
23*a65addddSAndroid Build Coastguard Worker 
24*a65addddSAndroid Build Coastguard Worker #include <functional>
25*a65addddSAndroid Build Coastguard Worker 
26*a65addddSAndroid Build Coastguard Worker namespace fruit {
27*a65addddSAndroid Build Coastguard Worker namespace impl {
28*a65addddSAndroid Build Coastguard Worker namespace meta {
29*a65addddSAndroid Build Coastguard Worker 
30*a65addddSAndroid Build Coastguard Worker template <typename MetaExpr>
31*a65addddSAndroid Build Coastguard Worker struct DoEval;
32*a65addddSAndroid Build Coastguard Worker 
33*a65addddSAndroid Build Coastguard Worker // General case, meta-constant.
34*a65addddSAndroid Build Coastguard Worker template <typename MetaExpr>
35*a65addddSAndroid Build Coastguard Worker struct DoEval {
36*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS
static_warningDoEval37*a65addddSAndroid Build Coastguard Worker   constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) {
38*a65addddSAndroid Build Coastguard Worker     return true;
39*a65addddSAndroid Build Coastguard Worker   }
40*a65addddSAndroid Build Coastguard Worker   static_assert(static_warning(), "");
41*a65addddSAndroid Build Coastguard Worker #endif
42*a65addddSAndroid Build Coastguard Worker   using type = MetaExpr;
43*a65addddSAndroid Build Coastguard Worker };
44*a65addddSAndroid Build Coastguard Worker 
45*a65addddSAndroid Build Coastguard Worker template <typename Type>
46*a65addddSAndroid Build Coastguard Worker struct SimpleIsError {
47*a65addddSAndroid Build Coastguard Worker   static constexpr bool value = false;
48*a65addddSAndroid Build Coastguard Worker };
49*a65addddSAndroid Build Coastguard Worker template <typename ErrorTag, typename... ErrorArgs>
50*a65addddSAndroid Build Coastguard Worker struct SimpleIsError<Error<ErrorTag, ErrorArgs...>> {
51*a65addddSAndroid Build Coastguard Worker   static constexpr bool value = true;
52*a65addddSAndroid Build Coastguard Worker };
53*a65addddSAndroid Build Coastguard Worker 
54*a65addddSAndroid Build Coastguard Worker #if FRUIT_EXTRA_DEBUG
55*a65addddSAndroid Build Coastguard Worker 
56*a65addddSAndroid Build Coastguard Worker // For debugging, we use a separate DoEvalFun so that we get longer (and more informative)
57*a65addddSAndroid Build Coastguard Worker // instantiation traces.
58*a65addddSAndroid Build Coastguard Worker 
59*a65addddSAndroid Build Coastguard Worker template <typename MetaFun, typename... Params>
60*a65addddSAndroid Build Coastguard Worker struct DoEvalFun {
61*a65addddSAndroid Build Coastguard Worker   using type =
62*a65addddSAndroid Build Coastguard Worker       typename DoEval<typename std::conditional<StaticOr<SimpleIsError<Params>::value...>::value, ExtractFirstError,
63*a65addddSAndroid Build Coastguard Worker                                                 MetaFun>::type::template apply<Params...>::type>::type;
64*a65addddSAndroid Build Coastguard Worker };
65*a65addddSAndroid Build Coastguard Worker 
66*a65addddSAndroid Build Coastguard Worker template <typename MetaFun, typename... MetaExprs>
67*a65addddSAndroid Build Coastguard Worker struct DoEval<MetaFun(MetaExprs...)> {
68*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS
69*a65addddSAndroid Build Coastguard Worker   constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) {
70*a65addddSAndroid Build Coastguard Worker     return true;
71*a65addddSAndroid Build Coastguard Worker   }
72*a65addddSAndroid Build Coastguard Worker   static_assert(static_warning(), "");
73*a65addddSAndroid Build Coastguard Worker #endif
74*a65addddSAndroid Build Coastguard Worker   using type = typename DoEvalFun<MetaFun, typename DoEval<MetaExprs>::type...>::type;
75*a65addddSAndroid Build Coastguard Worker };
76*a65addddSAndroid Build Coastguard Worker 
77*a65addddSAndroid Build Coastguard Worker // Similar to the previous specialization, but this will be selected when the function signature
78*a65addddSAndroid Build Coastguard Worker // became a function pointer (this happens when a signature parameter is itself a signature).
79*a65addddSAndroid Build Coastguard Worker template <typename MetaFun, typename... MetaExprs>
80*a65addddSAndroid Build Coastguard Worker struct DoEval<MetaFun (*)(MetaExprs...)> {
81*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS
82*a65addddSAndroid Build Coastguard Worker   constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) {
83*a65addddSAndroid Build Coastguard Worker     return true;
84*a65addddSAndroid Build Coastguard Worker   }
85*a65addddSAndroid Build Coastguard Worker   static_assert(static_warning(), "");
86*a65addddSAndroid Build Coastguard Worker #endif
87*a65addddSAndroid Build Coastguard Worker   using type = typename DoEvalFun<MetaFun, typename DoEval<MetaExprs>::type...>::type;
88*a65addddSAndroid Build Coastguard Worker };
89*a65addddSAndroid Build Coastguard Worker 
90*a65addddSAndroid Build Coastguard Worker #else // FRUIT_EXTRA_DEBUG
91*a65addddSAndroid Build Coastguard Worker 
92*a65addddSAndroid Build Coastguard Worker template <typename MetaFun, typename... MetaExprs>
93*a65addddSAndroid Build Coastguard Worker struct DoEval<MetaFun(MetaExprs...)> {
94*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS
95*a65addddSAndroid Build Coastguard Worker   constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) {
96*a65addddSAndroid Build Coastguard Worker     return true;
97*a65addddSAndroid Build Coastguard Worker   }
98*a65addddSAndroid Build Coastguard Worker   static_assert(static_warning(), "");
99*a65addddSAndroid Build Coastguard Worker #endif
100*a65addddSAndroid Build Coastguard Worker   using type = typename DoEval<typename std::conditional<
101*a65addddSAndroid Build Coastguard Worker       StaticOr<SimpleIsError<typename DoEval<MetaExprs>::type>::value...>::value, ExtractFirstError,
102*a65addddSAndroid Build Coastguard Worker       MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type;
103*a65addddSAndroid Build Coastguard Worker };
104*a65addddSAndroid Build Coastguard Worker 
105*a65addddSAndroid Build Coastguard Worker // Similar to the previous specialization, but this will be selected when the function signature
106*a65addddSAndroid Build Coastguard Worker // became a function pointer (this happens when a signature parameter is itself a signature).
107*a65addddSAndroid Build Coastguard Worker template <typename MetaFun, typename... MetaExprs>
108*a65addddSAndroid Build Coastguard Worker struct DoEval<MetaFun (*)(MetaExprs...)> {
109*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS
110*a65addddSAndroid Build Coastguard Worker   constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) {
111*a65addddSAndroid Build Coastguard Worker     return true;
112*a65addddSAndroid Build Coastguard Worker   }
113*a65addddSAndroid Build Coastguard Worker   static_assert(static_warning(), "");
114*a65addddSAndroid Build Coastguard Worker #endif
115*a65addddSAndroid Build Coastguard Worker   using type = typename DoEval<typename std::conditional<
116*a65addddSAndroid Build Coastguard Worker       StaticOr<SimpleIsError<typename DoEval<MetaExprs>::type>::value...>::value, ExtractFirstError,
117*a65addddSAndroid Build Coastguard Worker       MetaFun>::type::template apply<typename DoEval<MetaExprs>::type...>::type>::type;
118*a65addddSAndroid Build Coastguard Worker };
119*a65addddSAndroid Build Coastguard Worker 
120*a65addddSAndroid Build Coastguard Worker #endif // FRUIT_EXTRA_DEBUG
121*a65addddSAndroid Build Coastguard Worker 
122*a65addddSAndroid Build Coastguard Worker template <typename ExprResult, typename ErrorTag, typename Handler>
123*a65addddSAndroid Build Coastguard Worker struct EvalCatch {
124*a65addddSAndroid Build Coastguard Worker   using type = ExprResult;
125*a65addddSAndroid Build Coastguard Worker };
126*a65addddSAndroid Build Coastguard Worker 
127*a65addddSAndroid Build Coastguard Worker template <typename CaughtErrorTag, typename... ErrorArgs, typename Handler>
128*a65addddSAndroid Build Coastguard Worker struct EvalCatch<Error<CaughtErrorTag, ErrorArgs...>, CaughtErrorTag, Handler> {
129*a65addddSAndroid Build Coastguard Worker   using type =
130*a65addddSAndroid Build Coastguard Worker       typename DoEval<typename DoEval<Handler>::type::template apply<Error<CaughtErrorTag, ErrorArgs...>>::type>::type;
131*a65addddSAndroid Build Coastguard Worker };
132*a65addddSAndroid Build Coastguard Worker 
133*a65addddSAndroid Build Coastguard Worker template <typename ExprResult, typename Handler>
134*a65addddSAndroid Build Coastguard Worker struct EvalCatchAll {
135*a65addddSAndroid Build Coastguard Worker   using type = ExprResult;
136*a65addddSAndroid Build Coastguard Worker };
137*a65addddSAndroid Build Coastguard Worker 
138*a65addddSAndroid Build Coastguard Worker template <typename CaughtErrorTag, typename... ErrorArgs, typename Handler>
139*a65addddSAndroid Build Coastguard Worker struct EvalCatchAll<Error<CaughtErrorTag, ErrorArgs...>, Handler> {
140*a65addddSAndroid Build Coastguard Worker   using type =
141*a65addddSAndroid Build Coastguard Worker       typename DoEval<typename DoEval<Handler>::type::template apply<Error<CaughtErrorTag, ErrorArgs...>>::type>::type;
142*a65addddSAndroid Build Coastguard Worker };
143*a65addddSAndroid Build Coastguard Worker 
144*a65addddSAndroid Build Coastguard Worker template <typename Expr, typename ErrorTag, typename Handler>
145*a65addddSAndroid Build Coastguard Worker struct DoEval<Catch(Expr, ErrorTag, Handler)> {
146*a65addddSAndroid Build Coastguard Worker   using type = typename EvalCatch<typename DoEval<Expr>::type, typename DoEval<ErrorTag>::type, Handler>::type;
147*a65addddSAndroid Build Coastguard Worker };
148*a65addddSAndroid Build Coastguard Worker 
149*a65addddSAndroid Build Coastguard Worker template <typename Expr, typename ErrorTag, typename Handler>
150*a65addddSAndroid Build Coastguard Worker struct DoEval<Catch (*)(Expr, ErrorTag, Handler)> {
151*a65addddSAndroid Build Coastguard Worker   using type = typename EvalCatch<typename DoEval<Expr>::type, typename DoEval<ErrorTag>::type, Handler>::type;
152*a65addddSAndroid Build Coastguard Worker };
153*a65addddSAndroid Build Coastguard Worker 
154*a65addddSAndroid Build Coastguard Worker template <typename Expr, typename Handler>
155*a65addddSAndroid Build Coastguard Worker struct DoEval<CatchAll(Expr, Handler)> {
156*a65addddSAndroid Build Coastguard Worker   using type = typename EvalCatchAll<typename DoEval<Expr>::type, Handler>::type;
157*a65addddSAndroid Build Coastguard Worker };
158*a65addddSAndroid Build Coastguard Worker 
159*a65addddSAndroid Build Coastguard Worker template <typename Expr, typename Handler>
160*a65addddSAndroid Build Coastguard Worker struct DoEval<CatchAll (*)(Expr, Handler)> {
161*a65addddSAndroid Build Coastguard Worker   using type = typename EvalCatchAll<typename DoEval<Expr>::type, Handler>::type;
162*a65addddSAndroid Build Coastguard Worker };
163*a65addddSAndroid Build Coastguard Worker 
164*a65addddSAndroid Build Coastguard Worker template <typename MetaBool, typename ThenMetaExpr, typename ElseMetaExpr>
165*a65addddSAndroid Build Coastguard Worker struct EvalIf;
166*a65addddSAndroid Build Coastguard Worker 
167*a65addddSAndroid Build Coastguard Worker template <typename ErrorTag, typename... ErrorArgs, typename ThenMetaExpr, typename ElseMetaExpr>
168*a65addddSAndroid Build Coastguard Worker struct EvalIf<Error<ErrorTag, ErrorArgs...>, ThenMetaExpr, ElseMetaExpr> {
169*a65addddSAndroid Build Coastguard Worker   using type = Error<ErrorTag, ErrorArgs...>;
170*a65addddSAndroid Build Coastguard Worker };
171*a65addddSAndroid Build Coastguard Worker 
172*a65addddSAndroid Build Coastguard Worker template <typename ThenMetaExpr, typename ElseMetaExpr>
173*a65addddSAndroid Build Coastguard Worker struct EvalIf<Bool<true>, ThenMetaExpr, ElseMetaExpr> {
174*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS
175*a65addddSAndroid Build Coastguard Worker   constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) {
176*a65addddSAndroid Build Coastguard Worker     return true;
177*a65addddSAndroid Build Coastguard Worker   }
178*a65addddSAndroid Build Coastguard Worker   static_assert(static_warning(), "");
179*a65addddSAndroid Build Coastguard Worker #endif
180*a65addddSAndroid Build Coastguard Worker   using type = typename DoEval<ThenMetaExpr>::type;
181*a65addddSAndroid Build Coastguard Worker };
182*a65addddSAndroid Build Coastguard Worker 
183*a65addddSAndroid Build Coastguard Worker template <typename ThenMetaExpr, typename ElseMetaExpr>
184*a65addddSAndroid Build Coastguard Worker struct EvalIf<Bool<false>, ThenMetaExpr, ElseMetaExpr> {
185*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS
186*a65addddSAndroid Build Coastguard Worker   constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) {
187*a65addddSAndroid Build Coastguard Worker     return true;
188*a65addddSAndroid Build Coastguard Worker   }
189*a65addddSAndroid Build Coastguard Worker   static_assert(static_warning(), "");
190*a65addddSAndroid Build Coastguard Worker #endif
191*a65addddSAndroid Build Coastguard Worker   using type = typename DoEval<ElseMetaExpr>::type;
192*a65addddSAndroid Build Coastguard Worker };
193*a65addddSAndroid Build Coastguard Worker 
194*a65addddSAndroid Build Coastguard Worker template <typename CondMetaExpr, typename ThenMetaExpr, typename ElseMetaExpr>
195*a65addddSAndroid Build Coastguard Worker struct DoEval<If(CondMetaExpr, ThenMetaExpr, ElseMetaExpr)> {
196*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS
197*a65addddSAndroid Build Coastguard Worker   constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) {
198*a65addddSAndroid Build Coastguard Worker     return true;
199*a65addddSAndroid Build Coastguard Worker   }
200*a65addddSAndroid Build Coastguard Worker   static_assert(static_warning(), "");
201*a65addddSAndroid Build Coastguard Worker #endif
202*a65addddSAndroid Build Coastguard Worker   using type = typename EvalIf<typename DoEval<CondMetaExpr>::type, ThenMetaExpr, ElseMetaExpr>::type;
203*a65addddSAndroid Build Coastguard Worker };
204*a65addddSAndroid Build Coastguard Worker 
205*a65addddSAndroid Build Coastguard Worker // Similar to the previous specialization, but this will be selected when the function signature
206*a65addddSAndroid Build Coastguard Worker // became a function pointer (this happens when a signature parameter is itself a signature).
207*a65addddSAndroid Build Coastguard Worker template <typename CondMetaExpr, typename ThenMetaExpr, typename ElseMetaExpr>
208*a65addddSAndroid Build Coastguard Worker struct DoEval<If (*)(CondMetaExpr, ThenMetaExpr, ElseMetaExpr)> {
209*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS
210*a65addddSAndroid Build Coastguard Worker   constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) {
211*a65addddSAndroid Build Coastguard Worker     return true;
212*a65addddSAndroid Build Coastguard Worker   }
213*a65addddSAndroid Build Coastguard Worker   static_assert(static_warning(), "");
214*a65addddSAndroid Build Coastguard Worker #endif
215*a65addddSAndroid Build Coastguard Worker   using type = typename EvalIf<typename DoEval<CondMetaExpr>::type, ThenMetaExpr, ElseMetaExpr>::type;
216*a65addddSAndroid Build Coastguard Worker };
217*a65addddSAndroid Build Coastguard Worker 
218*a65addddSAndroid Build Coastguard Worker template <typename T, typename ElseMetaExpr>
219*a65addddSAndroid Build Coastguard Worker struct EvalPropagateError {
220*a65addddSAndroid Build Coastguard Worker   using type = typename DoEval<ElseMetaExpr>::type;
221*a65addddSAndroid Build Coastguard Worker };
222*a65addddSAndroid Build Coastguard Worker 
223*a65addddSAndroid Build Coastguard Worker template <typename ErrorTag, typename... ErrorArgs, typename ElseMetaExpr>
224*a65addddSAndroid Build Coastguard Worker struct EvalPropagateError<Error<ErrorTag, ErrorArgs...>, ElseMetaExpr> {
225*a65addddSAndroid Build Coastguard Worker   using type = Error<ErrorTag, ErrorArgs...>;
226*a65addddSAndroid Build Coastguard Worker };
227*a65addddSAndroid Build Coastguard Worker 
228*a65addddSAndroid Build Coastguard Worker template <typename MaybeErrorMetaExpr, typename ElseMetaExpr>
229*a65addddSAndroid Build Coastguard Worker struct DoEval<PropagateError(MaybeErrorMetaExpr, ElseMetaExpr)> {
230*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS
231*a65addddSAndroid Build Coastguard Worker   constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) {
232*a65addddSAndroid Build Coastguard Worker     return true;
233*a65addddSAndroid Build Coastguard Worker   }
234*a65addddSAndroid Build Coastguard Worker   static_assert(static_warning(), "");
235*a65addddSAndroid Build Coastguard Worker #endif
236*a65addddSAndroid Build Coastguard Worker   using type = typename EvalPropagateError<typename DoEval<MaybeErrorMetaExpr>::type, ElseMetaExpr>::type;
237*a65addddSAndroid Build Coastguard Worker };
238*a65addddSAndroid Build Coastguard Worker 
239*a65addddSAndroid Build Coastguard Worker // Similar to the previous specialization, but this will be selected when the function signature
240*a65addddSAndroid Build Coastguard Worker // became a function pointer (this happens when a signature parameter is itself a signature).
241*a65addddSAndroid Build Coastguard Worker template <typename MaybeErrorMetaExpr, typename ElseMetaExpr>
242*a65addddSAndroid Build Coastguard Worker struct DoEval<PropagateError (*)(MaybeErrorMetaExpr, ElseMetaExpr)> {
243*a65addddSAndroid Build Coastguard Worker #if FRUIT_TRACE_INSTANTIATIONS
244*a65addddSAndroid Build Coastguard Worker   constexpr static bool static_warning() __attribute__((deprecated("static_warning"))) {
245*a65addddSAndroid Build Coastguard Worker     return true;
246*a65addddSAndroid Build Coastguard Worker   }
247*a65addddSAndroid Build Coastguard Worker   static_assert(static_warning(), "");
248*a65addddSAndroid Build Coastguard Worker #endif
249*a65addddSAndroid Build Coastguard Worker   using type = typename EvalPropagateError<typename DoEval<MaybeErrorMetaExpr>::type, ElseMetaExpr>::type;
250*a65addddSAndroid Build Coastguard Worker };
251*a65addddSAndroid Build Coastguard Worker 
252*a65addddSAndroid Build Coastguard Worker template <typename MetaExpr>
253*a65addddSAndroid Build Coastguard Worker using Eval = typename DoEval<MetaExpr>::type;
254*a65addddSAndroid Build Coastguard Worker 
255*a65addddSAndroid Build Coastguard Worker } // namespace meta
256*a65addddSAndroid Build Coastguard Worker } // namespace impl
257*a65addddSAndroid Build Coastguard Worker } // namespace fruit
258*a65addddSAndroid Build Coastguard Worker 
259*a65addddSAndroid Build Coastguard Worker #endif // FRUIT_META_EVAL_H
260