00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef __MAP_INDEX_HH
00018 # define __MAP_INDEX_HH
00019
00020 # include "../strategies.hh"
00021
00022 namespace aurelia {
00023
00027 template <typename Model>
00028 struct index_strategy_concept {
00029 public:
00030 typedef typename Model::strat strat;
00031 typedef typename Model::input input;
00032 typedef typename Model::output output;
00033 #ifdef DOC_GEN
00034
00035 output operator()(strat, input, int);
00036 #else
00037 private:
00038 static_assert(std::is_same<decltype(std::declval<strat>()
00039 (std::declval<input>(),
00040 0)),
00041 output>::value,
00042 "operator() does not return the right type");
00043 #endif
00044 };
00045
00049 template <typename S, typename I>
00050 struct default_index_strategy_model {
00051 typedef S strat;
00052 typedef I input;
00053 typedef decltype(std::declval<strat>()(std::declval<input>(), 0)) output;
00054 };
00055
00056 template <typename S, typename I>
00057 struct index_strategy_model {
00058 typedef default_index_strategy_model<S, I> model;
00059 };
00060
00063 template <typename S>
00064 struct map_index_strategy {
00065 S s;
00066 map_index_strategy(const S& s): s(s) {
00067 }
00068
00069 template <typename Pool>
00070 untyped_term<Pool> operator()(const untyped_term<Pool>& t, int index = 0) const {
00071 typedef index_strategy_concept<typename
00072 index_strategy_model<S, untyped_term<Pool> >
00073 ::model>
00074 require;
00075
00076 typedef untyped_term<Pool> T;
00077 typedef untyped_constructor<Pool> C;
00078
00079 try {
00080 if (t.constructor() != C::AS_EMPTY_LIST)
00081 throw failure();
00082 return t;
00083 } catch (failure) {
00084 if (t.constructor() == C::AS_LIST) {
00085 T a = s(t[0], index);
00086 T b = (*this)(t[1], index+1);
00087 return T(C::AS_LIST, (a, b));
00088 } else
00089 throw failure();
00090 }
00091 }
00092 };
00093
00100 template <typename S>
00101 map_index_strategy<S> map_index(const S& s) {
00102 return map_index_strategy<S>(s);
00103 }
00104
00105 }
00106
00107 #endif