00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef __TERM_UTILS_HH
00019 # define __TERM_UTILS_HH
00020
00021 # include <functional>
00022 # include <strategies/failure.hh>
00023 # include <max_shared/max_shared_ptr.hh>
00024 # include "hash/tuple_hash.hh"
00025 # include "type_traits/overloading_priority.hh"
00026 # include "term_concept.hh"
00027
00028 namespace aurelia {
00029
00030 template <typename Constructor, typename... SubPatterns>
00031 struct pattern;
00032
00033 template <typename Term, typename Constr>
00034 struct get_tuple {
00035 };
00036
00037 template <typename Strat, typename tuple, size_t N, size_t size>
00038 struct tuple_all {
00039 static void apply(const Strat& s, tuple& t) {
00040 std::get<N>(t) = s(std::get<N>(t));
00041 tuple_all<Strat, tuple, N+1, size>::apply(s, t);
00042 }
00043 };
00044
00045 template <typename Strat, typename tuple, size_t size>
00046 struct tuple_all<Strat, tuple, size, size> {
00047 static void apply(const Strat&, tuple&) {
00048 }
00049 };
00050
00051 template <typename Term, typename Constr>
00052 struct virtual_term_constr {
00053 typedef typename get_tuple<Term,Constr>::tuple tuple;
00054
00055 virtual const tuple&
00056 getvalues(const Constr&) const throw (failure) {
00057 throw failure();
00058 }
00059
00060 virtual Term build(tuple&&) const {
00061 throw failure();
00062 }
00063
00064 template <typename Strat>
00065 Term all_prim(const Strat& s) const {
00066 tuple out(getvalues(Constr()));
00067 tuple_all<Strat, tuple, 0, std::tuple_size<tuple>::value>
00068 ::apply(s, out);
00069 return build(std::move(out));
00070 }
00071 };
00072
00073 template <typename T, typename... Tail>
00074 struct pos_of;
00075
00076 template <typename T, typename Head, typename... Tail>
00077 struct pos_of<T, Head, Tail...> {
00078 enum: size_t { value = (size_t)pos_of<T, Tail...>::value+1 };
00079 };
00080
00081 template <typename T, typename... Tail>
00082 struct pos_of<T, T, Tail...> {
00083 enum: size_t { value = 0 };
00084 };
00085
00086 template <typename Term, typename VirtualTerm, typename Strat,
00087 typename... Constrs>
00088 struct dispatch_all {
00089 static Term apply(const Strat&, size_t, const VirtualTerm&) {
00090 throw failure();
00091 }
00092 };
00093
00094 template <typename Term, typename VirtualTerm, typename Strat,
00095 typename Constr, typename... Constrs>
00096 struct dispatch_all<Term, VirtualTerm, Strat, Constr, Constrs...> {
00097 static Term apply(const Strat& s, size_t n, const VirtualTerm& v) {
00098 if (n == 0)
00099 return static_cast<const virtual_term_constr<Term, Constr>*>(&v)
00100 ->all_prim(s);
00101 return dispatch_all<Term, VirtualTerm, Strat, Constrs...>
00102 ::apply(s, n-1, v);
00103 }
00104 };
00105
00106 template <typename Term, typename... Constr>
00107 struct virtual_term: public virtual_term_constr<Term, Constr>... {
00108 virtual size_t constr() const = 0;
00109
00110 template <typename C, typename ...V>
00111 void match(pattern<C, V...>& p) const throw (failure) {
00112 p.subpatterns =
00113 ((const virtual_term_constr<Term,C>*)this)->getvalues(p.constructor);
00114 }
00115
00116 template <typename Strat>
00117 Term all_prim(const Strat& s) const {
00118 return dispatch_all<Term, virtual_term, Strat, Constr...>
00119 ::apply(s, constr(), *this);
00120 }
00121
00122 virtual bool operator==(const virtual_term& other) const = 0;
00123 virtual bool operator!=(const virtual_term& other) const = 0;
00124
00125 virtual size_t hash() const = 0;
00126 };
00127
00128 template <typename Constr, typename Term>
00129 struct ConstrNb {
00130 };
00131
00132 template <typename Constr, typename Term, typename... Constrs>
00133 struct ConstrNb<Constr, virtual_term<Term, Constrs...> > {
00134 enum: size_t { value = (size_t)pos_of<Constr, Constrs...>::value };
00135 };
00136
00137 template <typename Type, typename Constr>
00138 struct build_type {};
00139
00140 template <typename Real, typename... Constrs>
00141 struct term {
00142 typedef virtual_term<Real, Constrs...> virt;
00143 std::shared_ptr<virt> l;
00144
00145 term(virt *ptr): l(ptr) {}
00146
00147 term(const term&) = default;
00148
00149 term(term&& other): l(std::move(other.l)) {
00150 }
00151
00152 term(): l((virt*)NULL) {}
00153
00154 Real& operator=(term&& other) {
00155 std::swap(l, other.l);
00156 return *static_cast<Real*>(this);
00157 }
00158
00159 Real& operator=(const term& other) {
00160 if (&other == this)
00161 return *static_cast<Real*>(this);
00162 return *this = term(other);
00163 }
00164
00165 template <typename Constr, typename ...V>
00166 void match(pattern<Constr, V...>& p) const throw (failure) {
00167 l->match(p);
00168 }
00169
00170 bool operator==(const term& other) const {
00171 return *l == *(other.l);
00172 }
00173
00174 bool operator!=(const term& other) const {
00175 return *l != *(other.l);
00176 }
00177
00178 size_t hash() const {
00179 if (l.get() == (virt*)NULL)
00180 return 0;
00181 return l->hash();
00182 }
00183
00184 template <typename Strat>
00185 term all_prim(const Strat& s) const {
00186 return l->all_prim(s);
00187 }
00188 };
00189
00190 template <typename Strat, typename T, typename... Constrs>
00191 term<T, Constrs...> all_primitive(const Strat& s,
00192 const term<T, Constrs...>& term) {
00193 return term.all_prim(s);
00194 }
00195
00196 template <typename Real, typename... Constrs>
00197 struct term_model<term<Real, Constrs...> > {
00198 struct model {
00199 typedef term<Real, Constrs...> type;
00200 };
00201 };
00202
00203 template <typename Real, typename Constr, typename Super>
00204 struct std_term: public Super::virt {
00205 enum { constrnb = (size_t)ConstrNb<Constr, typename Super::virt>::value };
00206
00207 typedef typename get_tuple<Super, Constr>::tuple tuple;
00208 struct core_type {
00209 tuple args;
00210 size_t hash() const {
00211 return std::hash<tuple>()(args);
00212 };
00213
00214 core_type() = default;
00215 core_type(tuple&& args): args(std::move(args)) {}
00216 core_type(core_type&& other): args(std::move(other.args)) {
00217 }
00218
00219 bool operator==(const core_type& other) const {
00220 return args == other.args;
00221 }
00222
00223 bool operator!=(const core_type& other) const {
00224 return args != other.args;
00225 }
00226 };
00227 max_shared_ptr<core_type> core;
00228
00229 virtual size_t constr() const {
00230 return constrnb;
00231 }
00232
00233 virtual Super build(tuple&& t) const {
00234 return std_term(std::move(t));
00235 }
00236
00237 virtual size_t hash() const {
00238 return core->hash();
00239 }
00240
00241 operator Super() const {
00242 return Super((typename Super::virt*)new std_term(*this));
00243 }
00244
00245 std_term(const tuple& args): core(args) {}
00246 std_term(tuple&& args): core(std::move(args)) {}
00247
00248 std_term(const std_term& other): core(other.core) {}
00249 std_term(std_term&& other): core(std::move(other.core)) {}
00250
00251 virtual const tuple& getvalues(const Constr&) const throw() {
00252 return (*core).args;
00253 }
00254
00255 virtual bool operator==(const typename Super::virt& other) const {
00256 const std_term* ro = dynamic_cast<const std_term*>(&other);
00257 if (ro == NULL)
00258 return false;
00259 return core == ro->core;
00260 }
00261
00262 virtual bool operator!=(const typename Super::virt& other) const {
00263 const std_term* ro = dynamic_cast<const std_term*>(&other);
00264 if (ro == NULL)
00265 return true;
00266 return core != ro->core;
00267 }
00268 };
00269
00270 template <typename T, typename Constr, size_t N,
00271 typename tuple, typename... SubPatterns>
00272 struct build_real_type;
00273
00274 template <typename T, typename Constr, size_t N,
00275 typename tuple, typename Head, typename... SubPatterns>
00276 struct build_real_type<T,
00277 Constr, N, tuple, Head, SubPatterns...> {
00278 template <typename... Args>
00279 static T
00280 build(const tuple& t, Args... args) {
00281 static_assert((N+sizeof...(SubPatterns)+1) ==
00282 std::tuple_size<tuple>::value,
00283 "Was not the right number of arguments");
00284 static_assert(N == sizeof...(Args),
00285 "Was not the right number of arguments");
00286 return build_real_type<T, Constr, N+1, tuple, SubPatterns...>
00287 ::build(t, std::forward<Args>(args)..., *std::get<N>(t));
00288 }
00289 };
00290
00291 template <typename T,
00292 typename Constr, size_t N, typename tuple>
00293 struct build_real_type<T, Constr, N, tuple> {
00294 template <typename... Args>
00295 static T
00296 build(const tuple&, Args... args) {
00297 static_assert(N == std::tuple_size<tuple>::value,
00298 "Was not the right number of arguments");
00299 static_assert(N == sizeof...(Args),
00300 "Was not the right number of arguments");
00301 return T(new typename build_type<T, Constr>::
00302 type(std::forward<Args>(args)...));
00303 }
00304 };
00305
00306 }
00307
00308 #endif