00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00020
00021 #ifndef __TERM_HH
00022 # define __TERM_HH
00023
00024 # include "constructor.hh"
00025 # include <cassert>
00026 # include <cstdlib>
00027 # include "../strategies/failure.hh"
00028 # include "../lists/listable.hh"
00029 # include "../max_shared/max_shared_ptr.hh"
00030 # include "../memory/pool_allocator.hh"
00031
00032 namespace aurelia {
00033
00034 template <typename Pool>
00035 struct untyped_term;
00036
00037 template <typename Pool>
00038 struct untyped_term_core {
00039 private:
00040 untyped_constructor<Pool> _constructor;
00041 const untyped_term<Pool>* children;
00042 unsigned _hash;
00043
00044 public:
00045 ~untyped_term_core() {
00046 if (children != NULL) {
00047 for (unsigned i = 0; i < _constructor->arity(); ++i)
00048 (children+i)->~untyped_term();
00049 free((void*)children);
00050 }
00051 }
00052
00053 untyped_term_core(): _constructor("", 0), _hash(0) {
00054 children = NULL;
00055 }
00056
00057 private:
00058 void copy(const list_nil&, untyped_term<Pool>*) {
00059 }
00060
00061 template <typename T,
00062 typename M =
00063 typename aurelia::list_model<T>::model,
00064 typename = typename
00065 std::enable_if<!std::is_same<void,
00066 typename M::head_t>::value>::type>
00067 void copy(const T& l, untyped_term<Pool>* list) {
00068 typedef typename aurelia::list_concept<M>::check require;
00069 new (list+(unsigned)M::size-1) untyped_term<Pool>(head(l));
00070 copy(tail(l), list);
00071 }
00072
00073 public:
00074
00075 template <typename OtherPool,
00076 typename =
00077 typename
00078 std::enable_if<!std::is_same<Pool, OtherPool>::value>::type>
00079 untyped_term_core(const untyped_term<OtherPool>& other):
00080 _constructor(other->constructor()) {
00081 untyped_term<Pool>* tc = NULL;
00082 _hash = _constructor->hash();
00083 if (_constructor->arity() != 0) {
00084 tc = (untyped_term<Pool>*)malloc(_constructor->arity()*sizeof(untyped_term<Pool>));
00085 for (unsigned i = 0; i < _constructor->arity(); ++i) {
00086 new (tc+i) untyped_term<Pool>((*other)[i]);
00087 _hash ^= tc[i]->hash();
00088 _hash = (_hash << 11) | (_hash >> 21);
00089 }
00090 }
00091 children = tc;
00092 }
00093
00094 template <typename L,
00095 typename M = typename list_model<L>::model>
00096 untyped_term_core(const untyped_constructor<Pool>& c, const L& ch):
00097 _constructor(c), children(NULL)
00098 {
00099 if (c->arity() != M::size) {
00100 throw failure();
00101 }
00102 _hash = c->hash();
00103 untyped_term<Pool>* tc = NULL;
00104 if (M::size != 0)
00105 tc = (untyped_term<Pool>*)malloc((unsigned)M::size*sizeof(untyped_term<Pool>));
00106 copy(ch, tc);
00107 children = tc;
00108 for (unsigned i = 0; i < c->arity(); ++i) {
00109 _hash ^= children[i]->hash();
00110 _hash = (_hash << 11) | (_hash >> 21);
00111 }
00112 }
00113
00114 untyped_term_core(const untyped_constructor<Pool>& c, const untyped_term<Pool>& ch)
00115 : _constructor(c) {
00116 if (c->arity() != 1) {
00117 children = NULL;
00118 throw failure();
00119 }
00120 _hash = c.hash();
00121 untyped_term<Pool>* tc = (untyped_term<Pool>*)malloc(sizeof(untyped_term<Pool>));
00122 new (tc) untyped_term<Pool>(ch);
00123 _hash ^= tc[0]->hash();
00124 _hash = (_hash << 11) | (_hash >> 21);
00125 children = tc;
00126 }
00127
00128 untyped_term_core(const untyped_constructor<Pool>& c, const untyped_term<Pool>* ch)
00129 : _constructor(c) {
00130 _hash = c->hash();
00131 if (c->arity() != 0)
00132 children = ch;
00133 else
00134 children = NULL;
00135 for (unsigned i = 0; i < c->arity(); ++i) {
00136 _hash ^= children[i]->hash();
00137 _hash = (_hash << 11) | (_hash >> 21);
00138 }
00139 }
00140
00141 untyped_term_core(untyped_term_core&& other):
00142 _constructor(std::move(other._constructor)),
00143 children(NULL),
00144 _hash(other._hash)
00145 {
00146 std::swap(children, other.children);
00147 }
00148
00149 untyped_term_core(const untyped_term_core& other)
00150 : _constructor(other._constructor) {
00151 _hash = other._hash;
00152 untyped_term<Pool>* tc = NULL;
00153 if (_constructor->arity() != 0) {
00154 tc = (untyped_term<Pool>*)malloc(_constructor->arity()*sizeof(untyped_term<Pool>));
00155 for (unsigned i = 0; i < _constructor->arity(); ++i) {
00156 new (tc+i) untyped_term<Pool>(other.children[i]);
00157 }
00158 }
00159 children = tc;
00160 }
00161
00162 untyped_term_core& operator=(const untyped_term_core& other) {
00163 return (*this) = untyped_term_core(other);
00164 }
00165
00166 untyped_term_core& operator=(untyped_term_core&& other) {
00167 std::swap(_constructor, other._constructor);
00168 std::swap(children, other.children);
00169 std::swap(_hash, other._hash);
00170 return *this;
00171 }
00172
00173 unsigned hash() const {
00174 return _hash;
00175 }
00176
00177 bool operator==(const untyped_term_core& other) const {
00178 if (_constructor != other._constructor)
00179 return false;
00180 for (unsigned i = 0; i < _constructor->arity(); ++i)
00181 if (children[i] != other.children[i])
00182 return false;
00183 return true;
00184 }
00185
00186 const untyped_term<Pool>& operator[](unsigned n) const {
00187 if (n >= _constructor->arity())
00188 throw failure();
00189 return children[n];
00190 }
00191
00192 const untyped_constructor<Pool>& constructor() const {
00193 return _constructor;
00194 }
00195 };
00196
00197 template <typename Pool>
00198 struct untyped_term:
00199 public max_shared_ptr<untyped_term_core<Pool>,
00200 member_hash,
00201 std::equal_to<untyped_term_core<Pool> >,
00202 pool_allocator<untyped_term_core<Pool> > > {
00203 public:
00204 typedef max_shared_ptr<untyped_term_core<Pool>,
00205 member_hash,
00206 std::equal_to<untyped_term_core<Pool> >,
00207 pool_allocator<untyped_term_core<Pool> > > super;
00208
00209 untyped_term(const untyped_term& other): super((const super&)(other)) {
00210 }
00211
00212 untyped_term(untyped_term&& other): super((super&&)std::move(other)) {
00213 }
00214
00215 untyped_term(): super() {
00216 }
00217
00218 template <typename OtherPool,
00219 typename =
00220 typename
00221 std::enable_if<!std::is_same<Pool, OtherPool>::value>::type>
00222 bool operator==(const untyped_term<OtherPool>& other) const {
00223 return *this == untyped_term(other);
00224 }
00225
00226 bool operator==(const untyped_term& other) const {
00227 return this->super::operator==(other);
00228 }
00229
00230 untyped_term& operator=(const untyped_term& other) {
00231 this->super::operator=(other);
00232 return *this;
00233 }
00234
00235 untyped_term& operator=(untyped_term&& other) {
00236 this->super::operator=(other);
00237 return *this;
00238 }
00239
00240 template <typename OtherPool,
00241 typename =
00242 typename
00243 std::enable_if<!std::is_same<Pool, OtherPool>::value>::type>
00244 untyped_term(const untyped_term<OtherPool>& other): super(other) {}
00245
00246 template <typename L,
00247 typename M = typename list_model<L>::model>
00248 untyped_term(const untyped_constructor<Pool>& c, const L&l): super(c, l) {
00249 }
00250
00251 untyped_term(const untyped_constructor<Pool>& c, const untyped_term<Pool>&l): super(c, l) {
00252 }
00253
00254 untyped_term(const untyped_constructor<Pool>& c, const untyped_term<Pool>* l): super(c, l) {
00255 }
00256
00257 untyped_term(const untyped_constructor<Pool>& c): super(c, list_nil()) {}
00258
00259 untyped_constructor<Pool> constructor() const {
00260 return (*this)->constructor();
00261 }
00262
00263 const untyped_term<Pool>& operator[](unsigned i) const {
00264 return (**this)[i];
00265 }
00266
00267 operator list_cons<untyped_term<Pool>, list_nil>() const {
00268 return list_cons<untyped_term<Pool>, list_nil>()(*this, list_nil());
00269 }
00270
00271 unsigned hash() const {
00272 return (*this)->hash();
00273 }
00274 };
00275
00276 template <typename Stream, typename Pool>
00277 void print(Stream& s, const untyped_term<Pool>& t, bool inlist = false) {
00278 if (t.constructor() == untyped_constructor<Pool>::AS_EMPTY_LIST) {
00279 if (!inlist)
00280 s << "[]";
00281 } else if (t.constructor() == untyped_constructor<Pool>::AS_LIST) {
00282 if (!inlist)
00283 s << "[";
00284 else
00285 s << ",";
00286 bool snd = false;
00287 for (unsigned i = 0;
00288 i < t.constructor().arity();
00289 ++i) {
00290 print(s, t[i],snd);
00291 snd = true;
00292 }
00293 if (!inlist)
00294 s << "]";
00295 } else {
00296 s << t.constructor().name();
00297 if (t.constructor().arity() != 0)
00298 s << "(";
00299 for (unsigned i = 0;
00300 i < t.constructor().arity();
00301 ++i) {
00302 if (i != 0)
00303 s << ",";
00304 print(s, t[i]);
00305 }
00306 if (t.constructor().arity() != 0)
00307 s << ")";
00308 }
00309 }
00310
00311 template <typename Stream, typename Pool>
00312 Stream& operator<<(Stream& s, const untyped_term<Pool>& t) {
00313 print(s, t);
00314 return s;
00315 }
00316
00317 template <typename Pool>
00318 struct listable_model<untyped_term<Pool> > {
00319 struct model {
00320 typedef untyped_term<Pool> type;
00321 };
00322 };
00323
00324 template <typename Pool>
00325 template <typename L,
00326 typename,
00327 template <typename> class,
00328 typename>
00329 untyped_term<Pool> untyped_constructor<Pool>::operator[](const L& l) const {
00330 return untyped_term<Pool>(*this, l);
00331 }
00332
00333 }
00334
00335 namespace std {
00336 template <typename Pool>
00337 struct hash<aurelia::untyped_term<Pool> > {
00338 unsigned operator()(const aurelia::untyped_term<Pool>& t) const {
00339 return t.hash();
00340 }
00341 };
00342 }
00343
00344 namespace aurelia {
00345
00346 template <typename T>
00347 bool diff_no_conv(const T& a, const T& b) {
00348 return a != b;
00349 }
00350
00351 template <typename T, typename U>
00352 bool diff_no_conv(const T& a, const U& b) {
00353 return true;
00354 }
00355
00356 template <typename Strat, typename T>
00357 untyped_term<T> all_primitive(const Strat& s, const untyped_term<T>& term) {
00358 if (term.constructor().arity()) {
00359 bool changed = false;
00360 unsigned i = 0;
00361 untyped_term<T> *list = NULL;
00362 try {
00363 list = (untyped_term<T>*)malloc(term.constructor()->arity()
00364 *sizeof(untyped_term<T>));
00365 if (list == NULL)
00366 throw failure();
00367 for (;
00368 i < term.constructor().arity();
00369 ++i) {
00370 new (list+i) untyped_term<T>(s(term[i]));
00371 changed = changed || diff_no_conv(list[i], term[i]);
00372 }
00373 }
00374 catch (...) {
00375 if (list == NULL)
00376 throw ;
00377 for (unsigned j = 0; j < i; ++j) {
00378 (list+j)->~untyped_term<T>();
00379 }
00380 free(list);
00381 throw ;
00382 }
00383 if (changed)
00384 return untyped_term<T>(term.constructor(), list);
00385 else {
00386 for (unsigned j = 0;
00387 j < term.constructor().arity();
00388 ++j)
00389 (list+j)->~untyped_term<T>();
00390 free(list);
00391 return term;
00392 }
00393 }
00394 else
00395 return term;
00396 }
00397
00398 }
00399
00400 #endif