map_index.hh

00001 // This file is a part of Aurelia.
00002 // Copyright (C) 2010  Valentin David
00003 // Copyright (C) 2010  University of Bergen
00004 //
00005 // This program is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
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