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

Generated on Thu Apr 13 16:57:35 2006 for CVC Lite by  doxygen 1.4.4