term_pattern.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 __TERM_PATTERN_HH
00018 # define __TERM_PATTERN_HH
00019 
00020 # include "pattern.hh"
00021 # include "../terms/term.hh"
00022 # include "../lists/listable.hh"
00023 
00024 namespace aurelia {
00025 
00026   template <typename Pool>
00027   void assign(const list_nil&, const untyped_term<Pool>&) {
00028   }
00029 
00030   template <typename Pool, typename T,
00031             typename M = typename aurelia::list_model<T>::model,
00032             typename = typename
00033             std::enable_if<!std::is_same<void,
00034                                          typename M::head_t>::value>::type>
00035   void assign(const T& l, const untyped_term<Pool>& t) {
00036     typedef typename aurelia::list_concept<M>::check require;
00037     head(l) = t[M::size-1];
00038     assign(tail(l), t);
00039   }
00040 
00041   inline list_nil build(const list_nil&) {
00042     return list_nil();
00043   }
00044 
00045   template <typename T>
00046   struct build_type {
00047   };
00048 
00049   template <typename H, typename T>
00050   struct build_type<list_cons<H, T> > {
00051     typedef list_cons<typename pattern_model<H>::model::build_type,
00052                       typename build_type<T>::type> type;
00053   };
00054 
00055   template <>
00056   struct build_type<list_nil> {
00057     typedef list_nil type;
00058   };
00059 
00060   template <typename T, typename M = typename list_model<T>::model,
00061             typename = typename
00062             std::enable_if<!std::is_same<void,
00063                                          typename M::head_t>::value>::type>
00064   typename build_type<T>::type build(const T& l) {
00065     typedef typename aurelia::list_concept<M>::check require;
00066     return typename build_type<T>::type
00067       (*head(l), build(tail(l)));
00068   }
00069 
00070   template <typename Pool, typename List>
00071   struct untyped_pattern {
00072   private:
00073     untyped_constructor<Pool> c;
00074     List l;
00075   public:
00076     untyped_pattern(const untyped_constructor<Pool>& c,
00077                     const List& l): c(c), l(l) {
00078     }
00079 
00080     const untyped_term<Pool>& operator=(const untyped_term<Pool>& t) {
00081       if (c != t.constructor())
00082         throw failure();
00083       assign(l, t);
00084       return t;
00085     }
00086 
00087     untyped_term<Pool> operator*() const {
00088       return untyped_term<Pool>(c, build(l));
00089     }
00090   };
00091 
00094   template <typename Pool, typename List>
00095   struct pattern_model<untyped_pattern<Pool, List> > {
00096     struct model {
00097       typedef untyped_pattern<Pool, List> type;
00098       typedef untyped_term<Pool> build_type;
00099     };
00100   };
00101 
00102   template <typename Pool, typename List>
00103   struct listable_model<untyped_pattern<Pool, List> > {
00104     struct model {
00105       typedef untyped_pattern<Pool, List> type;
00106     };
00107   };
00108 
00109   template <typename Pool>
00110   template <typename L,
00111             typename,
00112             template <typename> class,
00113             template <typename> class,
00114             typename,
00115             typename>
00116   untyped_pattern<Pool, L>
00117   untyped_constructor<Pool>::operator[](const L& l) const {
00118     return untyped_pattern<Pool, L>(*this, l);
00119   }
00120 }
00121 
00122 #endif