CVC3

theory_datatype.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  *\file theory_datatype.cpp
00004  *
00005  * Author: Clark Barrett
00006  *
00007  * Created: Wed Dec  1 22:32:26 2004
00008  *
00009  * <hr>
00010  *
00011  * License to use, copy, modify, sell and/or distribute this software
00012  * and its documentation for any purpose is hereby granted without
00013  * royalty, subject to the terms and conditions defined in the \ref
00014  * LICENSE file provided with this distribution.
00015  * 
00016  * <hr>
00017  * 
00018  */
00019 /*****************************************************************************/
00020 
00021 
00022 #include "theory_datatype.h"
00023 #include "datatype_proof_rules.h"
00024 #include "typecheck_exception.h"
00025 #include "parser_exception.h"
00026 #include "smtlib_exception.h"
00027 #include "theory_core.h"
00028 #include "theory_uf.h"
00029 #include "command_line_flags.h"
00030 
00031 
00032 using namespace std;
00033 using namespace CVC3;
00034 
00035 
00036 ///////////////////////////////////////////////////////////////////////////////
00037 // TheoryDatatype Public Methods                                             //
00038 ///////////////////////////////////////////////////////////////////////////////
00039 
00040 
00041 TheoryDatatype::TheoryDatatype(TheoryCore* core)
00042   : Theory(core, "Datatypes"),
00043     d_labels(core->getCM()->getCurrentContext()),
00044     d_facts(core->getCM()->getCurrentContext()),
00045     d_splitters(core->getCM()->getCurrentContext()),
00046     d_splittersIndex(core->getCM()->getCurrentContext(), 0),
00047     d_splitterAsserted(core->getCM()->getCurrentContext(), false),
00048     d_smartSplits(core->getFlags()["dt-smartsplits"].getBool())
00049 {
00050   d_rules = createProofRules();
00051 
00052   // Register new local kinds with ExprManager
00053   getEM()->newKind(DATATYPE_DECL, "_DATATYPE_DECL");
00054   getEM()->newKind(DATATYPE, "_DATATYPE", true);
00055   getEM()->newKind(CONSTRUCTOR, "_CONSTRUCTOR");
00056   getEM()->newKind(SELECTOR, "_SELECTOR");
00057   getEM()->newKind(TESTER, "_TESTER");
00058 
00059   vector<int> kinds;
00060   kinds.push_back(DATATYPE_DECL);
00061   kinds.push_back(DATATYPE);
00062   kinds.push_back(TESTER);
00063   kinds.push_back(CONSTRUCTOR);
00064   kinds.push_back(SELECTOR);
00065 
00066   registerTheory(this, kinds);
00067 }
00068 
00069 
00070 TheoryDatatype::~TheoryDatatype() {
00071   delete d_rules;
00072 }
00073 
00074 
00075 void TheoryDatatype::instantiate(const Expr& e, const Unsigned& u)
00076 {
00077   DebugAssert(!e.hasFind() || findExpr(e) == e,
00078               "datatype: instantiate: Expected find(e)=e");
00079   if (isConstructor(e)) return;
00080   DebugAssert(u != 0 && (u & (u-1)) == 0,
00081               "datatype: instantiate: Expected single label in u");
00082   DebugAssert(d_datatypes.find(getBaseType(e).getExpr()) != d_datatypes.end(),
00083               "datatype: instantiate: Unexpected type: "+getBaseType(e).toString()
00084               +"\n\n for expression: "+e.toString());
00085   ExprMap<unsigned>& c = d_datatypes[getBaseType(e).getExpr()];
00086   ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end();
00087   for (; c_it != c_end; ++c_it) {
00088     if ((u & (Unsigned(1) << (unsigned)(*c_it).second)) != 0) break;
00089   }
00090   DebugAssert(c_it != c_end,
00091               "datatype: instantiate: couldn't find constructor");
00092   const Expr& cons = (*c_it).first;
00093 
00094   if (!cons.isFinite() && !e.isSelected()) return;
00095 
00096   Type consType = getBaseType(cons);
00097   if (consType.arity() == 1) {
00098     enqueueFact(d_rules->dummyTheorem(d_facts, e.eqExpr(cons)));
00099     return;
00100   }
00101   // create vars
00102   vector<Expr> vars;
00103   for (int i = 0; i < consType.arity()-1; ++i) {
00104     vars.push_back(getEM()->newBoundVarExpr(consType[i]));
00105   }
00106   Expr e2 = getEM()->newClosureExpr(EXISTS, vars,
00107                                     e.eqExpr(Expr(cons.mkOp(), vars)));
00108   enqueueFact(d_rules->dummyTheorem(d_facts, e2));
00109 }
00110 
00111 
00112 void TheoryDatatype::initializeLabels(const Expr& e, const Type& t)
00113 {
00114   DebugAssert(findExpr(e) == e,
00115               "datatype: initializeLabels: Expected find(e)=e");
00116   DebugAssert(d_datatypes.find(t.getExpr()) != d_datatypes.end(),
00117               "Unknown datatype: "+t.getExpr().toString());
00118   ExprMap<unsigned>& c = d_datatypes[t.getExpr()];
00119   DebugAssert(d_labels.find(e) == d_labels.end(),
00120               "datatype: initializeLabels: expected unlabeled expr");
00121   if (isConstructor(e)) {
00122     Expr cons = getConstructor(e);
00123     DebugAssert(c.find(cons) != c.end(),
00124                 "datatype: initializeLabels: Couldn't find constructor "
00125                 +cons.toString());
00126     d_labels.insert(e,
00127       SmartCDO<Unsigned>(theoryCore()->getCM()->getCurrentContext(),
00128                          (Unsigned)1 << c[cons], 0));
00129   }
00130   else {
00131     DebugAssert(c.size() > 0, "No constructors?");
00132     Unsigned value = ((Unsigned)1 << c.size()) - 1;
00133     d_labels.insert(e,
00134       SmartCDO<Unsigned>(theoryCore()->getCM()->getCurrentContext(),
00135                             value, 0));
00136     if (value == 1) instantiate(e, 1);
00137     else {
00138       if (!d_smartSplits || t.getExpr().isFinite()) d_splitters.push_back(e);
00139     }
00140   }
00141 }
00142 
00143 
00144 void TheoryDatatype::mergeLabels(const Theorem& thm,
00145                                  const Expr& e1, const Expr& e2)
00146 {
00147   DebugAssert(e2.hasFind() && findExpr(e2) == e2,
00148               "datatype: mergeLabels: Expected find(e2)=e2");
00149   DebugAssert(d_labels.find(e1) != d_labels.end() &&
00150               d_labels.find(e2) != d_labels.end(),
00151               "mergeLabels: expr is not labeled");
00152   DebugAssert(getBaseType(e1) == getBaseType(e2), "Expected same type");
00153   Unsigned u = d_labels[e2].get().get();
00154   Unsigned uNew = u & d_labels[e1].get().get();
00155   if (u != uNew) {
00156     if (!thm.isNull()) d_facts.push_back(thm);
00157     d_labels[e2].get().set(uNew);
00158     if (uNew == 0)
00159       setInconsistent(d_rules->dummyTheorem(d_facts, falseExpr()));
00160   }
00161   if (uNew != 0 && ((uNew - 1) & uNew) == 0) {
00162     instantiate(e2, uNew);
00163   }
00164 }
00165 
00166 
00167 void TheoryDatatype::mergeLabels(const Theorem& thm, const Expr& e,
00168                                  unsigned position, bool positive)
00169 {
00170   DebugAssert(e.hasFind() && findExpr(e) == e,
00171               "datatype: mergeLabels2: Expected find(e)=e");
00172   DebugAssert(d_labels.find(e) != d_labels.end(),
00173               "mergeLabels2: expr is not labeled");
00174   Unsigned u = d_labels[e].get().get();
00175   Unsigned uNew = (Unsigned)1 << position;
00176   if (positive) {
00177     uNew = u & uNew;
00178     if (u == uNew) return;
00179   } else if ((u & uNew) != 0) uNew = u - uNew;
00180   else return;
00181   d_facts.push_back(thm);
00182   d_labels[e].get().set(uNew);
00183   if (uNew == 0)
00184     setInconsistent(d_rules->dummyTheorem(d_facts, falseExpr()));
00185   else if (((uNew - 1) & uNew) == 0) {
00186     instantiate(e, uNew);
00187   }
00188 }
00189 
00190 
00191 void TheoryDatatype::addSharedTerm(const Expr& e)
00192 {
00193   if (getBaseType(e).getExpr().getKind() == DATATYPE &&
00194       d_labels.find(e) == d_labels.end()) {
00195     initializeLabels(e, getBaseType(e));
00196     e.addToNotify(this, Expr());
00197   }
00198 }
00199 
00200 
00201 void TheoryDatatype::assertFact(const Theorem& e)
00202 {
00203   if (!e.isRewrite()) {
00204     const Expr& expr = e.getExpr();
00205     if (expr.getOpKind() == TESTER) {
00206       mergeLabels(e, expr[0],
00207                   getConsPos(getConsForTester(expr.getOpExpr())),
00208                   true);
00209     }
00210     else if (expr.isNot()) {
00211       if (expr[0].getOpKind() == TESTER) {
00212         mergeLabels(e, expr[0][0],
00213                     getConsPos(getConsForTester(expr[0].getOpExpr())),
00214                     false);
00215       }
00216       else if (expr[0].isEq() &&
00217                getBaseType(expr[0][0]).getExpr().getKind() == DATATYPE) {
00218         // Propagate disequality down
00219         if (d_labels.find(expr[0][0]) == d_labels.end()) {
00220           initializeLabels(expr[0][0], getBaseType(expr[0][0]));
00221           expr[0][0].addToNotify(this, Expr());
00222         }
00223         if (d_labels.find(expr[0][1]) == d_labels.end()) {
00224           initializeLabels(expr[0][1], getBaseType(expr[0][1]));
00225           expr[0][1].addToNotify(this, Expr());
00226         }
00227         Unsigned u1 = d_labels[expr[0][0]].get().get();
00228         Unsigned u2 = d_labels[expr[0][1]].get().get();
00229         ExprMap<unsigned>& c = d_datatypes[getBaseType(expr[0][0]).getExpr()];
00230         ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end();
00231         Expr bigConj;
00232         for (; c_it != c_end; ++c_it) {
00233           if ((u1 & u2 & ((Unsigned)1 << unsigned((*c_it).second))) != 0) {
00234             vector<Expr>& selectors = d_constructorMap[(*c_it).first];
00235             Expr conj;
00236             for (unsigned i = 0; i < selectors.size(); ++i) {
00237               Expr e1 = Expr(selectors[i].mkOp(), expr[0][0]);
00238               Expr e2 = e1.eqExpr(Expr(selectors[i].mkOp(), expr[0][1]));
00239               if (conj.isNull()) conj = e2;
00240               else conj = conj.andExpr(e2);
00241             }
00242             if (!conj.isNull()) {
00243               Expr e1 = datatypeTestExpr((*c_it).first.getName(), expr[0][0]);
00244               Expr e2 = datatypeTestExpr((*c_it).first.getName(), expr[0][1]);
00245               conj = (e1 && e2).impExpr(!conj);
00246               if (bigConj.isNull()) bigConj = conj;
00247               else bigConj = bigConj.andExpr(conj);
00248             }
00249           }
00250         }
00251         if (!bigConj.isNull()) {
00252           enqueueFact(d_rules->dummyTheorem(d_facts, expr.impExpr(bigConj)));
00253         }          
00254       }
00255     }
00256   }
00257 }
00258 
00259 
00260 void TheoryDatatype::checkSat(bool fullEffort)
00261 {
00262   bool done = false;
00263   while (!done && d_splittersIndex < d_splitters.size()) {
00264     Expr e = d_splitters[d_splittersIndex];
00265     if ((!d_smartSplits || getBaseType(e).getExpr().isFinite()) &&
00266         findExpr(e) == e) {
00267       DebugAssert(d_labels.find(e) != d_labels.end(),
00268                   "checkSat: expr is not labeled");
00269       Unsigned u = d_labels[e].get().get();
00270       if ((u & (u-1)) != 0) {
00271         done = true;
00272         DebugAssert(!d_splitterAsserted || !fullEffort,
00273                     "splitter should have been resolved");
00274         if (!d_splitterAsserted) {
00275           DebugAssert
00276             (d_datatypes.find(getBaseType(e).getExpr()) != d_datatypes.end(),
00277              "datatype: checkSat: Unexpected type: "+getBaseType(e).toString()
00278              +"\n\n for expression: "+e.toString());
00279           ExprMap<unsigned>& c = d_datatypes[getBaseType(e).getExpr()];
00280           ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end();
00281           vector<Expr> vec;
00282           for (; c_it != c_end; ++c_it) {
00283             if ((u & ((Unsigned)1 << unsigned((*c_it).second))) != 0) {
00284               vec.push_back(datatypeTestExpr((*c_it).first.getName(), e));
00285             }
00286           }
00287           DebugAssert(vec.size() > 1, "datatype: checkSat: expected 2 or more possible constructors");
00288           enqueueFact(d_rules->dummyTheorem(d_facts, Expr(OR, vec)));
00289           d_splitterAsserted = true;
00290         }
00291       }
00292     }
00293     if (d_smartSplits && !done && isSelector(e)) {
00294       Expr f = findExpr(e[0]);
00295       DebugAssert(d_labels.find(f) != d_labels.end(),
00296                   "checkSat: expr is not labeled");
00297       Unsigned u = d_labels[f].get().get();
00298       if ((u & (u-1)) != 0) {
00299         pair<Expr, unsigned> selectorInfo = getSelectorInfo(e.getOpExpr());
00300         unsigned pos = getConsPos(selectorInfo.first);
00301         if ((u & ((Unsigned)1 << pos)) != 0) {
00302           done = true;
00303           DebugAssert(!d_splitterAsserted || !fullEffort,
00304                       "splitter should have been resolved");
00305           if (!d_splitterAsserted) {
00306             addSplitter(datatypeTestExpr(selectorInfo.first.getName(), f));
00307             d_splitterAsserted = true;
00308           }
00309         }
00310       }
00311     }
00312     if (!done) {
00313       d_splitterAsserted = false;
00314       d_splittersIndex = d_splittersIndex + 1;
00315     }
00316   }
00317 }
00318 
00319 
00320 Theorem TheoryDatatype::rewrite(const Expr& e)
00321 {
00322   // TODO: UF rewrite?
00323   Theorem thm;
00324   if (isSelector(e)) {
00325     if (canCollapse(e)) {
00326       thm = d_rules->rewriteSelCons(d_facts, e);
00327       return transitivityRule(thm, simplify(thm.getRHS()));
00328     }
00329   }
00330   else if (isTester(e)) {
00331     if (isConstructor(e[0])) {
00332       return d_rules->rewriteTestCons(e);
00333     }
00334   }
00335   return reflexivityRule(e);
00336 }
00337 
00338 
00339 void TheoryDatatype::setup(const Expr& e)
00340 {
00341   if (getBaseType(e).getExpr().getKind() == DATATYPE &&
00342       d_labels.find(e) == d_labels.end()) {
00343     initializeLabels(e, getBaseType(e));
00344     e.addToNotify(this, Expr());
00345   }
00346   if (e.getKind() != APPLY) return;
00347   if (isConstructor(e) && e.arity() > 0) {
00348     enqueueFact(d_rules->noCycle(e));
00349   }
00350   if (isSelector(e)) {
00351     if (d_smartSplits) d_splitters.push_back(e);
00352     e[0].setSelected();
00353     mergeLabels(Theorem(), e[0], e[0]);
00354   }
00355   setupCC(e);
00356 }
00357 
00358 
00359 void TheoryDatatype::update(const Theorem& e, const Expr& d)
00360 {
00361   if (d.isNull()) {
00362     const Expr& lhs = e.getLHS();
00363     const Expr& rhs = e.getRHS();
00364     if (isConstructor(lhs) && isConstructor(rhs) &&
00365         lhs.isApply() && rhs.isApply() &&
00366         lhs.getOpExpr() == rhs.getOpExpr()) {
00367       enqueueFact(d_rules->decompose(e));
00368     }
00369     else {
00370       // Possible for rhs to never have been seen: initialize it here
00371       DebugAssert(getBaseType(rhs).getExpr().getKind() == DATATYPE,
00372                   "Expected datatype");
00373       if (d_labels.find(rhs) == d_labels.end()) {
00374         initializeLabels(rhs, getBaseType(rhs));
00375         rhs.addToNotify(this, Expr());
00376       }
00377       Theorem thm(e);
00378       if (lhs.isSelected() && !rhs.isSelected()) {
00379         d_facts.push_back(e);
00380         rhs.setSelected();
00381         thm = Theorem();
00382       }
00383       mergeLabels(thm, lhs, rhs);
00384     }
00385   }
00386   else {
00387     const Theorem& dEQdsig = d.getSig();
00388     if (!dEQdsig.isNull()) {
00389       const Expr& dsig = dEQdsig.getRHS();
00390       Theorem thm = updateHelper(d);
00391       const Expr& sigNew = thm.getRHS();
00392       if (sigNew == dsig) return;
00393       dsig.setRep(Theorem());
00394       if (isSelector(sigNew) && canCollapse(sigNew)) {
00395         d.setSig(Theorem());
00396         enqueueFact(transitivityRule(thm, d_rules->rewriteSelCons(d_facts, sigNew)));
00397       }
00398       else if (isTester(sigNew) && isConstructor(sigNew[0])) {
00399         d.setSig(Theorem());
00400         enqueueFact(transitivityRule(thm, d_rules->rewriteTestCons(sigNew)));
00401       }
00402       else {
00403         const Theorem& repEQsigNew = sigNew.getRep();
00404         if (!repEQsigNew.isNull()) {
00405           d.setSig(Theorem());
00406           enqueueFact(transitivityRule(repEQsigNew, symmetryRule(thm)));
00407         }
00408         else {
00409           int k, ar(d.arity());
00410           for (k = 0; k < ar; ++k) {
00411             if (sigNew[k] != dsig[k]) {
00412               sigNew[k].addToNotify(this, d);
00413             }
00414           }
00415           d.setSig(thm);
00416           sigNew.setRep(thm);
00417           getEM()->invalidateSimpCache();
00418         }
00419       }
00420     }
00421   }
00422 }
00423 
00424 
00425 Theorem TheoryDatatype::solve(const Theorem& e)
00426 {
00427   DebugAssert(e.isRewrite() && e.getLHS().isTerm(), "Expected equality");
00428   const Expr& lhs = e.getLHS();
00429   if (isConstructor(lhs) && !isConstructor(e.getRHS())) {
00430     return symmetryRule(e);
00431   }
00432   return e;
00433 }
00434 
00435 
00436 void TheoryDatatype::checkType(const Expr& e)
00437 {
00438   switch (e.getKind()) {
00439     case DATATYPE: {
00440       if (e.arity() != 1 || !e[0].isString())
00441         throw Exception("Ill-formed datatype"+e.toString());
00442       if (resolveID(e[0].getString()) != e)
00443         throw Exception("Unknown datatype"+e.toString());
00444       break;
00445     }
00446     case CONSTRUCTOR:
00447     case SELECTOR:
00448     case TESTER:
00449       throw Exception("Non-type: "+e.toString());
00450     default:
00451       FatalAssert(false, "Unexpected kind in TheoryDatatype::checkType"
00452                   +getEM()->getKindName(e.getKind()));
00453   }
00454 }
00455 
00456 
00457 Cardinality TheoryDatatype::finiteTypeInfo(Expr& e, Unsigned& n,
00458                                            bool enumerate, bool computeSize)
00459 {
00460   DebugAssert(e.getKind() == DATATYPE,
00461               "Unexpected kind in TheoryDatatype::finiteTypeInfo");
00462   if (d_getConstantStack.count(e) != 0) {
00463     return CARD_INFINITE;
00464   }
00465   d_getConstantStack[e] = true;
00466 
00467   Expr typeExpr = e;
00468   ExprMap<unsigned>& c = d_datatypes[typeExpr];
00469   ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end();
00470   Cardinality card = CARD_FINITE, cardTmp;
00471   bool getSize = enumerate || computeSize;
00472   Unsigned totalSize = 0, thisSize, size;
00473   vector<Unsigned> sizes;
00474   int j;
00475 
00476   // Loop through constructors, and check if each one only has a finite number
00477   // of possibilities
00478   for (; c_it != c_end; ++c_it) {
00479     const Expr& cons = (*c_it).first;
00480     Expr funType = cons.getType().getExpr();
00481     thisSize = 1;
00482     for (j = 0; j < funType.arity()-1; ++j) {
00483       Expr e2 = funType[j];
00484       cardTmp = theoryOf(e2)->finiteTypeInfo(e2, size, false, getSize);
00485       if (cardTmp == CARD_INFINITE) {
00486         card = CARD_INFINITE;
00487         break;
00488       }
00489       else if (cardTmp == CARD_UNKNOWN) {
00490         card = CARD_UNKNOWN;
00491         getSize = false;
00492         // Keep looking to see if we can determine it is infinite
00493       }
00494       else if (getSize) {
00495         thisSize = thisSize * size;
00496         // Give up if it gets too big
00497         if (thisSize > 1000000) thisSize = 0;
00498         if (thisSize == 0) {
00499           totalSize = 0;
00500           getSize = false;
00501         }
00502       }
00503     }
00504     if (card == CARD_INFINITE) break;
00505     if (getSize) {
00506       sizes.push_back(thisSize);
00507       totalSize = totalSize + thisSize;
00508     }
00509   }
00510   
00511   if (card == CARD_FINITE) {
00512 
00513     if (enumerate) {
00514       c_it = c.begin();
00515       unsigned i = 0;
00516       for (; i < sizes.size(); ++i, ++c_it) {
00517         if (n < sizes[i]) {
00518           break;
00519         }
00520         else n = n - sizes[i];
00521       }
00522       if (i == sizes.size() && n != 0) {
00523         e = Expr();
00524       }
00525       else {
00526         const Expr& cons = (*c_it).first;
00527         Expr funType = cons.getType().getExpr();
00528         if (funType.arity() == 1) {
00529           e = cons;
00530         }
00531         else {
00532           vector<Expr> kids(funType.arity()-1);
00533           Unsigned thisSize;
00534           Unsigned elem;
00535           for (int j = funType.arity()-2; j >= 0; --j) {
00536             if (n == 0) {
00537               elem = 0;
00538             }
00539             else {
00540               thisSize = funType[j].typeSizeFinite();
00541               elem = n % thisSize;
00542               n = n - elem;
00543               n = n / thisSize;
00544             }
00545             kids[j] = funType[j].typeEnumerateFinite(elem);
00546           }
00547           e = Expr(cons.mkOp(), kids);
00548         }
00549       }
00550     }
00551 
00552     if (computeSize) {
00553       n = totalSize;
00554     }
00555 
00556   }
00557   d_getConstantStack.erase(typeExpr);
00558   return card;
00559 }
00560 
00561 
00562 void TheoryDatatype::computeType(const Expr& e)
00563 {
00564   switch (e.getOpKind()) {
00565     case CONSTRUCTOR:
00566     case SELECTOR:
00567     case TESTER: {
00568       DebugAssert(e.isApply(), "Expected application");
00569       Expr op = e.getOp().getExpr();
00570       Type t = op.lookupType();
00571       DebugAssert(!t.isNull(), "Expected operator to be well-typed");
00572       if (t.getExpr().getKind() == DATATYPE) {
00573         if (e.arity() != 0)
00574           throw TypecheckException("Expected no children: "+e.toString());
00575         e.setType(t);
00576         break;
00577       }
00578       else {
00579         DebugAssert(t.getExpr().getKind() == ARROW, "Expected function type");
00580         if (e.arity() != t.getExpr().arity()-1)
00581           throw TypecheckException("Wrong number of children:\n"+e.toString());
00582         Expr::iterator i = e.begin(), iend = e.end();
00583         Expr::iterator j = t.getExpr().begin();
00584         for (; i != iend; ++i, ++j) {
00585           if (getBaseType(*i) != getBaseType(Type(*j))) {
00586             throw TypecheckException("Type mismatch for expression:\n\n  "
00587                                      + (*i).toString()
00588                                      + "\n\nhas the following type:\n\n  "
00589                                      + (*i).getType().getExpr().toString()
00590                                      + "\n\nbut the expected type is:\n\n  "
00591                                      + (*j).toString()
00592                                      + "\n\nin datatype function application:\n\n  "
00593                                      + e.toString());
00594           }
00595         }
00596         e.setType(*j);
00597       }
00598       break;
00599     }
00600     default:
00601       DebugAssert(false, "Unexpected kind in datatype::computeType: "
00602                   +e.toString());
00603   }
00604 }
00605 
00606 
00607 void TheoryDatatype::computeModelTerm(const Expr& e, std::vector<Expr>& v) {
00608 }
00609 
00610 
00611 
00612 Expr TheoryDatatype::computeTCC(const Expr& e)
00613 {
00614   Expr tcc(Theory::computeTCC(e));
00615   switch (e.getKind()) {
00616     case CONSTRUCTOR:
00617       DebugAssert(e.arity() == 0, "Expected leaf constructor");
00618       return trueExpr();
00619     case APPLY: {
00620       DebugAssert(e.isApply(), "Should be application");
00621       Expr op(e.getOpExpr());
00622       if (op.getKind() != SELECTOR) return tcc;
00623       DebugAssert(e.arity() == 1, "Expected single argument");
00624       const std::pair<Expr,unsigned>& p = getSelectorInfo(op);
00625       Expr tester = datatypeTestExpr(p.first.getName(), e[0]);
00626       return tcc.andExpr(tester);
00627     }
00628     default:
00629       DebugAssert(false,"Unexpected type: "+e.toString());
00630       return trueExpr();
00631   }
00632 }
00633 
00634 ///////////////////////////////////////////////////////////////////////////////
00635 // Pretty-printing                                           //
00636 ///////////////////////////////////////////////////////////////////////////////
00637 
00638 
00639 ExprStream& TheoryDatatype::print(ExprStream& os, const Expr& e) {
00640   switch (os.lang()) {
00641     case PRESENTATION_LANG:
00642       switch (e.getKind()) {
00643         case DATATYPE_DECL: {
00644           os << "DATATYPE" << endl;
00645           bool first(true);
00646           for (Expr::iterator i = e.begin(), iend = e.end(); i != iend; ++i) {
00647             if (first) first = false;
00648             else os << "," << endl;
00649             os << "  " << push << *i << space << "= " << push;
00650             DebugAssert(d_datatypes.find(*i) != d_datatypes.end(),
00651                         "Unknown datatype: "+(*i).toString());
00652             ExprMap<unsigned>& c = d_datatypes[*i];
00653             ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end();
00654             bool firstCons(true);
00655             for (; c_it != c_end; ++c_it) {
00656               if (!firstCons) {
00657                 os << space << "| ";
00658               }
00659               else firstCons = false;
00660               const Expr& cons = (*c_it).first;
00661               os << cons;
00662               vector<Expr>& sels = d_constructorMap[cons];
00663               bool firstSel(true);
00664               for (unsigned j = 0; j < sels.size(); ++j) {
00665                 if (firstSel) {
00666                   firstSel = false;
00667                   os << "(";
00668                 } else {
00669                   os << ", ";
00670                 }
00671                 os << sels[j] << space << ": ";
00672                 os << sels[j].getType().getExpr()[1];
00673               }
00674               if (!firstSel) {
00675                 os << ")";
00676               }
00677             }
00678             os << pop;
00679           }
00680           os << pop << endl;
00681           os << "END;";
00682           break;
00683         }
00684         case DATATYPE:
00685           if (e.arity() == 1 && e[0].isString()) {
00686             os << e[0].getString();
00687           }
00688           else e.printAST(os);
00689           break;
00690         case APPLY:
00691           os << e.getOpExpr();
00692           if(e.arity() > 0) {
00693             os << "(" << push;
00694             bool first(true);
00695             for (Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
00696               if(first) first = false;
00697               else os << "," << space;
00698               os << *i;
00699             }
00700             os << push << ")";
00701           }
00702           break;
00703         case CONSTRUCTOR:
00704         case SELECTOR:
00705         case TESTER:
00706           DebugAssert(e.isSymbol(), "Expected symbol");
00707           os << e.getName();
00708           break;
00709         default:
00710           DebugAssert(false, "TheoryDatatype::print: Unexpected kind: "
00711                       +getEM()->getKindName(e.getKind()));
00712       }
00713       break;
00714     case SMTLIB_LANG:
00715       FatalAssert(false, "Not Implemented Yet");
00716       break;
00717     case LISP_LANG:
00718       FatalAssert(false, "Not Implemented Yet");
00719       break;
00720     default:
00721       e.printAST(os);
00722       break;
00723   }
00724   return os;
00725 }
00726 
00727 //////////////////////////////////////////////////////////////////////////////
00728 //parseExprOp:
00729 //translating special Exprs to regular EXPR??
00730 ///////////////////////////////////////////////////////////////////////////////
00731 Expr TheoryDatatype::parseExprOp(const Expr& e)
00732 {
00733   // If the expression is not a list, it must have been already
00734   // parsed, so just return it as is.
00735   if(RAW_LIST != e.getKind()) return e;
00736 
00737   DebugAssert(e.arity() > 0,
00738         "TheoryDatatype::parseExprOp:\n e = "+e.toString());
00739   
00740   DebugAssert(e[0].getKind() == ID,
00741               "Expected ID kind for first elem in list expr");
00742 
00743   const Expr& c1 = e[0][0];
00744   int kind = getEM()->getKind(c1.getString());
00745   switch(kind) {
00746     case DATATYPE: {
00747       DebugAssert(e.arity() > 1,
00748                   "Empty DATATYPE expression\n"
00749                   " (expected at least one datatype): "+e.toString());
00750 
00751       vector<Expr> names;
00752 
00753       vector<Expr> allConstructorNames;
00754       vector<Expr> constructorNames;
00755 
00756       vector<Expr> allSelectorNames;
00757       vector<Expr> selectorNames;
00758       vector<Expr> selectorNamesKids;
00759 
00760       vector<Expr> allTypes;
00761       vector<Expr> types;
00762       vector<Expr> typesKids;
00763 
00764       int i,j,k;
00765       Expr dt, constructor, selectors, selector;
00766 
00767       // Get names of datatypes
00768       ExprMap<bool> namesMap;
00769       for (i = 0; i < e.arity()-1; ++i) {
00770         dt = e[i+1];
00771         DebugAssert(dt.getKind() == RAW_LIST && dt.arity() == 2,
00772                     "Bad formed datatype expression"
00773                     +dt.toString());
00774         DebugAssert(dt[0].getKind() == ID,
00775                     "Expected ID kind for datatype name"
00776                     +dt.toString());
00777         names.push_back(dt[0][0]);
00778         if (namesMap.count(dt[0][0]) != 0) {
00779           throw ParserException("Datatype name used more than once"+dt[0][0].getString());
00780         }
00781         namesMap.insert(dt[0][0], true);
00782       }
00783 
00784       // Loop through datatypes
00785       for (i = 0; i < e.arity()-1; ++i) {
00786         dt = e[i+1];
00787         DebugAssert(dt[1].getKind() == RAW_LIST && dt[1].arity() > 0,
00788                     "Expected non-empty list for datatype constructors"
00789                     +dt.toString());
00790         dt = dt[1];
00791 
00792         // Loop through constructors for this datatype
00793         for(j = 0; j < dt.arity(); ++j) {
00794           constructor = dt[j];
00795           DebugAssert(constructor.getKind() == RAW_LIST &&
00796                       (constructor.arity() == 1 || constructor.arity() == 2),
00797                     "Unexpected constructor"+constructor.toString());
00798           DebugAssert(constructor[0].getKind() == ID,
00799                       "Expected ID kind for constructor name"
00800                       +constructor.toString());
00801           constructorNames.push_back(constructor[0][0]);
00802 
00803           if (constructor.arity() == 2) {
00804             selectors = constructor[1];
00805             DebugAssert(selectors.getKind() == RAW_LIST && selectors.arity() > 0,
00806                         "Non-empty list expected as second argument of constructor:\n"
00807                         +constructor.toString());
00808 
00809             // Loop through selectors for this constructor
00810             for (k = 0; k < selectors.arity(); ++k) {
00811               selector = selectors[k];
00812               DebugAssert(selector.getKind() == RAW_LIST && selector.arity() == 2,
00813                           "Expected list of arity 2 for selector"
00814                           +selector.toString());
00815               DebugAssert(selector[0].getKind() == ID,
00816                           "Expected ID kind for selector name"
00817                           +selector.toString());
00818               selectorNamesKids.push_back(selector[0][0]);
00819               if (selector[1].getKind() == ID && namesMap.count(selector[1][0]) > 0) {
00820                 typesKids.push_back(selector[1][0]);
00821               }
00822               else {
00823                 typesKids.push_back(parseExpr(selector[1]));
00824               }
00825             }
00826             selectorNames.push_back(Expr(RAW_LIST, selectorNamesKids));
00827             selectorNamesKids.clear();
00828             types.push_back(Expr(RAW_LIST, typesKids));
00829             typesKids.clear();
00830           }
00831           else {
00832             selectorNames.push_back(Expr(RAW_LIST, selectorNamesKids, getEM()));
00833             types.push_back(Expr(RAW_LIST, typesKids, getEM()));
00834           }
00835         }
00836         allConstructorNames.push_back(Expr(RAW_LIST, constructorNames));
00837         constructorNames.clear();
00838         allSelectorNames.push_back(Expr(RAW_LIST, selectorNames));
00839         selectorNames.clear();
00840         allTypes.push_back(Expr(RAW_LIST, types));
00841         types.clear();
00842       }
00843 
00844       return Expr(DATATYPE,
00845                   Expr(RAW_LIST, names),
00846                   Expr(RAW_LIST, allConstructorNames),
00847                   Expr(RAW_LIST, allSelectorNames),
00848                   Expr(RAW_LIST, allTypes));
00849     }
00850 
00851     default: {
00852       throw ParserException("Unexpected datatype expression: "+e.toString());
00853     }
00854   }
00855   return e;
00856 }
00857 
00858 
00859 Expr TheoryDatatype::dataType(const string& name,
00860                               const vector<string>& constructors,
00861                               const vector<vector<string> >& selectors,
00862                               const vector<vector<Expr> >& types)
00863 {
00864   vector<string> names;
00865   vector<vector<string> > constructors2;
00866   vector<vector<vector<string> > > selectors2;
00867   vector<vector<vector<Expr> > > types2;
00868   names.push_back(name);
00869   constructors2.push_back(constructors);
00870   selectors2.push_back(selectors);
00871   types2.push_back(types);
00872   return dataType(names, constructors2, selectors2, types2);
00873 }
00874  
00875 
00876 // Elements of types are either the expr from an existing type or a string
00877 // naming one of the datatypes being defined
00878 Expr TheoryDatatype::dataType(const vector<string>& names,
00879                               const vector<vector<string> >& allConstructors,
00880                               const vector<vector<vector<string> > >& allSelectors,
00881                               const vector<vector<vector<Expr> > >& allTypes)
00882 {
00883   vector<Expr> returnTypes;
00884 
00885   //  bool wellFounded = false, infinite = false, 
00886   bool thisWellFounded;
00887 
00888   if (names.size() != allConstructors.size() ||
00889       allConstructors.size() != allSelectors.size() ||
00890       allSelectors.size() != allTypes.size()) {
00891     throw TypecheckException
00892       ("dataType: vector sizes don't match");
00893   }
00894 
00895   unsigned i, j, k;
00896   Expr e;
00897 
00898   // Create reachability predicate for constructor cycle detection
00899   vector<Type> funTypeArgs;
00900   funTypeArgs.push_back(Type::anyType(getEM()));
00901   funTypeArgs.push_back(Type::anyType(getEM()));
00902   Op op = newFunction("_reach_"+names[0],
00903                       Type::funType(funTypeArgs, boolType()),
00904                       true /* compute trans closure */);
00905   Op reach = getEM()->newSymbolExpr(op.getExpr().getName(),
00906                                     TRANS_CLOSURE).mkOp();
00907 
00908   for (i = 0; i < names.size(); ++i) {
00909     e = resolveID(names[i]);
00910     if (!e.isNull()) {
00911       throw TypecheckException
00912         ("Attempt to define datatype "+names[i]+":\n "
00913          "This variable is already defined.");
00914     }
00915     e = Expr(DATATYPE, getEM()->newStringExpr(names[i]));
00916     installID(names[i], e);
00917     returnTypes.push_back(e);
00918     d_reach[e] = reach;
00919   }
00920 
00921   vector<Expr> selectorVec;
00922 
00923   for (i = 0; i < names.size(); ++i) {
00924 
00925     const vector<string>& constructors = allConstructors[i];
00926     const vector<vector<string> >& selectors = allSelectors[i];
00927     const vector<vector<Expr> >& types = allTypes[i];
00928 
00929     if (constructors.size() == 0) {
00930       throw TypecheckException
00931         ("datatype: "+names[i]+": must have at least one constructor");
00932     }
00933     if (constructors.size() != selectors.size() ||
00934         selectors.size() != types.size()) {
00935       throw TypecheckException
00936         ("dataType: vector sizes at index "+int2string(i)+" don't match");
00937     }
00938 
00939     ExprMap<unsigned>& constMap = d_datatypes[returnTypes[i]];
00940 
00941     for (j = 0; j < constructors.size(); ++j) {
00942       Expr c = resolveID(constructors[j]);
00943       if (!c.isNull()) {
00944         throw TypecheckException
00945           ("Attempt to define datatype constructor "+constructors[j]+":\n "
00946            "This variable is already defined.");
00947       }
00948       c = getEM()->newSymbolExpr(constructors[j], CONSTRUCTOR);
00949 
00950       if (selectors[j].size() != types[j].size()) {
00951         throw TypecheckException
00952           ("dataType: constructor at index "+int2string(i)+", "+int2string(j)+
00953            ": number of selectors does not match number of types");
00954       }
00955       thisWellFounded = true;
00956       const vector<string>& sels = selectors[j];
00957       const vector<Expr>& tps = types[j];
00958 
00959       vector<Type> selTypes;
00960       Type t;
00961       Expr s;
00962       for (k = 0; k < sels.size(); ++k) {
00963         s = resolveID(sels[k]);
00964         if (!s.isNull()) {
00965           throw TypecheckException
00966             ("Attempt to define datatype selector "+sels[k]+":\n "
00967              "This variable is already defined.");
00968         }
00969         s = getEM()->newSymbolExpr(sels[k], SELECTOR);
00970         if (tps[k].isString()) {
00971           t = Type(resolveID(tps[k].getString()));
00972           if (t.isNull()) {
00973             throw TypecheckException
00974               ("Unable to resolve type identifier: "+tps[k].getString());
00975           }
00976         } else t = Type(tps[k]);
00977         if (t.isBool()) {
00978           throw TypecheckException
00979             ("Cannot have BOOLEAN inside of datatype");
00980         }
00981         else if (t.isFunction()) {
00982           throw TypecheckException
00983             ("Cannot have function inside of datatype");
00984         }
00985         
00986         selTypes.push_back(Type(t));
00987         s.setType(Type(returnTypes[i]).funType(Type(t)));
00988         if (isDatatype(Type(t)) && !t.getExpr().isWellFounded()) {
00989           thisWellFounded = false;
00990         }
00991         d_selectorMap[s] = pair<Expr,unsigned>(c,k);
00992         installID(sels[k], s);
00993         selectorVec.push_back(s);
00994       }
00995       if (thisWellFounded) c.setWellFounded();
00996       if (selTypes.size() == 0) {
00997         c.setType(Type(returnTypes[i]));
00998         c.setFinite();
00999       }
01000       else c.setType(Type::funType(selTypes, Type(returnTypes[i])));
01001       installID(constructors[j], c);
01002       constMap[c] = j;
01003       d_constructorMap[c] = selectorVec;
01004       selectorVec.clear();
01005 
01006       string testerString = "is_"+constructors[j];
01007       e = resolveID(testerString);
01008       if (!e.isNull()) {
01009         throw TypecheckException
01010           ("Attempt to define datatype tester "+testerString+":\n "
01011            "This variable is already defined.");
01012       }
01013       e = getEM()->newSymbolExpr(testerString, TESTER);
01014       e.setType(Type(returnTypes[i]).funType(boolType()));
01015       d_testerMap[e] = c;
01016       installID(testerString, e);
01017     }
01018   }
01019 
01020   // Compute fixed point for wellfoundedness check
01021 
01022   bool changed, thisFinite;
01023   int firstNotWellFounded;
01024   do {
01025     changed = false;
01026     firstNotWellFounded = -1;
01027     for (i = 0; i < names.size(); ++i) {
01028       ExprMap<unsigned>& c = d_datatypes[returnTypes[i]];
01029       ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end();
01030       thisWellFounded = false;
01031       thisFinite = true;
01032       for (; c_it != c_end; ++c_it) {
01033         const Expr& cons = (*c_it).first;
01034         Expr funType = getBaseType(cons).getExpr();
01035         int j;
01036         if (!cons.isFinite()) {
01037           for (j = 0; j < funType.arity()-1; ++j) {
01038             if (!isDatatype(funType[j]) || !funType[j].isFinite())
01039               break;
01040           }
01041           if (j == funType.arity()-1) {
01042             changed = true;
01043             cons.setFinite();
01044           }
01045           else thisFinite = false;
01046         }
01047         if (cons.isWellFounded()) {
01048           thisWellFounded = true;
01049           continue;
01050         }
01051         for (j = 0; j < funType.arity()-1; ++j) {
01052           if (isDatatype(funType[j]) && !funType[j].isWellFounded())
01053             break;
01054         }
01055         if (j == funType.arity()-1) {
01056           changed = true;
01057           cons.setWellFounded();
01058           thisWellFounded = true;
01059         }
01060       }
01061       if (!thisWellFounded) {
01062         if (firstNotWellFounded == -1) firstNotWellFounded = i;
01063       }
01064       else {
01065         if (!returnTypes[i].isWellFounded()) {
01066           changed = true;
01067           returnTypes[i].setWellFounded();
01068         }
01069       }
01070       if (thisFinite && !returnTypes[i].isFinite()) {
01071         changed = true;
01072         returnTypes[i].setFinite();
01073       }
01074     }
01075   } while (changed);
01076 
01077   if (firstNotWellFounded >= 0) {
01078     // TODO: uninstall all ID's
01079     throw TypecheckException
01080       ("Datatype "+names[firstNotWellFounded]+" has no finite terms");
01081   }
01082 
01083   return Expr(DATATYPE_DECL, returnTypes);
01084 }
01085 
01086 Expr TheoryDatatype::datatypeConsExpr(const string& constructor,
01087                                       const vector<Expr>& args)
01088 {
01089   Expr e = resolveID(constructor);
01090   if (e.isNull())
01091     throw Exception("datatype: unknown constructor: "+constructor);
01092   if (!(e.isSymbol() && e.getKind() == CONSTRUCTOR))
01093     throw Exception("datatype: "+constructor+" resolves to: "+e.toString()+
01094                     "\nwhich is not a constructor");
01095   if (args.size() == 0) return e;
01096   return Expr(e.mkOp(), args);
01097 }
01098 
01099 
01100 Expr TheoryDatatype::datatypeSelExpr(const string& selector, const Expr& arg)
01101 {
01102   Expr e = resolveID(selector);
01103   if (e.isNull())
01104     throw Exception("datatype: unknown selector: "+selector);
01105   if (!(e.isSymbol() && e.getKind() == SELECTOR))
01106     throw Exception("datatype: "+selector+" resolves to: "+e.toString()+
01107                     "\nwhich is not a selector");
01108   return Expr(e.mkOp(), arg);
01109 }
01110 
01111 
01112 Expr TheoryDatatype::datatypeTestExpr(const string& constructor, const Expr& arg)
01113 {
01114   Expr e = resolveID("is_"+constructor);
01115   if (e.isNull())
01116     throw Exception("datatype: unknown tester: is_"+constructor);
01117   if (!(e.isSymbol() && e.getKind() == TESTER))
01118     throw Exception("datatype: is_"+constructor+" resolves to: "+e.toString()+
01119                     "\nwhich is not a tester");
01120   return Expr(e.mkOp(), arg);
01121 }
01122 
01123 
01124 const pair<Expr,unsigned>& TheoryDatatype::getSelectorInfo(const Expr& e)
01125 {
01126   DebugAssert(e.getKind() == SELECTOR, "getSelectorInfo called on non-selector: "
01127               +e.toString());
01128   DebugAssert(d_selectorMap.find(e) != d_selectorMap.end(),
01129               "Unknown selector: "+e.toString());
01130   return d_selectorMap[e];
01131 }
01132 
01133 
01134 Expr TheoryDatatype::getConsForTester(const Expr& e)
01135 {
01136   DebugAssert(e.getKind() == TESTER,
01137               "getConsForTester called on non-tester"
01138               +e.toString());
01139   DebugAssert(d_testerMap.find(e) != d_testerMap.end(),
01140               "Unknown tester: "+e.toString());
01141   return d_testerMap[e];
01142 }
01143 
01144 
01145 unsigned TheoryDatatype::getConsPos(const Expr& e)
01146 {
01147   DebugAssert(e.getKind() == CONSTRUCTOR,
01148               "getConsPos called on non-constructor");
01149   Type t = getBaseType(e);
01150   if (t.isFunction()) t = t[t.arity()-1];
01151   DebugAssert(isDatatype(t), "Expected datatype");
01152   DebugAssert(d_datatypes.find(t.getExpr()) != d_datatypes.end(),
01153               "Could not find datatype: "+t.toString());
01154   ExprMap<unsigned>& constMap = d_datatypes[t.getExpr()];
01155   DebugAssert(constMap.find(e) != constMap.end(),
01156               "Could not find constructor: "+e.toString());
01157   return constMap[e];
01158 }
01159 
01160 
01161 Expr TheoryDatatype::getConstant(const Type& t)
01162 {
01163   // if a cycle is detected, backtrack from this branch
01164   if (d_getConstantStack.count(t.getExpr()) != 0) {
01165     return Expr();
01166   }
01167   DebugAssert(d_getConstantStack.size() < 1000,
01168         "TheoryDatatype::getconstant: too deep recursion depth");
01169   d_getConstantStack[t.getExpr()] = true;
01170   if (isDatatype(t)) {
01171    DebugAssert(d_datatypes.find(t.getExpr()) != d_datatypes.end(),
01172                "Unknown datatype: "+t.getExpr().toString());
01173    ExprMap<unsigned>& c = d_datatypes[t.getExpr()];
01174    ExprMap<unsigned>::iterator i = c.begin(), iend = c.end();
01175    for (; i != iend; ++i) {
01176      const Expr& cons = (*i).first;
01177      if (!getBaseType(cons).isFunction()) {
01178        d_getConstantStack.erase(t.getExpr());
01179        return cons;
01180      }
01181    }
01182    for (i = c.begin(), iend = c.end(); i != iend; ++i) {
01183      const Expr& cons = (*i).first;
01184      Expr funType = getBaseType(cons).getExpr();
01185      vector<Expr> args;
01186      int j = 0;
01187      for (; j < funType.arity()-1; ++j) {
01188        Type t_j = Type(funType[j]);
01189        if (t_j == t || isDatatype(t_j)) break;
01190        args.push_back(getConstant(t_j));
01191        DebugAssert(!args.back().isNull(), "Expected non-null");
01192      }
01193      if (j == funType.arity()-1) {
01194        d_getConstantStack.erase(t.getExpr());
01195        return Expr(cons.mkOp(), args);
01196      }
01197    }
01198    for (i = c.begin(), iend = c.end(); i != iend; ++i) {
01199      const Expr& cons = (*i).first;
01200      Expr funType = getBaseType(cons).getExpr();
01201      vector<Expr> args;
01202      int j = 0;
01203      for (; j < funType.arity()-1; ++j) {
01204        Type t_j = Type(funType[j]);
01205        if (t_j == t) break;
01206        args.push_back(getConstant(t_j));
01207        if (args.back().isNull()) break;
01208      }
01209      if (j == funType.arity()-1) {
01210        d_getConstantStack.erase(t.getExpr());
01211        return Expr(cons.mkOp(), args);
01212      }
01213    }
01214    FatalAssert(false, "Couldn't find constant for"
01215                +t.toString());
01216   }
01217   DebugAssert(!t.isBool() && !t.isFunction(),
01218               "Expected non-bool, non-function type");
01219   //TODO: this name could be an illegal identifier (i.e. could include spaces)
01220   string name = "datatype_"+t.getExpr().toString();
01221   Expr e = resolveID(name);
01222   d_getConstantStack.erase(t.getExpr());
01223   if (e.isNull()) return newVar(name, t);
01224   return e;
01225 }
01226 
01227 
01228 const Op& TheoryDatatype::getReachablePredicate(const Type& t)
01229 {
01230   DebugAssert(isDatatype(t), "Expected datatype");
01231   DebugAssert(d_reach.find(t.getExpr()) != d_reach.end(),
01232               "Couldn't find reachable predicate");
01233   return d_reach[t.getExpr()];
01234 }
01235 
01236 
01237 bool TheoryDatatype::canCollapse(const Expr& e)
01238 {
01239   DebugAssert(isSelector(e), "canCollapse: Selector expression expected");
01240   DebugAssert(e.arity() == 1, "expected arity 1");
01241   if (isConstructor(e[0])) return true;
01242   if (d_labels.find(e[0]) == d_labels.end()) return false;
01243   DebugAssert(e[0].hasFind() && findExpr(e[0]) == e[0],
01244               "canCollapse: Expected find(e[0])=e[0]");
01245   Unsigned u = d_labels[e[0]].get().get();
01246   Expr cons = getSelectorInfo(e.getOpExpr()).first;
01247   Unsigned uCons = (Unsigned)1 << unsigned(getConsPos(cons));
01248   if ((u & uCons) == 0) return true;
01249   return false;
01250 }