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, "_DATATYPE", true);
00054   getEM()->newKind(CONSTRUCTOR, "_CONSTRUCTOR");
00055   getEM()->newKind(SELECTOR, "_SELECTOR");
00056   getEM()->newKind(TESTER, "_TESTER");
00057 
00058   vector<int> kinds;
00059   kinds.push_back(DATATYPE);
00060   kinds.push_back(TESTER);
00061   kinds.push_back(CONSTRUCTOR);
00062   kinds.push_back(SELECTOR);
00063 
00064   registerTheory(this, kinds);
00065 }
00066 
00067 
00068 TheoryDatatype::~TheoryDatatype() {
00069   delete d_rules;
00070 }
00071 
00072 
00073 void TheoryDatatype::instantiate(const Expr& e, const bigunsigned& u)
00074 {
00075   DebugAssert(!e.hasFind() || findExpr(e) == e,
00076               "datatype: instantiate: Expected find(e)=e");
00077   if (isConstructor(e)) return;
00078   DebugAssert(u != 0 && (u & (u-1)) == 0,
00079               "datatype: instantiate: Expected single label in u");
00080   DebugAssert(d_datatypes.find(getBaseType(e).getExpr()) != d_datatypes.end(),
00081               "datatype: instantiate: Unexpected type: "+getBaseType(e).toString()
00082               +"\n\n for expression: "+e.toString());
00083   ExprMap<unsigned>& c = d_datatypes[getBaseType(e).getExpr()];
00084   ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end();
00085   for (; c_it != c_end; ++c_it) {
00086     if (u & (1 << bigunsigned((*c_it).second))) break;
00087   }
00088   DebugAssert(c_it != c_end,
00089               "datatype: instantiate: couldn't find constructor");
00090   const Expr& cons = (*c_it).first;
00091 
00092   if (!cons.isFinite() && !e.isSelected()) return;
00093 
00094   Type consType = getBaseType(cons);
00095   if (consType.arity() == 1) {
00096     enqueueFact(d_rules->dummyTheorem(d_facts, e.eqExpr(cons)));
00097     return;
00098   }
00099   // create vars
00100   vector<Expr> vars;
00101   for (int i = 0; i < consType.arity()-1; ++i) {
00102     vars.push_back(getEM()->newBoundVarExpr(consType[i]));
00103   }
00104   Expr e2 = getEM()->newClosureExpr(EXISTS, vars,
00105                                     e.eqExpr(Expr(cons.mkOp(), vars)));
00106   enqueueFact(d_rules->dummyTheorem(d_facts, e2));
00107 }
00108 
00109 
00110 void TheoryDatatype::initializeLabels(const Expr& e, const Type& t)
00111 {
00112   DebugAssert(findExpr(e) == e,
00113               "datatype: initializeLabels: Expected find(e)=e");
00114   DebugAssert(d_datatypes.find(t.getExpr()) != d_datatypes.end(),
00115               "Unknown datatype: "+t.getExpr().toString());
00116   ExprMap<unsigned>& c = d_datatypes[t.getExpr()];
00117   DebugAssert(d_labels.find(e) == d_labels.end(),
00118               "datatype: initializeLabels: expected unlabeled expr");
00119   if (isConstructor(e)) {
00120     Expr cons = getConstructor(e);
00121     DebugAssert(c.find(cons) != c.end(),
00122                 "datatype: initializeLabels: Couldn't find constructor "
00123                 +cons.toString());
00124     bigunsigned position = c[cons];
00125     d_labels.insert(e,
00126       SmartCDO<bigunsigned>(theoryCore()->getCM()->getCurrentContext(),
00127                             1 << position, 0));
00128   }
00129   else {
00130     DebugAssert(c.size() > 0, "No constructors?");
00131     bigunsigned value = (1 << bigunsigned(c.size())) - 1;
00132     d_labels.insert(e,
00133       SmartCDO<bigunsigned>(theoryCore()->getCM()->getCurrentContext(),
00134                             value, 0));
00135     if (value == 1) instantiate(e, 1);
00136     else {
00137       if (!d_smartSplits || t.getExpr().isFinite()) d_splitters.push_back(e);
00138     }
00139   }
00140 }
00141 
00142 
00143 void TheoryDatatype::mergeLabels(const Theorem& thm,
00144                                  const Expr& e1, const Expr& e2)
00145 {
00146   DebugAssert(e2.hasFind() && findExpr(e2) == e2,
00147               "datatype: mergeLabels: Expected find(e2)=e2");
00148   DebugAssert(d_labels.find(e1) != d_labels.end() &&
00149               d_labels.find(e2) != d_labels.end(),
00150               "mergeLabels: expr is not labeled");
00151   DebugAssert(getBaseType(e1) == getBaseType(e2), "Expected same type");
00152   bigunsigned u = d_labels[e2].get().get();
00153   bigunsigned uNew = u & d_labels[e1].get().get();
00154   if (u != uNew) {
00155     if (!thm.isNull()) d_facts.push_back(thm);
00156     d_labels[e2].get().set(uNew);
00157     if (uNew == 0)
00158       setInconsistent(d_rules->dummyTheorem(d_facts, falseExpr()));
00159   }
00160   if (uNew != 0 && ((uNew - 1) & uNew) == 0) {
00161     instantiate(e2, uNew);
00162   }
00163 }
00164 
00165 
00166 void TheoryDatatype::mergeLabels(const Theorem& thm, const Expr& e,
00167                                  unsigned position, bool positive)
00168 {
00169   DebugAssert(e.hasFind() && findExpr(e) == e,
00170               "datatype: mergeLabels2: Expected find(e)=e");
00171   DebugAssert(d_labels.find(e) != d_labels.end(),
00172               "mergeLabels2: expr is not labeled");
00173   bigunsigned u = d_labels[e].get().get();
00174   bigunsigned uNew = 1 << bigunsigned(position);
00175   if (positive) {
00176     uNew = u & uNew;
00177     if (u == uNew) return;
00178   } else if (u & uNew) uNew = u - uNew;
00179   else return;
00180   d_facts.push_back(thm);
00181   d_labels[e].get().set(uNew);
00182   if (uNew == 0)
00183     setInconsistent(d_rules->dummyTheorem(d_facts, falseExpr()));
00184   else if (((uNew - 1) & uNew) == 0) {
00185     instantiate(e, uNew);
00186   }
00187 }
00188 
00189 
00190 void TheoryDatatype::addSharedTerm(const Expr& e)
00191 {
00192   if (getBaseType(e).getExpr().getKind() == DATATYPE &&
00193       d_labels.find(e) == d_labels.end()) {
00194     initializeLabels(e, getBaseType(e));
00195     e.addToNotify(this, Expr());
00196   }
00197 }
00198 
00199 
00200 void TheoryDatatype::assertFact(const Theorem& e)
00201 {
00202   if (!e.isRewrite()) {
00203     const Expr& expr = e.getExpr();
00204     if (expr.getOpKind() == TESTER) {
00205       mergeLabels(e, expr[0],
00206                   getConsPos(getConsForTester(expr.getOpExpr())),
00207                   true);
00208     }
00209     else if (expr.isNot() && expr[0].getOpKind() == TESTER) {
00210       mergeLabels(e, expr[0][0],
00211                   getConsPos(getConsForTester(expr[0].getOpExpr())),
00212                   false);
00213     }
00214   }
00215 }
00216 
00217 
00218 void TheoryDatatype::checkSat(bool fullEffort)
00219 {
00220   bool done = false;
00221   while (!done && d_splittersIndex < d_splitters.size()) {
00222     Expr e = d_splitters[d_splittersIndex];
00223     if ((!d_smartSplits || getBaseType(e).getExpr().isFinite()) &&
00224         findExpr(e) == e) {
00225       DebugAssert(d_labels.find(e) != d_labels.end(),
00226                   "checkSat: expr is not labeled");
00227       bigunsigned u = d_labels[e].get().get();
00228       if ((u & (u-1)) != 0) {
00229         done = true;
00230         DebugAssert(!d_splitterAsserted || !fullEffort,
00231                     "splitter should have been resolved");
00232         if (!d_splitterAsserted) {
00233           DebugAssert
00234             (d_datatypes.find(getBaseType(e).getExpr()) != d_datatypes.end(),
00235              "datatype: checkSat: Unexpected type: "+getBaseType(e).toString()
00236              +"\n\n for expression: "+e.toString());
00237           ExprMap<unsigned>& c = d_datatypes[getBaseType(e).getExpr()];
00238           ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end();
00239           vector<Expr> vec;
00240           for (; c_it != c_end; ++c_it) {
00241             if (u & (1 << bigunsigned((*c_it).second))) {
00242               vec.push_back(datatypeTestExpr((*c_it).first.getName(), e));
00243             }
00244           }
00245           DebugAssert(vec.size() > 1, "datatype: checkSat: expected 2 or more possible constructors");
00246           enqueueFact(d_rules->dummyTheorem(d_facts, Expr(OR, vec)));
00247           d_splitterAsserted = true;
00248         }
00249       }
00250     }
00251     if (d_smartSplits && !done && isSelector(e)) {
00252       Expr f = findExpr(e[0]);
00253       DebugAssert(d_labels.find(f) != d_labels.end(),
00254                   "checkSat: expr is not labeled");
00255       bigunsigned u = d_labels[f].get().get();
00256       if ((u & (u-1)) != 0) {
00257         pair<Expr, unsigned> selectorInfo = getSelectorInfo(e.getOpExpr());
00258         bigunsigned pos = getConsPos(selectorInfo.first);
00259         if (u & (1 << pos)) {
00260           done = true;
00261           DebugAssert(!d_splitterAsserted || !fullEffort,
00262                       "splitter should have been resolved");
00263           if (!d_splitterAsserted) {
00264             addSplitter(datatypeTestExpr(selectorInfo.first.getName(), f));
00265             d_splitterAsserted = true;
00266           }
00267         }
00268       }
00269     }
00270     if (!done) {
00271       d_splitterAsserted = false;
00272       d_splittersIndex = d_splittersIndex + 1;
00273     }
00274   }
00275 }
00276 
00277 
00278 Theorem TheoryDatatype::rewrite(const Expr& e)
00279 {
00280   // TODO: UF rewrite?
00281   Theorem thm;
00282   if (isSelector(e)) {
00283     if (canCollapse(e)) {
00284       thm = d_rules->rewriteSelCons(d_facts, e);
00285       return transitivityRule(thm, simplify(thm.getRHS()));
00286     }
00287   }
00288   else if (isTester(e)) {
00289     if (isConstructor(e[0])) {
00290       return d_rules->rewriteTestCons(e);
00291     }
00292   }
00293   return reflexivityRule(e);
00294 }
00295 
00296 
00297 void TheoryDatatype::setup(const Expr& e)
00298 {
00299   if (getBaseType(e).getExpr().getKind() == DATATYPE &&
00300       d_labels.find(e) == d_labels.end()) {
00301     initializeLabels(e, getBaseType(e));
00302     e.addToNotify(this, Expr());
00303   }
00304   if (e.getKind() != APPLY) return;
00305   if (isConstructor(e) && e.arity() > 0) {
00306     enqueueFact(d_rules->noCycle(e));
00307   }
00308   if (isSelector(e)) {
00309     if (d_smartSplits) d_splitters.push_back(e);
00310     e[0].setSelected();
00311     mergeLabels(Theorem(), e[0], e[0]);
00312   }
00313   setupCC(e);
00314 }
00315 
00316 
00317 void TheoryDatatype::update(const Theorem& e, const Expr& d)
00318 {
00319   if (d.isNull()) {
00320     const Expr& lhs = e.getLHS();
00321     const Expr& rhs = e.getRHS();
00322     if (isConstructor(lhs) && isConstructor(rhs) &&
00323         lhs.isApply() && rhs.isApply() &&
00324         lhs.getOpExpr() == rhs.getOpExpr()) {
00325       enqueueFact(d_rules->decompose(e));
00326     }
00327     else {
00328       Theorem thm(e);
00329       if (lhs.isSelected() && !rhs.isSelected()) {
00330         d_facts.push_back(e);
00331         rhs.setSelected();
00332         thm = Theorem();
00333       }
00334       mergeLabels(thm, lhs, rhs);
00335     }
00336   }
00337   else {
00338     const Theorem& dEQdsig = d.getSig();
00339     if (!dEQdsig.isNull()) {
00340       const Expr& dsig = dEQdsig.getRHS();
00341       Theorem thm = updateHelper(d);
00342       const Expr& sigNew = thm.getRHS();
00343       if (sigNew == dsig) return;
00344       dsig.setRep(Theorem());
00345       if (isSelector(sigNew) && canCollapse(sigNew)) {
00346         d.setSig(Theorem());
00347         enqueueFact(transitivityRule(thm, d_rules->rewriteSelCons(d_facts, sigNew)));
00348       }
00349       else if (isTester(sigNew) && isConstructor(sigNew[0])) {
00350         d.setSig(Theorem());
00351         enqueueFact(transitivityRule(thm, d_rules->rewriteTestCons(sigNew)));
00352       }
00353       else {
00354         const Theorem& repEQsigNew = sigNew.getRep();
00355         if (!repEQsigNew.isNull()) {
00356           d.setSig(Theorem());
00357           enqueueFact(transitivityRule(repEQsigNew, symmetryRule(thm)));
00358         }
00359         else {
00360           int k, ar(d.arity());
00361           for (k = 0; k < ar; ++k) {
00362             if (sigNew[k] != dsig[k]) {
00363               sigNew[k].addToNotify(this, d);
00364             }
00365           }
00366           d.setSig(thm);
00367           sigNew.setRep(thm);
00368         }
00369       }
00370     }
00371   }
00372 }
00373 
00374 
00375 Theorem TheoryDatatype::solve(const Theorem& e)
00376 {
00377   DebugAssert(e.isRewrite() && e.getLHS().isTerm(), "Expected equality");
00378   const Expr& lhs = e.getLHS();
00379   if (isConstructor(lhs) && !isConstructor(e.getRHS())) {
00380     return symmetryRule(e);
00381   }
00382   return e;
00383 }
00384 
00385 
00386 void TheoryDatatype::checkType(const Expr& e)
00387 {
00388   switch (e.getKind()) {
00389     case DATATYPE: {
00390       if (e.arity() != 1 || !e[0].isString())
00391         throw Exception("Ill-formed datatype"+e.toString());
00392       if (resolveID(e[0].getString()) != e)
00393         throw Exception("Unknown datatype"+e.toString());
00394       break;
00395     }
00396     case CONSTRUCTOR:
00397     case SELECTOR:
00398     case TESTER:
00399       throw Exception("Non-type: "+e.toString());
00400     default:
00401       DebugAssert(false, "Unexpected kind in TheoryDatatype::checkType"
00402                   +getEM()->getKindName(e.getKind()));
00403   }
00404 }
00405 
00406 
00407 void TheoryDatatype::computeType(const Expr& e)
00408 {
00409   switch (e.getOpKind()) {
00410     case CONSTRUCTOR:
00411     case SELECTOR:
00412     case TESTER: {
00413       DebugAssert(e.isApply(), "Expected application");
00414       Expr op = e.getOp().getExpr();
00415       Type t = op.lookupType();
00416       DebugAssert(!t.isNull(), "Expected operator to be well-typed");
00417       if (t.getExpr().getKind() == DATATYPE) {
00418         if (e.arity() != 0)
00419           throw TypecheckException("Expected no children: "+e.toString());
00420         e.setType(t);
00421         break;
00422       }
00423       else {
00424         DebugAssert(t.getExpr().getKind() == ARROW, "Expected function type");
00425         if (e.arity() != t.getExpr().arity()-1)
00426           throw TypecheckException("Wrong number of children:\n"+e.toString());
00427         Expr::iterator i = e.begin(), iend = e.end();
00428         Expr::iterator j = t.getExpr().begin();
00429         for (; i != iend; ++i, ++j) {
00430           if (getBaseType(*i) != getBaseType(Type(*j))) {
00431             throw TypecheckException("Type mismatch for expression:\n\n  "
00432                                      + (*i).toString()
00433                                      + "\n\nhas the following type:\n\n  "
00434                                      + (*i).getType().getExpr().toString()
00435                                      + "\n\nbut the expected type is:\n\n  "
00436                                      + (*j).toString()
00437                                      + "\n\nin datatype function application:\n\n  "
00438                                      + e.toString());
00439           }
00440         }
00441         e.setType(*j);
00442       }
00443       break;
00444     }
00445     default:
00446       DebugAssert(false, "Unexpected kind in datatype::computeType: "
00447                   +e.toString());
00448   }
00449 }
00450 
00451 
00452 void TheoryDatatype::computeModelTerm(const Expr& e, std::vector<Expr>& v) {
00453 }
00454 
00455 
00456 
00457 Expr TheoryDatatype::computeTCC(const Expr& e)
00458 {
00459   Expr tcc(Theory::computeTCC(e));
00460   switch (e.getKind()) {
00461     case CONSTRUCTOR:
00462       DebugAssert(e.arity() == 0, "Expected leaf constructor");
00463       return trueExpr();
00464     case APPLY: {
00465       DebugAssert(e.isApply(), "Should be application");
00466       Expr op(e.getOpExpr());
00467       if (op.getKind() != SELECTOR) return tcc;
00468       DebugAssert(e.arity() == 1, "Expected single argument");
00469       const std::pair<Expr,unsigned>& p = getSelectorInfo(op);
00470       Expr tester = datatypeTestExpr(p.first.getName(), e[0]);
00471       return tcc.andExpr(tester);
00472     }
00473     default:
00474       DebugAssert(false,"Unexpected type: "+e.toString());
00475       return trueExpr();
00476   }
00477 }
00478 
00479 ///////////////////////////////////////////////////////////////////////////////
00480 // Pretty-printing                                           //
00481 ///////////////////////////////////////////////////////////////////////////////
00482 
00483 
00484 ExprStream& TheoryDatatype::print(ExprStream& os, const Expr& e) {
00485   switch (os.lang()) {
00486     case PRESENTATION_LANG:
00487       switch (e.getKind()) {
00488         case DATATYPE:
00489           if (e.arity() == 1 && e[0].isString()) {
00490             os << e[0].getString();
00491           }
00492           else e.printAST(os);
00493           break;
00494         case APPLY:
00495           os << e.getOpExpr();
00496           if(e.arity() > 0) {
00497             os << "(" << push;
00498             bool first(true);
00499             for (Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
00500               if(first) first = false;
00501               else os << "," << space;
00502               os << *i;
00503             }
00504             os << push << ")";
00505           }
00506           break;
00507         case CONSTRUCTOR:
00508         case SELECTOR:
00509         case TESTER:
00510           DebugAssert(e.isSymbol(), "Expected symbol");
00511           os << e.getName();
00512           break;
00513         default:
00514           DebugAssert(false, "TheoryDatatype::print: Unexpected kind: "
00515                       +getEM()->getKindName(e.getKind()));
00516       }
00517       break;
00518     case SMTLIB_LANG:
00519       FatalAssert(false, "Not Implemented Yet");
00520       break;
00521     case LISP_LANG:
00522       FatalAssert(false, "Not Implemented Yet");
00523       break;
00524     default:
00525       e.printAST(os);
00526       break;
00527   }
00528   return os;
00529 }
00530 
00531 //////////////////////////////////////////////////////////////////////////////
00532 //parseExprOp:
00533 //translating special Exprs to regular EXPR??
00534 ///////////////////////////////////////////////////////////////////////////////
00535 Expr TheoryDatatype::parseExprOp(const Expr& e)
00536 {
00537   // If the expression is not a list, it must have been already
00538   // parsed, so just return it as is.
00539   if(RAW_LIST != e.getKind()) return e;
00540 
00541   DebugAssert(e.arity() > 0,
00542         "TheoryDatatype::parseExprOp:\n e = "+e.toString());
00543   
00544   DebugAssert(e[0].getKind() == ID,
00545               "Expected ID kind for first elem in list expr");
00546 
00547   const Expr& c1 = e[0][0];
00548   int kind = getEM()->getKind(c1.getString());
00549   switch(kind) {
00550     case DATATYPE: {
00551       DebugAssert(e.arity() > 1,
00552                   "Empty DATATYPE expression\n"
00553                   " (expected at least one datatype): "+e.toString());
00554 
00555       vector<string> names;
00556       vector<vector<string> > allConstructorNames(e.arity()-1);
00557       vector<vector<vector<string> > > allSelectorNames(e.arity()-1);
00558       vector<vector<vector<Expr> > > allTypes(e.arity()-1);
00559       int i,j,k;
00560       Expr dt, constructor, selectors, selector;
00561 
00562       // Get names of datatypes
00563       ExprMap<bool> namesMap;
00564       for (i = 0; i < e.arity()-1; ++i) {
00565         dt = e[i+1];
00566         DebugAssert(dt.getKind() == RAW_LIST && dt.arity() == 2,
00567                     "Bad formed datatype expression"
00568                     +dt.toString());
00569         DebugAssert(dt[0].getKind() == ID,
00570                     "Expected ID kind for datatype name"
00571                     +dt.toString());
00572         names.push_back(dt[0][0].getString());
00573         if (namesMap.count(dt[0][0]) != 0) {
00574           throw ParserException("Datatype name used more than once"+names.back());
00575         }
00576         namesMap.insert(dt[0][0], true);
00577       }
00578 
00579       // Loop through datatypes
00580       for (i = 0; i < e.arity()-1; ++i) {
00581         dt = e[i+1];
00582         DebugAssert(dt[1].getKind() == RAW_LIST && dt[1].arity() > 0,
00583                     "Expected non-empty list for datatype constructors"
00584                     +dt.toString());
00585         dt = dt[1];
00586         vector<string>& constructorNames = allConstructorNames[i];
00587         vector<vector<string> >& selectorNames = allSelectorNames[i];
00588         selectorNames.resize(dt.arity());
00589         vector<vector<Expr> >& types = allTypes[i];
00590         types.resize(dt.arity());
00591         
00592         // Loop through constructors for this datatype
00593         for(j = 0; j < dt.arity(); ++j) {
00594           constructor = dt[j];
00595           DebugAssert(constructor.getKind() == RAW_LIST &&
00596                       (constructor.arity() == 1 || constructor.arity() == 2),
00597                     "Unexpected constructor"+constructor.toString());
00598           DebugAssert(constructor[0].getKind() == ID,
00599                       "Expected ID kind for constructor name"
00600                       +constructor.toString());
00601           constructorNames.push_back(constructor[0][0].getString());
00602 
00603           if (constructor.arity() == 2) {
00604             selectors = constructor[1];
00605             DebugAssert(selectors.getKind() == RAW_LIST && selectors.arity() > 0,
00606                         "Non-empty list expected as second argument of constructor:\n"
00607                         +constructor.toString());
00608 
00609             // Loop through selectors for this constructor
00610             for (k = 0; k < selectors.arity(); ++k) {
00611               selector = selectors[k];
00612               DebugAssert(selector.getKind() == RAW_LIST && selector.arity() == 2,
00613                           "Expected list of arity 2 for selector"
00614                           +selector.toString());
00615               DebugAssert(selector[0].getKind() == ID,
00616                           "Expected ID kind for selector name"
00617                           +selector.toString());
00618               selectorNames[j].push_back(selector[0][0].getString());
00619               DebugAssert(selector[1].getKind() == ID,
00620                           "Expected ID kind for selector type"
00621                           +selector.toString());
00622               if (namesMap.count(selector[1][0]) > 0) {
00623                 types[j].push_back(selector[1][0]);
00624               }
00625               else {              
00626                 types[j].push_back(parseExpr(selector[1]));
00627               }
00628             }
00629           }
00630         }
00631       }
00632 
00633       vector<Type> returnTypes;
00634       dataType(names, allConstructorNames, allSelectorNames, allTypes,
00635                returnTypes);
00636       return returnTypes[0].getExpr();
00637     }
00638 
00639     default: {
00640       throw ParserException("Unexpected datatype expression: "+e.toString());
00641     }
00642   }
00643   return e;
00644 }
00645 
00646 
00647 Type TheoryDatatype::dataType(const string& name,
00648                               const vector<string>& constructors,
00649                               const vector<vector<string> >& selectors,
00650                               const vector<vector<Expr> >& types)
00651 {
00652   vector<string> names;
00653   vector<vector<string> > constructors2;
00654   vector<vector<vector<string> > > selectors2;
00655   vector<vector<vector<Expr> > > types2;
00656   vector<Type> returnTypes;
00657   names.push_back(name);
00658   constructors2.push_back(constructors);
00659   selectors2.push_back(selectors);
00660   types2.push_back(types);
00661   dataType(names, constructors2, selectors2, types2, returnTypes);
00662   return returnTypes[0];
00663 }
00664  
00665 
00666 // Elements of types are either the expr from an existing type or a string
00667 // naming one of the datatypes being defined
00668 void TheoryDatatype::dataType(const vector<string>& names,
00669                               const vector<vector<string> >& allConstructors,
00670                               const vector<vector<vector<string> > >& allSelectors,
00671                               const vector<vector<vector<Expr> > >& allTypes,
00672                               vector<Type>& returnTypes)
00673 {
00674   //  bool wellFounded = false, infinite = false, 
00675   bool thisWellFounded;
00676 
00677   if (names.size() != allConstructors.size() ||
00678       allConstructors.size() != allSelectors.size() ||
00679       allSelectors.size() != allTypes.size()) {
00680     throw TypecheckException
00681       ("dataType: vector sizes don't match");
00682   }
00683 
00684   unsigned i, j, k;
00685   Expr e;
00686 
00687   // Create reachability predicate for constructor cycle detection
00688   vector<Type> funTypeArgs;
00689   funTypeArgs.push_back(Type::anyType(getEM()));
00690   funTypeArgs.push_back(Type::anyType(getEM()));
00691   Op op = newFunction("_reach_"+names[0],
00692                       Type::funType(funTypeArgs, boolType()),
00693                       true /* compute trans closure */);
00694   Op reach = getEM()->newSymbolExpr(op.getExpr().getName(),
00695                                     TRANS_CLOSURE).mkOp();
00696 
00697   for (i = 0; i < names.size(); ++i) {
00698     e = resolveID(names[i]);
00699     if (!e.isNull()) {
00700       throw TypecheckException
00701         ("Attempt to define datatype "+names[i]+":\n "
00702          "This variable is already defined.");
00703     }
00704     e = Expr(DATATYPE, getEM()->newStringExpr(names[i]));
00705     installID(names[i], e);
00706     returnTypes.push_back(Type(e));
00707     d_reach[e] = reach;
00708   }
00709 
00710   for (i = 0; i < names.size(); ++i) {
00711 
00712     const vector<string>& constructors = allConstructors[i];
00713     const vector<vector<string> >& selectors = allSelectors[i];
00714     const vector<vector<Expr> >& types = allTypes[i];
00715 
00716     if (constructors.size() == 0) {
00717       throw TypecheckException
00718         ("datatype: "+names[i]+": must have at least one constructor");
00719     }
00720     if (constructors.size() != selectors.size() ||
00721         selectors.size() != types.size()) {
00722       throw TypecheckException
00723         ("dataType: vector sizes at index "+int2string(i)+" don't match");
00724     }
00725 
00726     ExprMap<unsigned>& constMap = d_datatypes[returnTypes[i].getExpr()];
00727 
00728     for (j = 0; j < constructors.size(); ++j) {
00729       Expr c = resolveID(constructors[j]);
00730       if (!c.isNull()) {
00731         throw TypecheckException
00732           ("Attempt to define datatype constructor "+constructors[j]+":\n "
00733            "This variable is already defined.");
00734       }
00735       c = getEM()->newSymbolExpr(constructors[j], CONSTRUCTOR);
00736 
00737       if (selectors[j].size() != types[j].size()) {
00738         throw TypecheckException
00739           ("dataType: constructor at index "+int2string(i)+", "+int2string(j)+
00740            ": number of selectors does not match number of types");
00741       }
00742       thisWellFounded = true;
00743       const vector<string>& sels = selectors[j];
00744       const vector<Expr>& tps = types[j];
00745 
00746       vector<Type> selTypes;
00747       Type t;
00748       Expr s;
00749       for (k = 0; k < sels.size(); ++k) {
00750         s = resolveID(sels[k]);
00751         if (!s.isNull()) {
00752           throw TypecheckException
00753             ("Attempt to define datatype selector "+sels[k]+":\n "
00754              "This variable is already defined.");
00755         }
00756         s = getEM()->newSymbolExpr(sels[k], SELECTOR);
00757         if (tps[k].isString()) {
00758           t = Type(resolveID(tps[k].getString()));
00759           if (t.isNull()) {
00760             throw TypecheckException
00761               ("Unable to resolve type identifier: "+tps[k].getString());
00762           }
00763         } else t = Type(tps[k]);
00764         if (t.isBool()) {
00765           throw TypecheckException
00766             ("Cannot have BOOLEAN inside of datatype");
00767         }
00768         else if (t.isFunction()) {
00769           throw TypecheckException
00770             ("Cannot have function inside of datatype");
00771         }
00772         
00773         selTypes.push_back(Type(t));
00774         s.setType(returnTypes[i].funType(Type(t)));
00775         if (isDatatype(Type(t)) && !t.getExpr().isWellFounded()) {
00776           thisWellFounded = false;
00777         }
00778         d_selectorMap[s] = pair<Expr,unsigned>(c,k);
00779         installID(sels[k], s);
00780       }
00781       if (thisWellFounded) c.setWellFounded();
00782       if (selTypes.size() == 0) {
00783         c.setType(returnTypes[i]);
00784         c.setFinite();
00785       }
00786       else c.setType(Type::funType(selTypes, returnTypes[i]));
00787       installID(constructors[j], c);
00788       constMap[c] = j;
00789 
00790       string testerString = "is_"+constructors[j];
00791       e = resolveID(testerString);
00792       if (!e.isNull()) {
00793         throw TypecheckException
00794           ("Attempt to define datatype tester "+testerString+":\n "
00795            "This variable is already defined.");
00796       }
00797       e = getEM()->newSymbolExpr(testerString, TESTER);
00798       e.setType(returnTypes[i].funType(boolType()));
00799       d_testerMap[e] = c;
00800       installID(testerString, e);
00801     }
00802   }
00803 
00804   // Compute fixed point for wellfoundedness check
00805 
00806   bool changed, thisFinite;
00807   int firstNotWellFounded;
00808   do {
00809     changed = false;
00810     firstNotWellFounded = -1;
00811     for (i = 0; i < names.size(); ++i) {
00812       ExprMap<unsigned>& c = d_datatypes[returnTypes[i].getExpr()];
00813       ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end();
00814       thisWellFounded = false;
00815       thisFinite = true;
00816       for (; c_it != c_end; ++c_it) {
00817         const Expr& cons = (*c_it).first;
00818         Expr funType = getBaseType(cons).getExpr();
00819         int j;
00820         if (!cons.isFinite()) {
00821           for (j = 0; j < funType.arity()-1; ++j) {
00822             if (!isDatatype(funType[j]) || !funType[j].isFinite())
00823               break;
00824           }
00825           if (j == funType.arity()-1) {
00826             changed = true;
00827             cons.setFinite();
00828           }
00829           else thisFinite = false;
00830         }
00831         if (cons.isWellFounded()) {
00832           thisWellFounded = true;
00833           continue;
00834         }
00835         for (j = 0; j < funType.arity()-1; ++j) {
00836           if (isDatatype(funType[j]) && !funType[j].isWellFounded())
00837             break;
00838         }
00839         if (j == funType.arity()-1) {
00840           changed = true;
00841           cons.setWellFounded();
00842           thisWellFounded = true;
00843         }
00844       }
00845       if (!thisWellFounded) {
00846         if (firstNotWellFounded == -1) firstNotWellFounded = i;
00847       }
00848       else {
00849         if (!returnTypes[i].getExpr().isWellFounded()) {
00850           changed = true;
00851           returnTypes[i].getExpr().setWellFounded();
00852         }
00853       }
00854       if (thisFinite && !returnTypes[i].getExpr().isFinite()) {
00855         changed = true;
00856         returnTypes[i].getExpr().setFinite();
00857       }
00858     }
00859   } while (changed);
00860 
00861   if (firstNotWellFounded >= 0) {
00862     // TODO: uninstall all ID's
00863     throw TypecheckException
00864       ("Datatype "+names[firstNotWellFounded]+" has no finite terms");
00865   }
00866 
00867 }
00868 
00869 Expr TheoryDatatype::datatypeConsExpr(const string& constructor,
00870                                       const vector<Expr>& args)
00871 {
00872   Expr e = resolveID(constructor);
00873   if (e.isNull())
00874     throw Exception("datatype: unknown constructor: "+constructor);
00875   if (!(e.isSymbol() && e.getKind() == CONSTRUCTOR))
00876     throw Exception("datatype: "+constructor+" resolves to: "+e.toString()+
00877                     "\nwhich is not a constructor");
00878   if (args.size() == 0) return e;
00879   return Expr(e.mkOp(), args);
00880 }
00881 
00882 
00883 Expr TheoryDatatype::datatypeSelExpr(const string& selector, const Expr& arg)
00884 {
00885   Expr e = resolveID(selector);
00886   if (e.isNull())
00887     throw Exception("datatype: unknown selector: "+selector);
00888   if (!(e.isSymbol() && e.getKind() == SELECTOR))
00889     throw Exception("datatype: "+selector+" resolves to: "+e.toString()+
00890                     "\nwhich is not a selector");
00891   return Expr(e.mkOp(), arg);
00892 }
00893 
00894 
00895 Expr TheoryDatatype::datatypeTestExpr(const string& constructor, const Expr& arg)
00896 {
00897   Expr e = resolveID("is_"+constructor);
00898   if (e.isNull())
00899     throw Exception("datatype: unknown tester: is_"+constructor);
00900   if (!(e.isSymbol() && e.getKind() == TESTER))
00901     throw Exception("datatype: is_"+constructor+" resolves to: "+e.toString()+
00902                     "\nwhich is not a tester");
00903   return Expr(e.mkOp(), arg);
00904 }
00905 
00906 
00907 const pair<Expr,unsigned>& TheoryDatatype::getSelectorInfo(const Expr& e)
00908 {
00909   DebugAssert(e.getKind() == SELECTOR, "getSelectorInfo called on non-selector: "
00910               +e.toString());
00911   DebugAssert(d_selectorMap.find(e) != d_selectorMap.end(),
00912               "Unknown selector: "+e.toString());
00913   return d_selectorMap[e];
00914 }
00915 
00916 
00917 Expr TheoryDatatype::getConsForTester(const Expr& e)
00918 {
00919   DebugAssert(e.getKind() == TESTER,
00920               "getConsForTester called on non-tester"
00921               +e.toString());
00922   DebugAssert(d_testerMap.find(e) != d_testerMap.end(),
00923               "Unknown tester: "+e.toString());
00924   return d_testerMap[e];
00925 }
00926 
00927 
00928 unsigned TheoryDatatype::getConsPos(const Expr& e)
00929 {
00930   DebugAssert(e.getKind() == CONSTRUCTOR,
00931               "getConsPos called on non-constructor");
00932   Type t = getBaseType(e);
00933   if (t.isFunction()) t = t[t.arity()-1];
00934   DebugAssert(isDatatype(t), "Expected datatype");
00935   DebugAssert(d_datatypes.find(t.getExpr()) != d_datatypes.end(),
00936               "Could not find datatype: "+t.toString());
00937   ExprMap<unsigned>& constMap = d_datatypes[t.getExpr()];
00938   DebugAssert(constMap.find(e) != constMap.end(),
00939               "Could not find constructor: "+e.toString());
00940   return constMap[e];
00941 }
00942 
00943 
00944 Expr TheoryDatatype::getConstant(const Type& t)
00945 {
00946   //TODO: this could still cause an infinite loop
00947   if (isDatatype(t)) {
00948    DebugAssert(d_datatypes.find(t.getExpr()) != d_datatypes.end(),
00949                "Unknown datatype: "+t.getExpr().toString());
00950    ExprMap<unsigned>& c = d_datatypes[t.getExpr()];
00951    ExprMap<unsigned>::iterator i = c.begin(), iend = c.end();
00952    for (; i != iend; ++i) {
00953      const Expr& cons = (*i).first;
00954      if (!getBaseType(cons).isFunction()) return cons;
00955    }
00956    for (i = c.begin(), iend = c.end(); i != iend; ++i) {
00957      const Expr& cons = (*i).first;
00958      if (!cons.isWellFounded()) continue;
00959      if (!getBaseType(cons).isFunction()) return cons;
00960      Expr funType = getBaseType(cons).getExpr();
00961      vector<Expr> args;
00962      int j = 0;
00963      for (; j < funType.arity()-1; ++j) {
00964        Type t_j = Type(funType[j]);
00965        if (t_j == t) break;
00966        args.push_back(getConstant(t_j));
00967      }
00968      if (j == funType.arity()-1) return Expr(cons.mkOp(), args);
00969    }
00970    FatalAssert(false, "Couldn't find well-founded constructor for"
00971                +t.toString());
00972   }
00973   DebugAssert(!t.isBool() && !t.isFunction(),
00974               "Expected non-bool, non-function type");
00975   string name = "datatype_"+t.getExpr().toString();
00976   Expr e = resolveID(name);
00977   if (e.isNull()) return newVar(name, t);
00978   return e;
00979 }
00980 
00981 
00982 const Op& TheoryDatatype::getReachablePredicate(const Type& t)
00983 {
00984   DebugAssert(isDatatype(t), "Expected datatype");
00985   DebugAssert(d_reach.find(t.getExpr()) != d_reach.end(),
00986               "Couldn't find reachable predicate");
00987   return d_reach[t.getExpr()];
00988 }
00989 
00990 
00991 bool TheoryDatatype::canCollapse(const Expr& e)
00992 {
00993   DebugAssert(isSelector(e), "canCollapse: Selector expression expected");
00994   DebugAssert(e.arity() == 1, "expected arity 1");
00995   if (isConstructor(e[0])) return true;
00996   if (d_labels.find(e[0]) == d_labels.end()) return false;
00997   DebugAssert(e[0].hasFind() && findExpr(e[0]) == e[0],
00998               "canCollapse: Expected find(e[0])=e[0]");
00999   bigunsigned u = d_labels[e[0]].get().get();
01000   Expr cons = getSelectorInfo(e.getOpExpr()).first;
01001   bigunsigned uCons = 1 << bigunsigned(getConsPos(cons));
01002   if ((u & uCons) == 0) return true;
01003   return false;
01004 }

Generated on Tue Jul 3 14:33:41 2007 for CVC3 by  doxygen 1.5.1