scope.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 __SCOPE_HH
00018 # define __SCOPE_HH
00019 
00020 # include "../strategies.hh"
00021 # include "../../patterns/variable.hh"
00022 
00023 namespace aurelia {
00024 
00025   template <typename Strat, typename T>
00026   struct scope_strategy {
00027   private:
00028     Strat s;
00029     T v;
00030 
00031   public:
00032     scope_strategy(const Strat& s, const T& v): s(s), v(v) {}
00033     scope_strategy(const scope_strategy& other): s(other.s), v(other.v) {}
00034 
00035     template <typename U>
00036     typename strategy_model<Strat, U>::model::output
00037     operator()(const U& t) const {
00038       typedef typename strategy_concept
00039         <typename strategy_model<Strat, U>::model>::check
00040         require;
00041 
00042       struct onexit {
00043         const T& v;
00044         onexit(const T& v): v(v) {
00045           v.push();
00046         }
00047         ~onexit() {
00048           v.pop();
00049           }
00050       };
00051       onexit oe(v);
00052       return s(t);
00053     }
00054   };
00055 
00056   template <typename Strat, typename T>
00057   scope_strategy<Strat, variable<T> > scope(const variable<T>& v,
00058                                             const Strat& s) {
00059     return scope_strategy<Strat, variable<T> >(s, v);
00060   }
00061 
00062   template <typename T>
00063   struct is_variable: public std::false_type {};
00064 
00065   template <typename T>
00066   struct is_variable<variable<T> >: public std::true_type {};
00067 
00068   template <typename Strat, typename L,
00069             typename M =
00070             typename list_model<L>::model,
00071             typename = typename
00072             std::enable_if<all_elements<is_variable, L>::value>::type>
00073   scope_strategy<Strat, L>
00074   scope(const L& v, const Strat& s) {
00075     typedef typename list_concept<M>::check require;
00076     return scope_strategy<Strat, L>(s, v);
00077   }
00078 }
00079 
00080 #endif