CVC3

theory_core.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file theory_core.cpp
00004  *
00005  * Author: Clark Barrett, Vijay Ganesh (CNF converter)
00006  *
00007  * Created: Thu Jan 30 16:57:52 2003
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 #include <locale>
00022 #include <cctype>
00023 #include <ctime>
00024 #include "command_line_flags.h"
00025 #include "expr.h"
00026 #include "notifylist.h"
00027 #include "pretty_printer.h"
00028 #include "common_proof_rules.h"
00029 #include "parser_exception.h"
00030 #include "typecheck_exception.h"
00031 #include "smtlib_exception.h"
00032 #include "eval_exception.h"
00033 #include "theory_core.h"
00034 #include "expr_transform.h"
00035 #include "core_proof_rules.h"
00036 #include "theorem_manager.h"
00037 #include "translator.h"
00038 #include "theory_arith.h" // for isReal() tester
00039 
00040 using namespace std;
00041 
00042 
00043 namespace CVC3 {
00044 
00045 
00046   //! Implementation of PrettyPrinter class
00047   /*! \ingroup PrettyPrinting */
00048   class PrettyPrinterCore: public PrettyPrinter {
00049   private:
00050     TheoryCore *d_core;
00051     //! Disable the default constructor
00052     PrettyPrinterCore() { }
00053   public:
00054     //! Constructor
00055     PrettyPrinterCore(TheoryCore* core): d_core(core) { }
00056     ExprStream& print(ExprStream& os, const Expr& e)
00057     {
00058       if(e.isString())
00059   return e.print(os);
00060       else if (e.isApply())
00061         return d_core->theoryOf(e)->print(os, e);
00062       else if(d_core->hasTheory(e.getKind()))
00063   return d_core->theoryOf(e.getKind())->print(os, e);
00064       else
00065   return e.print(os);
00066     }
00067   };
00068 
00069 
00070   class TypeComputerCore: public ExprManager::TypeComputer {
00071     TheoryCore *d_core;
00072   public:
00073     TypeComputerCore(TheoryCore* core): d_core(core) { }
00074     void computeType(const Expr& e)
00075     {
00076       DebugAssert(!e.isVar(), "Variables should have a type: "+e.toString());
00077       Theory* i = d_core->theoryOf(e.getKind());
00078       if (e.isApply()) i = d_core->theoryOf(e);
00079       i->computeType(e);
00080       DebugAssert(!e.lookupType().getExpr().isNull(), "Type not set by computeType");
00081     }
00082     void checkType(const Expr& e)
00083     {
00084       if (!e.isType()) throw Exception
00085           ("Tried to use non-type as a type: "+e.toString());
00086       d_core->theoryOf(e)->checkType(e);
00087       e.setValidType();
00088     }
00089     Cardinality finiteTypeInfo(Expr& e, Unsigned& n,
00090                                bool enumerate, bool computeSize)
00091     {
00092       DebugAssert(e.isType(), "finiteTypeInfo called on non-type");
00093       return d_core->theoryOf(e)->finiteTypeInfo(e, n, enumerate, computeSize);
00094     }
00095   };
00096 
00097 
00098   ostream& operator<<(ostream& os, const NotifyList& l)
00099   {
00100     os << "NotifyList(\n";
00101     for(size_t i=0,iend=l.size(); i<iend; ++i) {
00102       os << "[" << l.getTheory(i)->getName() << ", " << l.getExpr(i) << "]\n";
00103     }
00104     return os << ")";
00105   }
00106 
00107 
00108 }
00109 
00110 
00111 using namespace CVC3;
00112 
00113 
00114 /*****************************************************************************/
00115 /*
00116  * Private helper functions
00117  */
00118 /*****************************************************************************/
00119 
00120 
00121 bool TheoryCore::processFactQueue(EffortLevel effort)
00122 {
00123   Theorem thm;
00124   vector<Theory*>::iterator i, iend = d_theories.end();
00125   bool lemmasAdded = false;
00126   do {
00127     processUpdates();
00128     while (!d_queue.empty() && !d_inconsistent && !timeLimitReached()) {
00129       thm = d_queue.front();
00130       d_queue.pop();
00131       assertFactCore(thm);
00132       processUpdates();
00133     };
00134 
00135     if (d_inconsistent) break;
00136 
00137     while (!d_queueSE.empty() && !timeLimitReached()) {
00138       // Copy a Theorem by value, to guarantee valid reference down
00139       // the call chain
00140       lemmasAdded = true;
00141       Theorem thm(d_queueSE.back());
00142       d_queueSE.pop_back();
00143       d_coreSatAPI->addLemma(thm);
00144     }
00145 
00146     if (effort > LOW) {
00147       for(i = d_theories.begin(); d_update_thms.empty() && d_queue.empty() && i != iend && !d_inconsistent && !timeLimitReached(); ++i) {
00148         (*i)->checkSat(effort == FULL && !lemmasAdded);
00149       }
00150     }
00151   } while ((!d_queue.empty() || !d_update_thms.empty()) && !d_inconsistent && !timeLimitReached());
00152 
00153   if (d_inconsistent) {
00154     d_update_thms.clear();
00155     d_update_data.clear();
00156     while(d_queue.size()) d_queue.pop();
00157     d_queueSE.clear();
00158     return false;
00159   }
00160 
00161   if (timeLimitReached()) {
00162     // clear all work queues to satisfy invariants
00163     d_update_thms.clear();
00164     d_update_data.clear();
00165     while (!d_queue.empty()) d_queue.pop();
00166     d_queueSE.clear();
00167   }
00168 
00169   return lemmasAdded;
00170 }
00171 
00172 
00173 void TheoryCore::processNotify(const Theorem& e, NotifyList *L)
00174 {
00175   ++d_inUpdate;
00176   DebugAssert(L, "Expected non-NULL notify list");
00177   for(unsigned k = 0; k < L->size() && !d_inconsistent; ++k) {
00178     L->getTheory(k)->update(e, L->getExpr(k));
00179   }
00180   --d_inUpdate;
00181 }
00182 
00183 
00184 Theorem TheoryCore::simplify(const Expr& e)
00185 {
00186   DebugAssert(d_simpStack.count(e) == 0, "TheoryCore::simplify: loop detected over e =\n"
00187         +e.toString());
00188   DebugAssert(d_simpStack.size() < 10000,
00189         "TheoryCore::simplify: too deep recursion depth");
00190   IF_DEBUG(d_simpStack[e] = true;)
00191 
00192   // Normally, if an expr has a find, we don't need to simplify, just return the find.
00193   // However, if we are in the middle of an update, the find may not yet be updated, so
00194   // we should do a full simplify.  The exception is expressions like
00195   // uninterp. functions or reads that use a congruence closure algorithm that
00196   // relies on not simplifying inside of expressions that have finds.
00197   if (e.hasFind()) {
00198     DebugAssert((find(e).getRHS().hasFind() && find(e).getRHS().isTerm())
00199                 || find(e).getRHS().isTrue()
00200                 || find(e).getRHS().isFalse(), "Unexpected find pointer");
00201     if (d_inUpdate) {
00202       if (e.usesCC()) {
00203         Theorem thm = find(e);
00204         if (!thm.isRefl()) {
00205           thm = transitivityRule(thm, simplify(thm.getRHS()));
00206         }
00207         IF_DEBUG(d_simpStack.erase(e);)
00208         return thm;
00209       }
00210     }
00211     else {
00212       IF_DEBUG(d_simpStack.erase(e);)
00213       return find(e);
00214     }
00215   }
00216 
00217   if(e.validSimpCache()) {
00218     IF_DEBUG(d_simpStack.erase(e);)
00219     return e.getSimpCache();
00220   }
00221 
00222   Theorem thm;
00223   if (e.isVar()) {
00224     thm = rewriteCore(e);
00225   }
00226   else {
00227     thm = rewriteCore(theoryOf(e.getOpKind())->simplifyOp(e));
00228   }
00229 
00230   const Expr& e2 = thm.getRHS();
00231 #ifdef _CVC3_DEBUG_MODE
00232   if (!e2.usesCC()) { //2.isTerm() || !e2.hasFind()) {
00233     // The rewriter should guarantee that all of its children are simplified.
00234     for (int k=0; k<e2.arity(); ++k) {
00235       Expr simplified(simplify(e2[k]).getRHS());
00236       DebugAssert(e2[k]==simplified,"Simplify Error 1:\n e2[k="+int2string(k)
00237                   +"] = "
00238                   +e2[k].toString() + "\nSimplified = "
00239                   +simplified.toString()
00240                   +"\ne2 = "+e2.toString());
00241     }
00242   }
00243   Expr rewritten(rewriteCore(e2).getRHS());
00244   DebugAssert(e2==rewritten,"Simplify Error 2: e2 = \n"
00245               +e2.toString() + "\nSimplified rewritten = \n"
00246               +rewritten.toString());
00247 #endif
00248   e.setSimpCache(thm);
00249   if (e != e2 && !e2.hasFind()) {
00250     e2.setSimpCache(reflexivityRule(e2));
00251   }
00252   IF_DEBUG(d_simpStack.erase(e);)
00253   return thm;
00254 }
00255 
00256 
00257 Theorem TheoryCore::rewriteCore(const Theorem& e)
00258 {
00259   DebugAssert(e.isRewrite(),
00260         "rewriteCore(thm): not equality or iff:\n  " + e.toString());
00261   return transitivityRule(e, rewriteCore(e.getRHS()));
00262 }
00263 
00264 
00265 /* Recurse through s looking for atomic formulas (or terms in the case of
00266  * then/else branches of ite's) and use the notifylist mechanism to indicate
00267  * that the atomic formula e depends on these atomic formulas and terms.  Used
00268  * by registerAtom. */
00269 void TheoryCore::setupSubFormulas(const Expr& s, const Expr& e,
00270                                   const Theorem& thm)
00271 {
00272   if (s.isAtomic()) {
00273     setupTerm(s, theoryOf(s), thm);
00274     s.addToNotify(this, e);
00275   }
00276   else if (s.isAbsAtomicFormula()) {
00277     setupTerm(s, theoryOf(s), thm);
00278     for (int i = 0; i < s.arity(); ++i) {
00279       s[i].addToNotify(this, e);
00280     }
00281     if (s != e) s.addToNotify(this, e);
00282   }
00283   else {
00284     for (int i = 0; i < s.arity(); ++i) {
00285       setupSubFormulas(s[i], e, thm);
00286     }
00287   }
00288 }
00289 
00290 
00291 void TheoryCore::processUpdates()
00292 {
00293   Theorem e;
00294   Expr d;
00295   DebugAssert(d_update_thms.size() == d_update_data.size(),
00296               "Expected same size");
00297   while (!d_inconsistent && !d_update_thms.empty()) {
00298     e = d_update_thms.back();
00299     d_update_thms.pop_back();
00300     d = d_update_data.back();
00301     d_update_data.pop_back();
00302 
00303     DebugAssert(d.isAbsAtomicFormula(), "Expected atomic formula");
00304     Theorem thm = simplify(d);
00305     if (thm.getRHS().isTrue()) {
00306       setFindLiteral(d_commonRules->iffTrueElim(thm));
00307     }
00308     else if (thm.getRHS().isFalse()) {
00309       setFindLiteral(d_commonRules->iffFalseElim(thm));
00310     }
00311     else {
00312       DebugAssert(e.isRewrite(), "Unexpected theorem in TheoryCore::update");
00313       if (e.getRHS().getType().isBool()) continue;
00314       find(e.getRHS()).getRHS().addToNotify(this, d);
00315       if (thm.getRHS().isAbsAtomicFormula()) thm.getRHS().addToNotify(this, d);
00316     }
00317   }
00318 }
00319 
00320 
00321 void TheoryCore::assertFactCore(const Theorem& e)
00322 {
00323   IF_DEBUG(string indentStr(getCM()->scopeLevel(), ' ');)
00324   TRACE("assertFactCore", indentStr, "AssertFactCore: ", e.getExpr().toString(PRESENTATION_LANG));
00325 
00326   Theorem estarThm(e);
00327   Expr estar = e.getExpr();
00328   IF_DEBUG(Expr e2 = estar;)
00329   Theorem equiv = simplify(estar);
00330   if (!equiv.isRefl()) {
00331     estarThm = iffMP(e, equiv);
00332     // Make sure originally asserted atomic formulas have a find pointer
00333     if (!estar.isTrue() && estar.isAbsLiteral()) {
00334       setFindLiteral(e);
00335     }
00336     estar = estarThm.getExpr();
00337   }
00338   if (estar.isAbsLiteral()) {
00339     if (estar.isEq()) {
00340       Theorem solvedThm(solve(estarThm));
00341       if(estar != solvedThm.getExpr()) setFindLiteral(estarThm);
00342       if (!solvedThm.getExpr().isTrue())
00343         assertEqualities(solvedThm);
00344     }
00345     else if (estar.isFalse()) {
00346       IF_DEBUG(debugger.counter("conflicts from simplifier")++;)
00347       setInconsistent(estarThm);
00348     }
00349     else if (!estar.isTrue()) {
00350       assertFormula(estarThm);
00351     }
00352     else {
00353       // estar is true, nothing will be done
00354       // Make sure equivalence classes of equations between two terms with finds get merged
00355       // We skip this check for now because unsolvable nonlinear equations bring up this kind of
00356       // problems, i.e. x^2 + y^2 = z^2 is not solved, it is true, but the find of LHS and RHS are
00357       // different
00358       if (!incomplete() && e.isRewrite() &&
00359           e.getLHS().hasFind() && e.getRHS().hasFind() &&
00360           find(e.getLHS()).getRHS() != find(e.getRHS()).getRHS()) {
00361         TRACE("assertFactCore", "Problem (LHS of): ", e.getExpr(), "");
00362         TRACE("assertFactCore", find(e.getLHS()).getRHS(), " vs ", find(e.getRHS()).getRHS());
00363         IF_DEBUG(cerr << "Warning: Equivalence classes didn't get merged" << endl;)
00364       }
00365     }
00366   } else if (estar.isAnd()) {
00367     for(int i=0,iend=estar.arity(); i<iend && !d_inconsistent; ++i)
00368       assertFactCore(d_commonRules->andElim(estarThm, i));
00369     return;
00370   }
00371   else {
00372     // Notify the search engine
00373     enqueueSE(estarThm);
00374   }
00375 
00376   DebugAssert(!e2.isAbsLiteral() || e2.hasFind()
00377         || (e2.isNot() && e2[0].hasFind()),
00378         "assertFactCore: e2 = "+e2.toString());
00379   DebugAssert(!estar.isAbsLiteral() || estar.hasFind()
00380         || (estar.isNot() && estar[0].hasFind()),
00381         "assertFactCore: estar = "+estar.toString());
00382 }
00383 
00384 
00385 void TheoryCore::assertFormula(const Theorem& thm)
00386 {
00387   const Expr& e = thm.getExpr();
00388   DebugAssert(e.isAbsLiteral(),"assertFormula: nonliteral asserted:\n  "
00389               +thm.toString());
00390   IF_DEBUG(string indentStr(getCM()->scopeLevel(), ' ');)
00391   TRACE("assertFormula",indentStr,"AssertFormula: ", e.toString(PRESENTATION_LANG));
00392 
00393   Theory* i = theoryOf(e);
00394   Theory* i2 = i;
00395 
00396   // Recursively set up terms in this formula
00397   setupTerm(e,i,thm);
00398 
00399   // Use find to force af to rewrite to TRUE and NOT af to rewrite to FALSE,
00400   // where af is an atomic formula.  If af is an equality, make sure its lhs
00401   // is greater than its rhs so the simplifier will be able to use the find.
00402   DebugAssert(!e.isNot() || (!e.hasFind() && !e[0].hasFind()),
00403               "Expected negated argument to assertFormula to not have find");
00404   setFindLiteral(thm);
00405 
00406   // Special processing for existentials, equalities, disequalities
00407   switch (e.getKind()) {
00408     case EXISTS:
00409       // Do not send existential quantifiers to DPs; instead, skolemize them
00410       enqueueFact(d_commonRules->skolemize(thm));
00411       return;
00412     case NOT:
00413       if (e[0].isEq()) {
00414 
00415         // Save the disequality for later processing
00416         e[0][0].addToNotify(this, e);
00417         e[0][1].addToNotify(this, e);
00418         i2 = theoryOf(getBaseType(e[0][0]));
00419         DebugAssert(e[0][0] > e[0][1], "Expected lhs of diseq to be greater");
00420 //     if(e[0][0] < e[0][1]) {
00421 //       Expr e2 = e[0][1].eqExpr(e[0][0]);
00422 //       DebugAssert(!e2.hasFind(), "already has find");
00423 //       thm2 = transitivityRule(d_commonRules->rewriteUsingSymmetry(e2),
00424 //                               d_commonRules->notToIff(thm));
00425 //       setFindLiteral(d_commonRules->iffFalseElim(thm2));
00426 //     }
00427       }
00428       break;
00429     case EQ:
00430       i2 = theoryOf(getBaseType(e[0]));
00431       if (e[0] < e[1]) {
00432         // this can happen because of the solver
00433         Expr e2 = e[1].eqExpr(e[0]);
00434         if (!e2.hasFind()) {
00435           Theorem thm2 =
00436             transitivityRule(d_commonRules->rewriteUsingSymmetry(e2),
00437                              d_commonRules->iffTrue(thm));
00438           setFindLiteral(d_commonRules->iffTrueElim(thm2));
00439         }
00440       }
00441       break;
00442     default:
00443       break;
00444   }
00445 
00446   // Send formula to the appropriate DP
00447   i->assertFact(thm);
00448 
00449   // Equalities and disequalities are also asserted to the theories of
00450   // their types
00451   if (i != i2) i2->assertFact(thm);
00452 }
00453 
00454 
00455 Theorem CVC3::TheoryCore::rewriteCore(const Expr& e)
00456 {
00457   // Normally, if an expr has a find, we don't need to rewrite, just return the find.
00458   // However, if we are in the middle of an update, the find may not yet be updated, so
00459   // we should simplify the result.
00460   if (e.hasFind()) {
00461     Theorem thm = find(e);
00462     if (d_inUpdate && !thm.isRefl()) {
00463       thm = transitivityRule(thm, simplify(thm.getRHS()));
00464     }
00465     return thm;
00466   }
00467 
00468   if (e.isRewriteNormal()) {
00469     IF_DEBUG(
00470       // Check that the RewriteNormal flag is set properly.  Note that we
00471       // assume theory-specific rewrites are idempotent
00472       e.clearRewriteNormal();
00473       Expr rewritten(rewriteCore(e).getRHS());
00474       e.setRewriteNormal(); // Restore the flag
00475       DebugAssert(rewritten == e,
00476       "Expected no change: e = " + e.toString()
00477       +"\n rewriteCore(e) = "+rewritten.toString());
00478     )
00479     return reflexivityRule(e);
00480   }
00481   switch (e.getKind()) {
00482     case EQ:
00483       if (e[0] < e[1])
00484         return rewriteCore(d_commonRules->rewriteUsingSymmetry(e));
00485       else if (e[0] == e[1])
00486         return d_commonRules->rewriteReflexivity(e);
00487       break;
00488     case NOT:
00489       if (e[0].isNot())
00490         return rewriteCore(d_commonRules->rewriteNotNot(e));
00491       break;
00492     default:
00493       break;
00494   }
00495   Theorem thm = theoryOf(e)->rewrite(e);
00496   const Expr& e2 = thm.getRHS();
00497 
00498   // Theory-specific rewrites for equality should ensure that lhs >= rhs, or
00499   // there is danger of an infinite loop.
00500   DebugAssert(!e2.isEq() || e2[0] >= e2[1],
00501         "theory-specific rewrites for equality should ensure lhs >= rhs");
00502   if (e != e2) {
00503     thm = rewriteCore(thm);
00504   }
00505   return thm;
00506 }
00507 
00508 
00509 void TheoryCore::setFindLiteral(const Theorem& thm)
00510 {
00511   const Expr& e = thm.getExpr();
00512   NotifyList* L;
00513   if (e.isNot()) {
00514     const Expr& e0 = e[0];
00515     if (!e0.hasFind()) {
00516       IF_DEBUG(string indentStr(getCM()->scopeLevel(), ' ');)
00517       TRACE("setFindLiteral", indentStr, "SFL: ", e.toString(PRESENTATION_LANG));
00518       Theorem findThm = d_commonRules->notToIff(thm);
00519       e0.setFind(findThm);
00520       if (e0.isRegisteredAtom()) {
00521         DebugAssert(!e.isImpliedLiteral(), "Should be new implied lit");
00522         e.setImpliedLiteral();
00523         d_impliedLiterals.push_back(thm);
00524       }
00525       d_em->invalidateSimpCache();
00526       L = e0.getNotify();
00527       if (L) processNotify(findThm, L);
00528     }
00529     else {
00530       Theorem findThm = find(e0);
00531       if (findThm.getRHS().isTrue()) {
00532         setInconsistent(iffMP(d_commonRules->iffTrueElim(findThm),
00533                               d_commonRules->notToIff(thm)));
00534       }
00535     }
00536   }
00537   else if (!e.hasFind()) {
00538     IF_DEBUG(string indentStr(getCM()->scopeLevel(), ' ');)
00539     TRACE("setFindLiteral", indentStr, "SFL: ", e.toString(PRESENTATION_LANG));
00540     Theorem findThm = d_commonRules->iffTrue(thm);
00541     e.setFind(findThm);
00542     if (e.isRegisteredAtom()) {
00543       DebugAssert(!e.isImpliedLiteral(), "Should be new implied lit");
00544       e.setImpliedLiteral();
00545       d_impliedLiterals.push_back(thm);
00546     }
00547     d_em->invalidateSimpCache();
00548     L = e.getNotify();
00549     if (L) processNotify(findThm, L);
00550   }
00551   else {
00552     Theorem findThm = find(e);
00553     if (findThm.getRHS().isFalse()) {
00554       setInconsistent(iffMP(thm, findThm));
00555     }
00556   }
00557 }
00558 
00559 
00560 Theorem TheoryCore::rewriteLitCore(const Expr& e)
00561 {
00562   switch (e.getKind()) {
00563     case EQ:
00564       if (e[0] == e[1])
00565         return d_commonRules->rewriteReflexivity(e);
00566       else if (e[0] < e[1])
00567         return d_commonRules->rewriteUsingSymmetry(e);
00568       break;
00569     case NOT:
00570       if (e[0].isTrue())
00571         return d_commonRules->rewriteNotTrue(e);
00572       else if (e[0].isFalse())
00573         return d_commonRules->rewriteNotFalse(e);
00574       else if (e[0].isNot())
00575         return d_commonRules->rewriteNotNot(e);
00576       break;
00577     default:
00578       DebugAssert(false,
00579       "TheoryCore::rewriteLitCore("
00580       + e.toString()
00581       + "): Not implemented");
00582       break;
00583   }
00584   return reflexivityRule(e);
00585 }
00586 
00587 
00588 void TheoryCore::enqueueSE(const Theorem& thm)
00589 {
00590   DebugAssert(okToEnqueue(), "enqueueSE()");
00591   d_queueSE.push_back(thm);
00592 }
00593 
00594 
00595 Theorem TheoryCore::getModelValue(const Expr& e)
00596 {
00597   ExprHashMap<Theorem>::iterator i=d_varAssignments.find(e),
00598     iend=d_varAssignments.end();
00599   if(i!=iend) return (*i).second;
00600   else return find(e);
00601 }
00602 
00603 
00604 //! An auxiliary recursive function to process COND expressions into ITE
00605 Expr TheoryCore::processCond(const Expr& e, int i)
00606 {
00607   DebugAssert(i < e.arity()-1, "e = "+e.toString()+", i = "+int2string(i));
00608   if(i == e.arity()-2) {
00609     if(e[i].getKind() == RAW_LIST && e[i].arity() == 2
00610        && e[i+1].getKind() == RAW_LIST  && e[i+1].arity() == 2
00611        && e[i+1][0].getKind() == ID && e[i+1][0][0].getString() == "_ELSE") {
00612       Expr c(parseExpr(e[i][0]));
00613       Expr e1(parseExpr(e[i][1]));
00614       Expr e2(parseExpr(e[i+1][1]));
00615       return c.iteExpr(e1,e2);
00616     }
00617   } else {
00618     if(e[i].getKind() == RAW_LIST && e[i].arity() == 2
00619        && e[i+1].getKind() == RAW_LIST  && e[i+1].arity() == 2) {
00620       Expr c(parseExpr(e[i][0]));
00621       Expr e1(parseExpr(e[i][1]));
00622       Expr e2(processCond(e, i+1));
00623       return c.iteExpr(e1,e2);
00624     }
00625   }
00626   throw ParserException("Parse Error: bad COND expression: "+e.toString());
00627 }
00628 
00629 
00630 bool TheoryCore::isBasicKind(int kind)
00631 {
00632   switch (kind) {
00633     case VARDECLS:
00634     case LETDECLS:
00635     case HELP:
00636     case GET_VALUE:
00637     case GET_ASSIGNMENT:
00638     case DUMP_PROOF:
00639     case DUMP_ASSUMPTIONS:
00640     case DUMP_SIG:
00641     case DUMP_TCC:
00642     case DUMP_TCC_ASSUMPTIONS:
00643     case DUMP_TCC_PROOF:
00644     case DUMP_CLOSURE:
00645     case DUMP_CLOSURE_PROOF:
00646     case WHERE:
00647     case ASSERTIONS:
00648     case ASSUMPTIONS:
00649     case COUNTEREXAMPLE:
00650     case COUNTERMODEL:
00651     case ASSERT:
00652     case PRINT:
00653     case QUERY:
00654     case CHECKSAT:
00655     case CONTINUE:
00656     case RESTART:
00657     case TRACE:
00658     case ECHO:
00659     case UNTRACE:
00660     case VARLIST:
00661     case FORGET:
00662     case GET_TYPE:
00663     case IFF:
00664     case IMPLIES:
00665     case TYPEDEF:
00666     case OPTION:
00667     case AND:
00668     case OR:
00669     case XOR:
00670     case NOT:
00671     case DISTINCT:
00672     case CALL:
00673     case TRANSFORM:
00674     case CHECK_TYPE:
00675     case VARDECL:
00676     case GET_CHILD:
00677     case SUBSTITUTE:
00678     case SEQ:
00679     case DBG:
00680     case PUSH:
00681     case POP:
00682     case POPTO:
00683     case PUSH_SCOPE:
00684     case POP_SCOPE:
00685     case POPTO_SCOPE:
00686     case RESET:
00687     case LETDECL:
00688     case ELSE:
00689     case CONTEXT:
00690       return true;
00691     default:
00692       break;
00693   }
00694   return false;
00695 }
00696 
00697 
00698 TheoryCore::TheoryCore(ContextManager* cm,
00699                        ExprManager* em,
00700                        TheoremManager* tm,
00701                        Translator* translator,
00702                        const CLFlags& flags,
00703                        Statistics& statistics)
00704   : Theory(), d_cm(cm), d_tm(tm), d_flags(flags), d_statistics(statistics),
00705     d_translator(translator),
00706     d_inconsistent(cm->getCurrentContext(), false, 0),
00707     d_incomplete(cm->getCurrentContext()),
00708     d_incThm(cm->getCurrentContext()),
00709     d_terms(cm->getCurrentContext()),
00710     //    d_termTheorems(cm->getCurrentContext()),
00711     d_predicates(cm->getCurrentContext()),
00712     d_solver(NULL),
00713     d_simplifyInPlace(false),
00714     d_currentRecursiveSimplifier(NULL),
00715     d_resourceLimit(0),
00716     d_timeBase(0),
00717     d_timeLimit(0),
00718     d_inCheckSATCore(false), d_inAddFact(false),
00719     d_inRegisterAtom(false), d_inPP(false),
00720     d_notifyObj(this, cm->getCurrentContext()),
00721     d_impliedLiterals(cm->getCurrentContext()),
00722     d_impliedLiteralsIdx(cm->getCurrentContext(), 0, 0),
00723     d_notifyEq(cm->getCurrentContext()),
00724     d_inUpdate(0),
00725     d_coreSatAPI(NULL)
00726 {
00727   d_em = em;
00728   // Since we are in the middle of creating TheoryCore, we set the pointer to
00729   // TheoryCore in the Theory base class ourselves.
00730   d_theoryCore = this;
00731   d_commonRules = tm->getRules();
00732   d_name = "Core";
00733   d_theoryUsed = false;
00734 
00735   d_rules = createProofRules(tm);
00736   d_printer = new PrettyPrinterCore(this);
00737   d_typeComputer = new TypeComputerCore(this);
00738   d_em->registerTypeComputer(d_typeComputer);
00739   d_exprTrans = new ExprTransform(this);
00740 
00741   // Register the pretty-printer
00742   d_em->registerPrettyPrinter(*d_printer);
00743 
00744   // for (int i = 0; i < LAST_KIND; ++i) d_theoryMap[i] = NULL;
00745 
00746   vector<int> kinds;
00747   kinds.push_back(RAW_LIST);
00748   kinds.push_back(BOOLEAN);
00749   kinds.push_back(ANY_TYPE);
00750   kinds.push_back(SUBTYPE);
00751   kinds.push_back(STRING_EXPR);
00752   kinds.push_back(ID);
00753   kinds.push_back(TRUE_EXPR);
00754   kinds.push_back(FALSE_EXPR);
00755   kinds.push_back(UCONST);
00756   kinds.push_back(BOUND_VAR);
00757   kinds.push_back(SKOLEM_VAR);
00758   kinds.push_back(EQ);
00759   kinds.push_back(NEQ);
00760   kinds.push_back(DISTINCT);
00761   kinds.push_back(ECHO);
00762   kinds.push_back(DBG);
00763   kinds.push_back(TRACE);
00764   kinds.push_back(UNTRACE);
00765   kinds.push_back(OPTION);
00766   kinds.push_back(HELP);
00767   kinds.push_back(AND);
00768   kinds.push_back(OR);
00769   kinds.push_back(IFTHEN);
00770   kinds.push_back(IF);
00771   kinds.push_back(ELSE);
00772   kinds.push_back(COND);
00773   kinds.push_back(XOR);
00774   kinds.push_back(NOT);
00775   kinds.push_back(ITE);
00776   kinds.push_back(IFF);
00777   kinds.push_back(IMPLIES);
00778   kinds.push_back(APPLY);
00779   // For printing LET expressions (in DAG printing mode)
00780   kinds.push_back(LET);
00781   kinds.push_back(LETDECLS);
00782   kinds.push_back(LETDECL);
00783   // For printing raw parsed quantifier expressions
00784   kinds.push_back(VARLIST);
00785   kinds.push_back(VARDECLS);
00786   kinds.push_back(VARDECL);
00787 
00788   // Type declarations and definitions
00789   kinds.push_back(TYPE);
00790   // For printing type declarations (or definitions)
00791   kinds.push_back(CONST);
00792 
00793   kinds.push_back(TYPEDEF);
00794   kinds.push_back(DEFUN);
00795   // Printing proofs
00796   kinds.push_back(PF_APPLY);
00797   kinds.push_back(PF_HOLE);
00798   // Register commands for pretty-printing.  Currently, only ASSERT
00799   // needs to be printed.
00800   kinds.push_back(ASSERT);
00801   kinds.push_back(QUERY);
00802   kinds.push_back(PRINT);
00803 
00804   kinds.push_back(GET_VALUE);
00805   kinds.push_back(GET_ASSIGNMENT);
00806   kinds.push_back(DUMP_PROOF);
00807   kinds.push_back(DUMP_ASSUMPTIONS);
00808   kinds.push_back(DUMP_SIG);
00809   kinds.push_back(DUMP_TCC);
00810   kinds.push_back(DUMP_TCC_ASSUMPTIONS);
00811   kinds.push_back(DUMP_TCC_PROOF);
00812   kinds.push_back(DUMP_CLOSURE);
00813   kinds.push_back(DUMP_CLOSURE_PROOF);
00814   kinds.push_back(TRANSFORM);
00815   kinds.push_back(CALL);
00816   kinds.push_back(WHERE);
00817   kinds.push_back(ASSERTIONS);
00818   kinds.push_back(ASSUMPTIONS);
00819   kinds.push_back(COUNTEREXAMPLE);
00820   kinds.push_back(COUNTERMODEL);
00821   kinds.push_back(PUSH);
00822   kinds.push_back(POP);
00823   kinds.push_back(POPTO);
00824   kinds.push_back(PUSH_SCOPE);
00825   kinds.push_back(POP_SCOPE);
00826   kinds.push_back(POPTO_SCOPE);
00827   kinds.push_back(RESET);
00828   kinds.push_back(CONTEXT);
00829   kinds.push_back(FORGET);
00830   kinds.push_back(GET_TYPE);
00831   kinds.push_back(CHECK_TYPE);
00832   kinds.push_back(GET_CHILD);
00833   kinds.push_back(SUBSTITUTE);
00834   kinds.push_back(SEQ);
00835   kinds.push_back(ARITH_VAR_ORDER);
00836   kinds.push_back(ANNOTATION);
00837   kinds.push_back(THEOREM_KIND);
00838 
00839   kinds.push_back(AND_R);
00840   kinds.push_back(IFF_R);
00841   kinds.push_back(ITE_R);
00842 
00843   registerTheory(this, kinds);
00844 }
00845 
00846 
00847 TheoryCore::~TheoryCore()
00848 {
00849   delete d_exprTrans;
00850   delete d_rules;
00851   delete d_typeComputer;
00852   d_em->unregisterPrettyPrinter();
00853   delete d_printer;
00854 }
00855 
00856 
00857 Theorem TheoryCore::callTheoryPreprocess(const Expr& e)
00858 {
00859   Theorem thm = reflexivityRule(e);
00860   for(unsigned i=1; i<d_theories.size(); ++i) {
00861     thm = transitivityRule(thm, d_theories[i]->theoryPreprocess(thm.getRHS()));
00862   }
00863   processFactQueue(LOW);
00864   return thm;
00865 }
00866 
00867 
00868 Theorem TheoryCore::getTheoremForTerm(const Expr& e){
00869 
00870 // <<<<<<< theory_core_sat.cpp
00871 //   //  DebugAssert(e.hasFind(), "getTheoremForTerm called on term without find");
00872 //   CDMap<Expr, Theorem>::iterator i = d_termTheorems.find(e);
00873 //   if( i == d_termTheorems.end()){
00874 //    TRACE("quantlevel", "getTheoremForTerm: no theorem found: ", e , "");
00875 //    Theorem nul;
00876 //    return nul;
00877 //   }
00878 //   //  DebugAssert(i != d_termTheorems.end(), "getTheoremForTerm: no theorem found");
00879 // =======
00880 //  DebugAssert(e.hasFind() || e.isStoredPredicate(), "getTheoremForTerm called on invalid term");
00881 
00882   hash_map<Expr, Theorem>::iterator i = d_termTheorems.find(e);
00883   // yeting, I think we should use CDMap here, but a static map works better.
00884   //  CDMap<Expr, Theorem>::iterator i = d_termTheorems.find(e);
00885 
00886   //  DebugAssert(i != d_termTheorems.end(), "getTheoremForTerm: no theorem found");
00887 
00888   if(i != d_termTheorems.end()){
00889     return (*i).second;
00890   }
00891   else{
00892     TRACE("quantlevel", "getTheoremForTerm: no theorem found: ", e , "");
00893     Theorem x;
00894     return x;
00895   }
00896 }
00897 
00898 #ifdef _CVC3_DEBUG_MODE
00899 int TheoryCore::getCurQuantLevel(){
00900   return theoryOf(FORALL)->help(1);
00901 }
00902 #endif
00903 
00904 unsigned TheoryCore::getQuantLevelForTerm(const Expr& e)
00905 {
00906 
00907 
00908 /*
00909   if (!e.hasFind() && !e.isStoredPredicate()) {
00910     TRACE("quantlevel", "get 0 ", e , "");
00911     return 0;
00912   }
00913 */
00914   TRACE("quantlevel", "trying get level for (" + e.toString() + ") with index ", "", e.getIndex());
00915   Theorem thm = getTheoremForTerm(e);
00916   if (thm.isNull()) {
00917     if(e.isNot()){
00918       thm = getTheoremForTerm(e[0]);
00919     }
00920   }
00921 
00922   if(thm.isNull()){
00923     if (e.inUserAssumption())   {
00924       return 0 ;
00925     }
00926     else{
00927       TRACE("quantlevel", "expr get null :", e.getIndex(), "" );
00928       if( ! (e.isNot() || e.isIff())){
00929   TRACE("quantlevel", "cannot find expr: " , e, "");
00930       }
00931       return 0;
00932     }
00933   }
00934 
00935   TRACE("quantlevel", "expr get level:", thm.getQuantLevel(), "");
00936 
00937   /*
00938   if(thm.getQuantLevel() != thm.getQuantLevelDebug()){
00939     cout << "theorem: " << thm.getExpr().toString() <<endl;
00940     cout << "quant level : " << thm.getQuantLevel()<<endl;
00941     cout << "debug quant level : " << thm.getQuantLevelDebug() <<endl;
00942     cout << "the proof is " << thm.getProof() << endl;
00943   }
00944   */
00945 
00946   return thm.getQuantLevel();
00947   /*
00948   unsigned ql = thm.getQuantLevel();
00949   unsigned qld = thm.getQuantLevelDebug();
00950   return (ql > qld ? ql : qld);
00951   */
00952 }
00953 
00954 
00955 ///////////////////////////////////////////////////////////////////////////////
00956 // Theory interface implementaion                                            //
00957 ///////////////////////////////////////////////////////////////////////////////
00958 
00959 
00960 void TheoryCore::assertFact(const Theorem& e)
00961 {
00962   DebugAssert(e.getExpr().unnegate().getKind() == SKOLEM_VAR ||
00963               e.getExpr().unnegate().getKind() == UCONST,
00964               "TheoryCore::assertFact("+e.toString()+")");
00965 }
00966 
00967 
00968 Theorem TheoryCore::rewrite(const Expr& e)
00969 {
00970   Theorem thm;
00971   switch (e.getKind()) {
00972     case TRUE_EXPR:
00973     case FALSE_EXPR:
00974     case UCONST:
00975     case BOUND_VAR:
00976     case SKOLEM_VAR:
00977       thm = reflexivityRule(e);
00978       break; // do not rewrite
00979     case LETDECL:
00980       // Replace LETDECL with its definition.  The
00981       // typechecker makes sure it's type-safe to do so.
00982       thm = d_rules->rewriteLetDecl(e);
00983       break;
00984     case APPLY:
00985       //TODO: this is a bit of a hack
00986       if (e.getOpKind() == LAMBDA)
00987         thm = theoryOf(LAMBDA)->rewrite(e);
00988       else thm = reflexivityRule(e);
00989       break;
00990     case EQ:
00991     case NOT:
00992       thm = rewriteLitCore(e);
00993       break;
00994     case DISTINCT: {
00995       Theorem thm1 = d_rules->rewriteDistinct(e);
00996       thm = transitivityRule(thm1, simplify(thm1.getRHS()));
00997       break;
00998     }
00999     case IMPLIES: {
01000       thm = d_rules->rewriteImplies(e);
01001       const Expr& rhs = thm.getRHS();
01002       // rhs = OR(!e1, e2).  Rewrite !e1, then top-level OR().
01003       DebugAssert(rhs.isOr() && rhs.arity() == 2,
01004       "TheoryCore::rewrite[IMPLIES]: rhs = "+rhs.toString());
01005       Theorem rw = rewriteCore(rhs[0]);
01006       if (!rw.isRefl()) {
01007   vector<unsigned> changed;
01008   vector<Theorem> thms;
01009   changed.push_back(0);
01010   thms.push_back(rw);
01011   rw = substitutivityRule(rhs, changed, thms);
01012   // Simplify to the find pointer of the result
01013   rw = transitivityRule(rw, find(rw.getRHS()));
01014   // Now rw = Theorem(rhs = rhs')
01015   rw = transitivityRule(rw, rewrite(rw.getRHS()));
01016       } else
01017   rw = rewrite(rhs);
01018       thm = transitivityRule(thm, rw);
01019       //       thm = transitivityRule(thm, simplify(thm.getRHS()));
01020       break;
01021     }
01022     case XOR: {
01023       thm = d_commonRules->xorToIff(e);
01024       thm = transitivityRule(thm, simplify(thm.getRHS()));
01025       break;
01026     }
01027     case IFF: {
01028       thm = d_commonRules->rewriteIff(e);
01029       Expr e1 = thm.getRHS();
01030       // The only time we need to rewrite the result (e1) is when
01031       // e==(FALSE<=>e[1]) or (e[1]<=>FALSE), so e1==!e[1].
01032       if (e != e1 && e1.isNot())
01033   thm = transitivityRule(thm, rewriteCore(e1));
01034       break;
01035     }
01036     case ITE:
01037       thm = rewriteIte(e);
01038       if (!thm.isRefl()) break;
01039       else if (getFlags()["un-ite-ify"].getBool()) {
01040   // undo the rewriting of Boolean connectives to ITEs.
01041   // helpful for examples converted from SVC.
01042   // must rewrite again because we might create expressions
01043   // that can be further rewritten, and we must normalize.
01044   if (e[1].isFalse() && e[2].isTrue())
01045     thm = rewriteCore(d_rules->rewriteIteToNot(e));
01046   else if (e[1].isTrue())
01047     thm = rewriteCore(d_rules->rewriteIteToOr(e));
01048   else if (e[2].isFalse())
01049     thm = rewriteCore(d_rules->rewriteIteToAnd(e));
01050   else if (e[2].isTrue())
01051     thm = rewriteCore(d_rules->rewriteIteToImp(e));
01052   else if (e[1] == e[2].negate())
01053     thm = rewriteCore(d_rules->rewriteIteToIff(e));
01054   else thm = reflexivityRule(e);
01055       }
01056       else if(getFlags()["ite-cond-simp"].getBool()) {
01057   thm = d_rules->rewriteIteCond(e);
01058   if (!thm.isRefl()) {
01059     thm = transitivityRule(thm, simplify(thm.getRHS()));
01060         }
01061       }
01062       else thm = reflexivityRule(e);
01063       break;
01064     case AND: {
01065       thm = rewriteAnd(e);
01066       Expr ee = thm.getRHS();
01067       break;
01068     }
01069     case OR: {
01070       thm = rewriteOr(e);
01071       Expr ee = thm.getRHS();
01072       break;
01073     }
01074       // Quantifiers
01075     case FORALL:
01076     case EXISTS:
01077       thm = d_commonRules->reflexivityRule(e);
01078       break;
01079       // don't need to rewrite these
01080     case AND_R:
01081     case IFF_R:
01082     case ITE_R:
01083       thm = reflexivityRule(e);
01084       break;
01085     default:
01086       DebugAssert(false,
01087       "TheoryCore::rewrite("
01088       + e.toString() + " : " + e.getType().toString()
01089       + "): Not implemented");
01090       break;
01091   }
01092 
01093   DebugAssert(thm.getLHS() == e, "TheoryCore::rewrite("+e.toString()
01094         +") = "+thm.getExpr().toString());
01095 
01096   Expr rhs = thm.getRHS();
01097   // Advanced Boolean rewrites
01098   switch(rhs.getKind()) {
01099   case AND:
01100     if(getFlags()["simp-and"].getBool()) {
01101       Theorem tmp(reflexivityRule(rhs));
01102       for(int i=0, iend=rhs.arity(); i<iend; ++i) {
01103   tmp = transitivityRule
01104     (tmp, d_rules->rewriteAndSubterms(tmp.getRHS(), i));
01105       }
01106       if(tmp.getRHS() != rhs) { // Something changed: simplify recursively
01107   thm = transitivityRule(thm, tmp);
01108   thm = transitivityRule(thm, simplify(thm.getRHS()));
01109   rhs = thm.getRHS();
01110       }
01111     }
01112     break;
01113   case OR:
01114     if(getFlags()["simp-or"].getBool()) {
01115       Theorem tmp(reflexivityRule(rhs));
01116       for(int i=0, iend=rhs.arity(); i<iend; ++i) {
01117   tmp = transitivityRule
01118     (tmp, d_rules->rewriteOrSubterms(tmp.getRHS(), i));
01119       }
01120       if(tmp.getRHS() != rhs) { // Something changed: simplify recursively
01121   thm = transitivityRule(thm, tmp);
01122   thm = transitivityRule(thm, simplify(thm.getRHS()));
01123   rhs = thm.getRHS();
01124       }
01125     }
01126     break;
01127   default:
01128     break;
01129   }
01130   if (theoryOf(rhs) == this) {
01131     // Core rewrites are idempotent (FIXME: are they, still?)
01132     rhs.setRewriteNormal();
01133   }
01134   return thm;
01135 }
01136 
01137 
01138 /*! We use the update method of theory core to track registered atomic
01139  * formulas.  Updates are recorded and then processed by calling processUpdates
01140  * once all equalities have been processed. */
01141 void TheoryCore::update(const Theorem& e, const Expr& d)
01142 {
01143   // Disequalities
01144   if (d.isNot()) {
01145     const Expr& eq = d[0];
01146     DebugAssert(eq.isEq(), "Expected equality");
01147     Theorem thm1(find(eq[0]));
01148     Theorem thm2(find(eq[1]));
01149     const Expr& newlhs = thm1.getRHS();
01150     const Expr& newrhs = thm2.getRHS();
01151     if (newlhs == newrhs) {
01152       Theorem thm = find(eq);
01153       DebugAssert(thm.getRHS().isFalse(), "Expected disequality");
01154       Theorem leftEqRight = transitivityRule(thm1, symmetryRule(thm2));
01155       setInconsistent(iffMP(leftEqRight, thm));
01156     }
01157     else {
01158       e.getRHS().addToNotify(this, d);
01159       // propagate new disequality
01160       Theorem thm = d_commonRules->substitutivityRule(eq, thm1, thm2);
01161       if (newlhs < newrhs) {
01162         thm = transitivityRule(thm, d_commonRules->rewriteUsingSymmetry(thm.getRHS()));
01163       }
01164       const Expr& newEq = thm.getRHS();
01165       if (newEq.hasFind()) {
01166         Theorem thm2 = find(newEq);
01167         if (thm2.getRHS().isTrue()) {
01168           thm2 = transitivityRule(thm, thm2);
01169           thm = find(eq);
01170           DebugAssert(thm.getRHS().isFalse(), "Expected disequality");
01171           thm = transitivityRule(symmetryRule(thm), thm2);
01172           setInconsistent(d_commonRules->iffTrueElim(thm));
01173         }
01174         // else if thm2.getRHS().isFalse(), nothing to do
01175       }
01176       else {
01177         Theorem thm2 = find(eq);
01178         DebugAssert(thm2.getRHS().isFalse(), "Expected disequality");
01179         thm2 = transitivityRule(symmetryRule(thm),thm2);
01180         setFindLiteral(d_commonRules->iffFalseElim(thm2));
01181       }
01182     }
01183   }
01184   // Registered atoms
01185   else {
01186     DebugAssert(d.isRegisteredAtom(), "Expected registered atom");
01187     if (!d.isImpliedLiteral()) {
01188       d_update_thms.push_back(e);
01189       d_update_data.push_back(d);
01190     }
01191   }
01192 }
01193 
01194 
01195 void TheoryCore::checkEquation(const Theorem& thm)
01196 {
01197   Expr e2 = thm.getExpr();
01198   DebugAssert(e2.isEq(), "Expected equation");
01199   Expr solved;
01200   if (d_solver) {
01201     solved = d_solver->solve(thm).getExpr();
01202     DebugAssert(solved == e2, "e2 = "+e2.toString()
01203                 +"\nsolved = "+solved.toString());
01204   }
01205   Theory* i = theoryOf(e2);
01206   if (d_solver != i) {
01207     solved = i->solve(thm).getExpr();
01208     DebugAssert(solved == e2, "e2 = "+e2.toString()
01209                 +"\nsolved = "+solved.toString());
01210   }
01211   Theory* j = theoryOf(e2[0].getType());
01212   if (d_solver != j && i != j) {
01213     solved = j->solve(thm).getExpr();
01214     DebugAssert(solved == e2, "e2 = "+e2.toString()
01215                 +"\nsolved = "+solved.toString());
01216   }
01217 }
01218 
01219 
01220 void TheoryCore::checkSolved(const Theorem& thm)
01221 {
01222   Expr e2 = thm.getExpr();
01223   if (e2.isAnd()) {
01224     for (int index = 0; index < e2.arity(); ++index) {
01225       checkEquation(d_commonRules->andElim(thm, index));
01226     }
01227   }
01228   else if (!e2.isBoolConst()) checkEquation(thm);
01229 }
01230 
01231 
01232 /*****************************************************************************/
01233 /*!
01234  * Function: TheoryCore::solve
01235  *
01236  * Author: Clark Barrett
01237  *
01238  * Created: Wed Feb 26 16:17:54 2003
01239  *
01240  * This is a generalization of what's in my thesis.  The goal is to rewrite e
01241  * into an equisatisfiable conjunction of equations such that the left-hand
01242  * side of each equation is a variable which does not appear as an i-leaf of
01243  * the rhs, where i is the theory of the primary solver.  Any solution which
01244  * satisfies this is fine.  "Solvers" from other theories can do whatever they
01245  * want as long as we eventually reach this form.
01246  */
01247 /*****************************************************************************/
01248 Theorem TheoryCore::solve(const Theorem& eThm)
01249 {
01250   const Expr& e = eThm.getExpr();
01251   Theorem thm;
01252   Expr e2;
01253 
01254   DebugAssert(eThm.isRewrite() && eThm.getLHS().isTerm(), "Expected equation");
01255 
01256   // Invoke the primary solver
01257   if (d_solver) {
01258     thm = d_solver->solve(eThm);
01259     e2 = thm.getExpr();
01260     if (e2.isBoolConst() || e2.isAnd()) {
01261       // We expect a conjunction of equations, each of which is terminally solved
01262       IF_DEBUG(checkSolved(thm));
01263       return thm;
01264     }
01265   }
01266   else {
01267     thm = eThm;
01268     e2 = e;
01269   }
01270 
01271   // Invoke solver based on owner of equation
01272   DebugAssert(e2.isEq(), "Expected equation");
01273   Theory* i = theoryOf(e2);
01274   if (d_solver != i) thm = i->solve(thm);
01275   e2 = thm.getExpr();
01276   if (e2.isBoolConst() || e2.isAnd()) {
01277     // We expect a conjunction of equations, each of which is solved
01278     IF_DEBUG(checkSolved(thm));
01279     return thm;
01280   }
01281 
01282   // Invoke solver based on type of terms in equation
01283   DebugAssert(e2.isEq(), "Expected equation");
01284   Theory* j = theoryOf(getBaseType(e2[0]));
01285   if (d_solver != j && i != j) thm = j->solve(thm);
01286 
01287   IF_DEBUG(checkSolved(thm));
01288   return thm;
01289 }
01290 
01291 
01292 Theorem TheoryCore::simplifyOp(const Expr& e)
01293 {
01294   int kind(e.getKind());
01295 
01296   switch(kind) {
01297   case EQ:
01298   case IFF:
01299     if(e[0]==e[1]) {
01300       IF_DEBUG(debugger.counter("simplified x=x")++;)
01301       return d_commonRules->iffTrue(reflexivityRule(e[0]));
01302     }
01303     return Theory::simplifyOp(e);
01304   case AND:
01305   case OR: {
01306     // Stop when a child has this kind
01307     int endKind = (kind==AND)? FALSE_EXPR : TRUE_EXPR;
01308     int ar = e.arity();
01309     // Optimization: before simplifying anything recursively, check if
01310     // any kid is already TRUE or FALSE, and just return at that point
01311     int l(0);
01312     for(; l<ar && e[l].getKind() != endKind; ++l);
01313     if(l < ar) { // Found TRUE or FALSE: e simplifies to a const
01314       IF_DEBUG(debugger.counter("simplified AND/OR topdown")++;)
01315       if(kind==AND)
01316   return rewriteAnd(e);
01317       else
01318   return rewriteOr(e);
01319     }
01320     vector<Theorem> newChildrenThm;
01321     vector<unsigned> changed;
01322     for(int k = 0; k < ar; ++k) {
01323       // Recursively simplify the kids
01324       Theorem thm = simplify(e[k]);
01325       if (!thm.isRefl()) {
01326   if (thm.getRHS().getKind() == endKind) {
01327     newChildrenThm.clear();
01328     changed.clear();
01329     newChildrenThm.push_back(thm);
01330     changed.push_back(k);
01331     thm = substitutivityRule(e, changed, newChildrenThm);
01332     // Simplify to TRUE or FALSE
01333     if(kind==AND)
01334       thm = transitivityRule(thm, rewriteAnd(thm.getRHS()));
01335     else
01336       thm = transitivityRule(thm, rewriteOr(thm.getRHS()));
01337     IF_DEBUG(debugger.counter("simplified AND/OR: skipped kids")
01338        += ar-k-1;)
01339     return thm;
01340   } else { // Child simplified to something else
01341     newChildrenThm.push_back(thm);
01342     changed.push_back(k);
01343   }
01344       }
01345     }
01346     if(changed.size() > 0)
01347       return substitutivityRule(e, changed, newChildrenThm);
01348     break;
01349   }
01350   case ITE: {
01351     DebugAssert(e.arity()==3, "Bad ITE in TheoryCore::simplify(e="
01352     +e.toString()+")");
01353     // Optimization: check if the two branches are the same, so we
01354     // don't have to simplify the condition
01355     if(e[1]==e[2]) {
01356       IF_DEBUG(debugger.counter("simplified ITE(c,e,e)")++;)
01357       Theorem res = d_commonRules->rewriteIteSame(e);
01358       return transitivityRule(res, simplify(res.getRHS()));
01359     }
01360 
01361     // First, simplify the conditional
01362     vector<Theorem> newChildrenThm;
01363     vector<unsigned> changed;
01364     Theorem thm = simplify(e[0]);
01365     if (!thm.isRefl()) {
01366       newChildrenThm.push_back(thm);
01367       changed.push_back(0);
01368     }
01369     Expr cond = thm.getRHS();
01370 
01371     for(int k=1; k<=2; ++k) {
01372       // If condition value is known, only the appropriate branch
01373       // needs to be simplified
01374       if (cond.isBoolConst()) {
01375         if((k==1 && cond.isFalse()) || (k==2 && cond.isTrue())) {
01376           IF_DEBUG(debugger.counter("simplified ITE: skiped one branch")++;)
01377             continue;
01378         }
01379       }
01380       thm = simplify(e[k]);
01381       if (!thm.isRefl()) {
01382   newChildrenThm.push_back(thm);
01383   changed.push_back(k);
01384       }
01385     }
01386     if(changed.size() > 0)
01387       return substitutivityRule(e, changed, newChildrenThm);
01388     break;
01389   }
01390   case NOT: {
01391     Theorem res = simplify(e[0]);
01392     if (!res.isRefl()) {
01393       return d_commonRules->substitutivityRule(e, res);
01394     }
01395     break;
01396   }
01397   case IMPLIES: {
01398     Theorem res = d_rules->rewriteImplies(e);
01399     return transitivityRule(res, simplifyOp(res.getRHS()));
01400   }
01401   default:
01402     return Theory::simplifyOp(e);
01403   }
01404   return reflexivityRule(e);
01405 }
01406 
01407 
01408 void TheoryCore::checkType(const Expr& e)
01409 {
01410   switch (e.getKind()) {
01411     case BOOLEAN:
01412       if (e.arity() > 0) {
01413         throw Exception("Ill-formed Boolean type:\n\n"+e.toString());
01414       }
01415       break;
01416     case SUBTYPE: {
01417         if (e.arity() != 1)
01418           throw Exception("Ill-formed SUBTYPE expression:\n\n"+e.toString());
01419         Type t = e[0].getType();
01420         if (!t.isFunction())
01421           throw Exception
01422             ("Non-function argument to SUBTYPE:\n\n"
01423              +e.toString());
01424         if (!t[1].isBool())
01425           throw Exception
01426             ("Non-predicate argument to SUBTYPE:\n\n"
01427              +e.toString());
01428       }
01429       break;
01430     case ANY_TYPE: {
01431       if (e.arity() != 0) {
01432         throw Exception("Expected no children: "+e.toString());
01433       }
01434       break;
01435     }
01436     default:
01437       FatalAssert(false, "Unexpected kind in TheoryCore::checkType"
01438                   +getEM()->getKindName(e.getKind()));
01439   }
01440 }
01441 
01442 
01443 Cardinality TheoryCore::finiteTypeInfo(Expr& e, Unsigned& n,
01444                                        bool enumerate, bool computeSize)
01445 {
01446   Cardinality card = CARD_INFINITE;
01447   switch (e.getKind()) {
01448     case BOOLEAN:
01449       card = CARD_FINITE;
01450       if (enumerate) {
01451         e = (n == 0) ? falseExpr() : (n == 1) ? trueExpr() : Expr();
01452       }
01453       if (computeSize) {
01454         n = 2;
01455       }
01456       break;
01457     case SUBTYPE:
01458       card = CARD_UNKNOWN;
01459       break;
01460     case ANY_TYPE:
01461       card = CARD_UNKNOWN;
01462       break;
01463     default:
01464       FatalAssert(false, "Unexpected kind in TheoryCore::finiteTypeInfo"
01465                   +getEM()->getKindName(e.getKind()));
01466   }
01467   return card;
01468 }
01469 
01470 
01471 void TheoryCore::computeType(const Expr& e)
01472 {
01473   switch (e.getKind()) {
01474     case ITE: {
01475       Type t1(getBaseType(e[1])), t2(getBaseType(e[2]));
01476       if (e[0].getType() != boolType())
01477   throw TypecheckException
01478     ("The conditional in IF-THEN-ELSE must be BOOLEAN, but is:\n\n"
01479      +e[0].getType().toString()
01480      +"\n\nIn the expression:\n\n  "
01481      +e.toString());
01482       if(t1 != t2) {
01483   throw TypecheckException
01484     ("The types of the IF-THEN-ELSE branches do not match.\n"
01485      "THEN branch has the type:\n\n  "
01486      +e[1].getType().toString()
01487      +"\n\nELSE branch has the type:\n\n  "
01488      +e[2].getType().toString()
01489      +"\n\nIn expression:\n\n  "+e.toString());
01490       }
01491       Type res(e[1].getType());
01492       // If the precise types match in both branches, use it as the
01493       // result type.
01494       if(res == e[2].getType()) {
01495   e.setType(res);
01496       }
01497       else
01498   // Note: setting the base type, since e[1] and e[2] have
01499   // different exact types, and the base type is a conservative
01500   // approximation we can easily compute.
01501   e.setType(t1);
01502     }
01503       break;
01504     case EQ: {
01505       Type t0(getBaseType(e[0])), t1(getBaseType(e[1]));
01506       if (t0.isBool() || t1.isBool()) {
01507   throw TypecheckException
01508     ("Cannot use EQ ('=') for BOOLEAN type; use IFF ('<=>') instead.\n"
01509      "Error in the following expression:\n"+e.toString());
01510       }
01511       if (t0 != t1) {
01512   throw TypecheckException
01513     ("Type mismatch in equality:\n\n LHS type:\n"+t0.toString()
01514      +"\n\n RHS type: \n"+t1.toString()
01515      +"\n\n in expression: \n"+e.toString());
01516       }
01517       e.setType(boolType());
01518       break;
01519     }
01520     case DISTINCT: {
01521       Type t0(getBaseType(e[0]));
01522       for (int i = 1; i < e.arity(); ++i) {
01523         if (t0 != getBaseType(e[i])) {
01524           throw TypecheckException
01525             ("Type mismatch in distinct:\n\n types:\n"+t0.toString()
01526              +"\n\n and type: \n"+getBaseType(e[i]).toString()
01527              +"\n\n in expression: \n"+e.toString());
01528         }
01529       }
01530       e.setType(boolType());
01531       break;
01532     }
01533     case NOT:
01534     case AND:
01535     case OR:
01536     case XOR:
01537     case IFF:
01538     case IMPLIES:
01539 
01540     case AND_R:
01541     case IFF_R:
01542     case ITE_R:
01543 
01544       for (int k = 0; k < e.arity(); ++k) {
01545   if (e[k].getType() != boolType()) {
01546     throw TypecheckException(e.toString());
01547   }
01548       }
01549       if((e.getKind() == NOT && e.arity() != 1) ||
01550          (e.getKind() == IFF && e.arity() != 2) ||
01551          (e.getKind() == IMPLIES && e.arity() != 2)) {
01552   throw TypecheckException("Wrong arity ("+int2string(e.arity())+") for operator: "+e.toString());
01553       }
01554       e.setType(boolType());
01555       break;
01556     case LETDECL: {
01557       Type varTp(getBaseType(e[0]));
01558       Type valTp(getBaseType(e[1]));
01559       if(valTp != varTp) {
01560   throw TypecheckException("Type mismatch for "+e[0].toString()+":"
01561          +"\n  declared: "
01562          + varTp.toString()
01563          +"\n  derived: "+ valTp.toString());
01564       }
01565       e.setType(e[0].getType());
01566     }
01567       break;
01568     case APPLY:
01569     {
01570       DebugAssert(e.isApply(), "Should be application");
01571       DebugAssert(e.arity() > 0, "Expected non-zero arity in APPLY");
01572       Expr funExpr = e.getOpExpr();
01573       Type funType = funExpr.getType();
01574 
01575       if(!funType.isFunction()) {
01576   throw TypecheckException
01577     ("Expected function type for:\n\n"
01578      + funExpr.toString() + "\n\n but got this: "
01579      +funType.getExpr().toString()
01580      +"\n\n in function application:\n\n"+e.toString());
01581       }
01582 
01583       if(funType.arity() != e.arity()+1)
01584   throw TypecheckException("Type mismatch for expression:\n\n   "
01585          + e.toString()
01586          + "\n\nFunction \""+funExpr.toString()
01587          +"\" expects "+int2string(funType.arity()-1)
01588          +" argument"
01589          +string((funType.arity()==2)? "" : "s")
01590          +", but received "
01591          +int2string(e.arity())+".");
01592 
01593       for (int k = 0; k < e.arity(); ++k) {
01594   Type valType(getBaseType(e[k]));
01595   if (funType[k] != Type::anyType(d_em) && !(valType == getBaseType(funType[k]) || valType == Type::anyType(d_em)) ) {
01596     throw TypecheckException("Type mismatch for expression:\n\n   "
01597            + e[k].toString()
01598            + "\n\nhas the following type:\n\n  "
01599            + e[k].getType().toString()
01600            + "\n\nbut the expected type is:\n\n  "
01601            + funType[k].getExpr().toString()
01602            + "\n\nin function application:\n\n  "
01603            + e.toString());
01604   }
01605       }
01606       e.setType(funType[funType.arity()-1]);
01607       break;
01608     }
01609     case RAW_LIST:
01610       throw TypecheckException("computeType called on RAW_LIST");
01611       break;
01612     default:
01613       DebugAssert(false,"TheoryCore::computeType(" + e.toString()
01614       + "):\nNot implemented");
01615       break;
01616   }
01617 }
01618 
01619 
01620 Type TheoryCore::computeBaseType(const Type& tp)
01621 {
01622   const Expr& e = tp.getExpr();
01623   Type res;
01624   switch(e.getKind()) {
01625   case SUBTYPE: {
01626     DebugAssert(e.arity() == 1, "Expr::computeBaseType(): "+e.toString());
01627     Type lambdaTp = e[0].getType();
01628     Type lambdaBaseTp = getBaseType(lambdaTp);
01629     DebugAssert(lambdaBaseTp.isFunction(),
01630     "Expr::computeBaseType(): lambdaBaseTp = "
01631     +lambdaBaseTp.toString()+" in e = "+e.toString());
01632     res = lambdaBaseTp[0];
01633     break;
01634   }
01635   case BOOLEAN:
01636   case ANY_TYPE:
01637     res = tp;
01638     break;
01639   case TYPEDEF: // Compute the base type of the definition
01640     res = getBaseType(Type(e[1]));
01641     break;
01642   default:
01643     DebugAssert(false, "TheoryCore::computeBaseType("+tp.toString()+")");
01644     res = tp;
01645   }
01646   return res;
01647 }
01648 
01649 
01650 Expr TheoryCore::computeTCC(const Expr& e)
01651 {
01652   Expr res;
01653   switch (e.getKind()) {
01654   case NOT:
01655     res = getTCC(e[0]);
01656     break;
01657   case AND: {
01658     // ( (tcc(e1) & !e1) \/ ... \/ (tcc(en) & !en) \/ (tcc(e1)&...&tcc(en))
01659     vector<Expr> tccs;
01660     for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
01661       tccs.push_back(getTCC(*i));
01662     vector<Expr> pairs;
01663     pairs.push_back(rewriteAnd(andExpr(tccs)).getRHS());
01664     for(size_t i=0, iend=tccs.size(); i<iend; ++i)
01665       pairs.push_back(rewriteAnd(tccs[i].andExpr(e[i].negate())).getRHS());
01666     res = rewriteOr(orExpr(pairs)).getRHS();
01667     break;
01668   }
01669   case OR: {
01670     // ( (tcc(e1) & e1) \/ ... \/ (tcc(en) & en) \/ (tcc(e1)&...&tcc(en))
01671     vector<Expr> tccs;
01672     for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
01673       tccs.push_back(getTCC(*i));
01674     vector<Expr> pairs;
01675     pairs.push_back(rewriteAnd(andExpr(tccs)).getRHS());
01676     for(size_t i=0, iend=tccs.size(); i<iend; ++i)
01677       pairs.push_back(rewriteAnd(tccs[i].andExpr(e[i])).getRHS());
01678     res = rewriteOr(orExpr(pairs)).getRHS();
01679     break;
01680   }
01681   case ITE: {
01682     Expr tcc1(getTCC(e[1])), tcc2(getTCC(e[2]));
01683     // Optimize: if TCCs on both branches are the same, skip the ITE
01684     Expr tccITE((tcc1 == tcc2)? tcc1 : e[0].iteExpr(tcc1, tcc2));
01685     res = rewriteAnd(getTCC(e[0]).andExpr(tccITE)).getRHS();
01686     break;
01687   }
01688   case IMPLIES:
01689     res = getTCC(e[0].negate().orExpr(e[1]));
01690     break;
01691   case APPLY: {
01692     Theory* i = theoryOf(e);
01693     if (i != this) return i->computeTCC(e);
01694     // fall through
01695   }
01696   default: // All the other operators are strict
01697     res = Theory::computeTCC(e);
01698     break;
01699   }
01700   return res;
01701 }
01702 
01703 
01704 Expr TheoryCore::computeTypePred(const Type& t, const Expr& e)
01705 {
01706   Expr tExpr = t.getExpr();
01707   switch(tExpr.getKind()) {
01708     case SUBTYPE: {
01709       Expr pred = tExpr[0];
01710       const Type& argTp = pred.lookupType()[0];
01711       return Expr(pred.mkOp(), e).andExpr(getTypePred(argTp, e));
01712     }
01713     case APPLY: {
01714       Theory* i = theoryOf(e);
01715       if (i != this) return i->computeTypePred(t, e);
01716       // fall through
01717     }
01718     default:
01719       return e.getEM()->trueExpr();
01720   }
01721 }
01722 
01723 
01724 Expr TheoryCore::parseExprOp(const Expr& e)
01725 {
01726   // If the expression is not a list, it must have been already
01727   // parsed, so just return it as is.
01728   switch(e.getKind()) {
01729   case ID: {
01730     int kind = getEM()->getKind(e[0].getString());
01731     switch(kind) {
01732     case NULL_KIND: return e; // nothing to do
01733     case TRUE_EXPR:
01734     case FALSE_EXPR:
01735     case TYPE:
01736     case BOOLEAN: return getEM()->newLeafExpr(kind);
01737     default:
01738       DebugAssert(false, "Bad use of bare keyword: "+e.toString());
01739       return e;
01740     }
01741   }
01742   case RAW_LIST: break; // break out of switch, do the work
01743   default:
01744     return e;
01745   }
01746   DebugAssert(e.getKind()==RAW_LIST && e.arity() > 0 && e[0].getKind()==ID,
01747         "TheoryCore::parseExprOp:\n e = "+e.toString());
01748   TRACE("parse", "TheoryCore::parseExprOp:\n e = ", e.toString(), "");
01749   /* The first element of the list (e[0] is an ID of the operator.
01750      ID string values are the dirst element of the expression */
01751   const Expr& c1 = e[0][0];
01752   int kind = getEM()->getKind(c1.getString());
01753 
01754   if (isBasicKind(kind)) {
01755     vector<Expr> operatorStack;
01756     vector<Expr> operandStack;
01757     vector<int> childStack;
01758     Expr e2;
01759 
01760     operatorStack.push_back(e);
01761     childStack.push_back(1);
01762 
01763     while (!operatorStack.empty()) {
01764       DebugAssert(operatorStack.size() == childStack.size(), "Invariant violated");
01765 
01766       if (childStack.back() < operatorStack.back().arity()) {
01767 
01768         e2 = operatorStack.back()[childStack.back()++];
01769 
01770         ExprMap<Expr>::iterator iParseCache = d_parseCache->find(e2);
01771         if (iParseCache != d_parseCache->end()) {
01772           operandStack.push_back((*iParseCache).second);
01773         }
01774         else if (e2.getKind() == RAW_LIST &&
01775                  e2.arity() > 0 &&
01776                  e2[0].getKind() == ID &&
01777                  isBasicKind(getEM()->getKind(e2[0][0].getString()))) {
01778           operatorStack.push_back(e2);
01779           childStack.push_back(1);
01780         }
01781         else {
01782           operandStack.push_back(parseExpr(e2));
01783         }
01784       }
01785       else {
01786         e2 = operatorStack.back();
01787         operatorStack.pop_back();
01788         childStack.pop_back();
01789         vector<Expr> children;
01790         vector<Expr>::iterator childStart = operandStack.end() - (e2.arity() - 1);
01791         children.insert(children.begin(), childStart, operandStack.end());
01792         operandStack.erase(childStart, operandStack.end());
01793         kind = getEM()->getKind(e2[0][0].getString());
01794         operandStack.push_back(Expr(kind, children, e2.getEM()));
01795         (*d_parseCache)[e2] = operandStack.back();
01796         if (!getEM()->isTypeKind(operandStack.back().getKind())) {
01797           operandStack.back().getType();
01798         }
01799       }
01800     }
01801     DebugAssert(childStack.empty(), "Invariant violated");
01802     DebugAssert(operandStack.size() == 1, "Expected single operand left");
01803     return operandStack.back();
01804   }
01805 
01806   switch(kind) {
01807   case SUBTYPE:
01808     if (e.arity() <= 3) {
01809       Expr witness;
01810       if (e.arity() == 3) {
01811         witness = parseExpr(e[2]);
01812       }
01813       return newSubtypeExpr(parseExpr(e[1]), witness).getExpr();
01814     }
01815     else {
01816       throw ParserException("Expected one or two arguments to SUBTYPE");
01817     }
01818   case EQ:
01819     if(e.arity()==3) {
01820       Expr e1 = parseExpr(e[1]);
01821       Expr e2 = parseExpr(e[2]);
01822       if (e1.getType() == boolType() &&
01823           getFlags()["convert-eq-iff"].getBool()) {
01824         return e1.iffExpr(e2);
01825       }
01826       else {
01827         return e1.eqExpr(e2);
01828       }
01829     }
01830     else
01831       throw ParserException("Equality requires exactly two arguments: "
01832           +e.toString());
01833     break;
01834 
01835   case NEQ:
01836     if(e.arity()==3)
01837       return !(parseExpr(e[1]).eqExpr(parseExpr(e[2])));
01838     else
01839       throw ParserException("Disequality requires exactly two arguments: "
01840           +e.toString());
01841     break;
01842   case TYPE: {
01843     if(e.arity()==2) {
01844       const Expr& types = e[1];
01845       if(types.getKind() == RAW_LIST) {
01846   vector<Expr> names;
01847   for(Expr::iterator i=types.begin(), iend=types.end(); i!=iend; ++i)
01848     names.push_back(*i);
01849   return Expr(TYPEDECL, names, getEM());
01850       }
01851     }
01852     else if(e.arity() == 3 && e[1].getKind() == ID)
01853       return Expr(TYPEDEF, e[1], parseExpr(e[2]));
01854     throw ParserException("Bad TYPE declaration: "+e.toString());
01855     break;
01856   }
01857     //TODO: Is IF still used?
01858   case IF:
01859     if(e.arity() == 4) {
01860       Expr c(parseExpr(e[1]));
01861       Expr e1(parseExpr(e[2]));
01862       Expr e2(parseExpr(e[3]));
01863       return c.iteExpr(e1, e2);
01864     } else
01865       throw ParserException("Bad IF-THEN-ELSE expression: "
01866           +e.toString());
01867   case COND: {
01868     if(e.arity() >= 3)
01869       return processCond(e, 1);
01870     else
01871       throw ParserException("Bad COND expression: "+e.toString());
01872     break;
01873   }
01874   case LET: { // (LET ((v1 e1) (v2 e2) ... ) body)
01875     Expr e2(e);
01876     while (true) {
01877       if(!(e2.arity() == 3 && e2[1].getKind() == RAW_LIST && e2[1].arity() > 0))
01878         throw ParserException("Bad LET expression: "+e2.toString());
01879 
01880       // Iterate through the bound variables
01881       for(Expr::iterator i=e2[1].begin(), iend=e2[1].end(); i!=iend; ++i) {
01882         const Expr& decl = *i;
01883         if (decl.getKind() != RAW_LIST || decl.arity() != 2)
01884           throw ParserException("Bad variable declaration block in LET "
01885                                 "expression: "+decl.toString()+
01886                                 "\n e2 = "+e2.toString());
01887         if (decl[0].getKind() != ID)
01888           throw ParserException("Variable must be an identifier in LET "
01889                                 "expression: "+decl[0].toString()+
01890                                 "\n e2 = "+e2.toString());
01891         addBoundVar(decl[0][0].getString(), Type(), parseExpr(decl[1]));
01892       }
01893       // Optimization for nested LETs:
01894       if (e2[2].getKind()==RAW_LIST && e2[2].arity() > 0 &&
01895           e2[2][0].getKind()==ID && getEM()->getKind(e2[2][0][0].getString()) == LET) {
01896         e2 = e2[2];
01897       } else break;
01898     }
01899     // Parse the body recursively and return it (nuke the LET)
01900     return parseExpr(e2[2]);
01901   }
01902   case TRUE_EXPR: { return e.getEM()->trueExpr(); }
01903   case FALSE_EXPR:  { return e.getEM()->falseExpr();}
01904   case BOOLEAN:   { return e.getEM()->boolExpr(); }
01905     break;
01906   default:
01907     DebugAssert(false,
01908     "TheoryCore::parseExprOp: invalid command or expression: "
01909     + e.toString());
01910     break;
01911   }
01912   return e;
01913 }
01914 
01915 ExprStream& TheoryCore::printSmtLibShared(ExprStream& os, const Expr& e) {
01916   DebugAssert(os.lang() == SMTLIB_LANG || os.lang() == SMTLIB_V2_LANG,
01917       "Invalid state in printSmtLibShared" );
01918   switch(e.getKind()) {
01919   case TRUE_EXPR: os << "true"; break;
01920   case FALSE_EXPR: os << "false"; break;
01921   case UCONST: os << d_translator->escapeSymbol(d_translator->fixConstName(e.getName())); break;
01922   case BOOLEAN: e.printAST(os); break;
01923   case STRING_EXPR: e.print(os); break;
01924   case SUBTYPE:
01925     throw SmtlibException("TheoryCore::print: SMTLIB: SUBTYPE not implemented");
01926     break;
01927   case TYPEDEF: {
01928     throw SmtlibException("TheoryCore::print: SMTLIB: TYPEDEF not implemented");
01929     break;
01930   }
01931   case EQ:
01932     os << "(" << push << "=" << space << e[0]
01933        << space << e[1] << push << ")";
01934     break;
01935   case DISTINCT: {
01936     int i=0, iend=e.arity();
01937     os << "(" << push << "distinct";
01938     for(; i!=iend; ++i) os << space << e[i];
01939     os << push << ")";
01940     break;
01941   }
01942   case NOT:
01943     os << "(" << push << "not" << space << e[0] << push << ")";
01944     break;
01945   case AND: {
01946     int i=0, iend=e.arity();
01947     if(iend == 1 && os.lang() == SMTLIB_V2_LANG) {
01948       os << e[0];
01949     } else {
01950       os << "(" << push << "and";
01951       for(; i!=iend; ++i) os << space << e[i];
01952       os << push << ")";
01953     }
01954     break;
01955   }
01956   case OR: {
01957     int i=0, iend=e.arity();
01958     if(iend == 1 && os.lang() == SMTLIB_V2_LANG) {
01959       os << e[0];
01960     } else {
01961       os << "(" << push << "or";
01962       for(; i!=iend; ++i) os << space << e[i];
01963       os << push << ")";
01964     }
01965     break;
01966   }
01967   case XOR: {
01968     int i=0, iend=e.arity();
01969     if(iend == 1 && os.lang() == SMTLIB_V2_LANG) {
01970       os << e[0];
01971     } else {
01972       os << "(" << push << "xor";
01973       for(; i!=iend; ++i) os << space << e[i];
01974       os << push << ")";
01975     }
01976     break;
01977   }
01978 
01979   case TRANSFORM:
01980     throw SmtlibException("TheoryCore::print: SMTLIB: TRANSFORM not implemented");
01981     os << "(" << push << "TRANSFORM" << space << e[0] << push << ")";
01982     break;
01983 
01984   case LETDECL:
01985     //      throw SmtlibException("TheoryCore::print: SMTLIB: LETDECL not implemented");
01986     if(e.arity() == 2) os << e[1];
01987     else e.printAST(os);
01988     break;
01989 
01990 
01991   case PF_APPLY: {
01992     DebugAssert(e.arity() > 0, "TheoryCore::print(): "
01993     "Proof rule application must have at "
01994     "least one argument (rule name):\n "+e.toString());
01995     //      os << e[0]; by yeting
01996     os << e[0] << "\n" ;
01997     if(e.arity() > 1) { // Print the arguments
01998       os << push << "(" << push;
01999       bool first(true);
02000       for(int i=1; i<e.arity(); i++) {
02001         if(first) first=false;
02002         else os << push << "," << pop << space;
02003         //    os << e[i]; by yeting
02004         os << e[i] << "\n";
02005       }
02006       os << push << ")";
02007     }
02008     break;
02009   }
02010   case RAW_LIST: {
02011     os << "(" << push;
02012     bool firstTime(true);
02013     for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
02014       if(firstTime) firstTime = false;
02015       else os << space;
02016       os << *i;
02017     }
02018     os << push << ")";
02019     break;
02020   }
02021   case ANY_TYPE:
02022     os << "ANY_TYPE";
02023     break;
02024 
02025   case PF_HOLE: // FIXME: implement this (now fall through to default)
02026   default:
02027     throw SmtlibException("TheoryCore::print: SMTLIB_LANG: Unexpected expression: "
02028                           +getEM()->getKindName(e.getKind()));
02029   }
02030   return os;
02031 }
02032 
02033 static bool containsRec(const Expr& def, ExprHashMap<bool>& defs, ExprHashMap<bool>& visited) {
02034   ExprHashMap<bool>::iterator it = visited.find(def);
02035   if (it != visited.end()) return false;
02036   it = defs.find(def);
02037   if (it != defs.end()) return true;
02038   for(Expr::iterator i = def.begin(), iend=def.end(); i != iend; ++i) {
02039     if (containsRec(*i,defs,visited)) return true;
02040   }
02041   // [MGD] Closure exprs (LAMBDAs and quantifiers) don't have children,
02042   // they have bodies.
02043   if(def.isClosure()) {
02044     if (containsRec(def.getBody(),defs,visited)) return true;
02045   }
02046   visited[def] = true;
02047   return false;
02048 }
02049 
02050 static bool contains(const Expr& def, ExprHashMap<bool>& defs) {
02051   ExprHashMap<bool> visited;
02052   return containsRec(def, defs, visited);
02053 }
02054 
02055 ExprStream& TheoryCore::print(ExprStream& os, const Expr& e)
02056 {
02057   switch(os.lang()) {
02058   case SPASS_LANG:
02059     switch(e.getKind()) {
02060     case TRUE_EXPR: os << "true"; break;
02061     case FALSE_EXPR: os << "false"; break;
02062     case UCONST:
02063       if(isReal(getBaseType(e.getType()))) {
02064         // SPASS guys want "np" prefix on arith vars
02065         os << "np";
02066       }
02067       os << e.getName();
02068       break;
02069     case BOOLEAN: e.printAST(os); break;
02070     case STRING_EXPR: e.print(os); break;
02071     case TYPE:
02072       throw SmtlibException("TheoryCore::print: SPASS_LANG: TYPE should have been handled by Translator::finish()");
02073     case ID:
02074       if(e.arity() == 1 && e[0].isString()) os << e[0].getString();
02075       else e.printAST(os);
02076       break;
02077     case CONST:
02078       throw SmtlibException("TheoryCore::print: SPASS_LANG: CONST should have been handled by Translator::finish()");
02079     case SUBTYPE:
02080       throw SmtlibException("TheoryCore::print: SPASS_LANG: SUBTYPE not implemented");
02081       break;
02082     case TYPEDEF: {
02083       throw SmtlibException("TheoryCore::print: SPASS_LANG: TYPEDEF not implemented");
02084       break;
02085     }
02086     case EQ:
02087       os << push << "equal(" << e[0]
02088    << "," << space << e[1] << push << ")";
02089       break;
02090     case DISTINCT: {
02091       throw SmtlibException("TheoryCore::print: SPASS_LANG: SUBTYPE not implemented");
02092       break;
02093     }
02094     case NOT:
02095       os << push << "not(" << e[0] << push << ")";
02096       break;
02097     case AND: {
02098       int i=0, iend=e.arity();
02099       os << push << "and(" << e[i];
02100       while(++i != iend) os << "," << space << e[i];
02101       os << push << ")";
02102       break;
02103     }
02104     case OR: {
02105       int i=0, iend=e.arity();
02106       os << push << "or(" << e[i];
02107       while(++i != iend) os << "," << space << e[i];
02108       os << push << ")";
02109       break;
02110     }
02111     case XOR: {
02112       if(e.arity() != 2) {
02113         throw SmtlibException("TheoryCore::print: SPASS_LANG: XOR not supported when arity != 2 !");
02114       }
02115       os << push << "or(and(" << e[0] << "," << space << "not(" << e[1] << ")),"
02116          << space << "and(not(" << e[0] << ")," << space << e[1] << ")"
02117          << push << ")";
02118       break;
02119     }
02120     case ITE:
02121       if (e.getType().isBool()) {
02122         os << push << "and(" << space
02123            << push << "implies(" << space
02124            << e[0] << "," << space << e[1]
02125            << push << ")" << "," << space
02126            << push << "implies(" << space
02127            << e[0].negate() << "," << space << e[2]
02128            << push << ")"
02129            << push << ")";
02130       } else {
02131         os << push << "if_then_else("
02132            << e[0] << "," << space
02133            << e[1] << "," << space
02134            << e[2] << push << ")";
02135       }
02136       break;
02137     case IFF:
02138       os << push << "equiv(" << space
02139    << e[0] << space << "," << space << e[1] << push << ")";
02140       break;
02141     case IMPLIES:
02142       os << push << "implies(" << space
02143    << e[0] << space << "," << space << e[1] << push << ")";
02144       break;
02145     case ASSERT:
02146       // SPASS guys don't want formula(false) etc: comment them out
02147       if(e[0] == d_em->trueExpr() ||
02148          e[0] == d_em->falseExpr().notExpr()) {
02149         os << "% ";
02150       }
02151       os << "formula(" << space << push << e[0].negate() << space << ").";
02152       break;
02153     case TRANSFORM:
02154       throw SmtlibException("TheoryCore::print: SPASS: TRANSFORM not implemented");
02155       break;
02156     case QUERY:
02157       // SPASS guys don't want formula(false) etc: comment them out
02158       if(e[0].negate() == d_em->trueExpr() ||
02159          e[0].negate() == d_em->falseExpr().notExpr()) {
02160         os << "% ";
02161       }
02162       os << "formula(" << space << push << e[0] << space << ").";
02163       break;
02164     case LETDECL:
02165       throw SmtlibException("TheoryCore::print: SPASS_LANG: LETDECL not implemented");
02166     case LET:
02167       throw SmtlibException("TheoryCore::print: SPASS_LANG: LET should have been handled in Translator::finish()");
02168     case BOUND_VAR:
02169       if(isReal(getBaseType(e.getType()))) {
02170         // SPASS guys want "np" prefix on arith vars
02171         os << "np";
02172       }
02173       os << e.getName();
02174       break;
02175     case SKOLEM_VAR:
02176       os << push << "SKOLEM_" + int2string((int)e.getIndex());
02177       break;
02178     case PF_APPLY:
02179       throw SmtlibException("TheoryCore::print: SPASS_LANG: PF_APPLY not implemented");
02180     case ANNOTATION:
02181       throw SmtlibException("TheoryCore::print: SPASS_LANG: ANNOTATION should have been handled by Translator::finish()");
02182 
02183     case RAW_LIST:
02184     case ANY_TYPE:
02185     case WHERE:
02186     case ASSERTIONS:
02187     case ASSUMPTIONS:
02188     case COUNTEREXAMPLE:
02189     case COUNTERMODEL:
02190     case PUSH:
02191     case POP:
02192     case POPTO:
02193     case PUSH_SCOPE:
02194     case POP_SCOPE:
02195     case POPTO_SCOPE:
02196     case RESET:
02197     case PF_HOLE:
02198     default:
02199       throw SmtlibException("TheoryCore::print: SPASS_LANG: Unexpected expression: "
02200                             +getEM()->getKindName(e.getKind()));
02201     }
02202     break; // end of case SPASS_LANG
02203 
02204   case SIMPLIFY_LANG:
02205     switch(e.getKind()) {
02206     case TRUE_EXPR: os << "TRUE"; break;
02207     case FALSE_EXPR: os << "FALSE"; break;
02208     case TYPE:
02209       break; // no type for Simplify
02210     case ID:
02211       if(e.arity() == 1 && e[0].isString()) os << e[0].getString();
02212       else e.print(os);
02213       break;
02214     case CONST:
02215       //      os << "ERROR:const to be supported\n"; simplify do not need this
02216       break;
02217     case SUBTYPE:
02218       break;
02219     case TYPEDEF: {
02220       break;
02221     }
02222     case EQ:
02223       os << "(EQ " << e[0] << " " << e[1] << ")";
02224       break;
02225    case NOT: os << "(NOT " << e[0] << ")"; break;
02226    case AND: {
02227       int i=0, iend=e.arity();
02228       os << "(AND ";
02229       if(i!=iend) { os << e[i]; ++i; }
02230       for(; i!=iend; ++i) os << " " << e[i];
02231       os << ")";
02232     }
02233       break;
02234     case OR: {
02235       int i=0, iend=e.arity();
02236       os << "(OR ";
02237       if(i!=iend) { os << e[i]; ++i; }
02238       for(; i!=iend; ++i) os << " " << e[i];
02239       os << ")";
02240     }
02241       break;
02242     case ITE:
02243       os<<"ERROR:ITE:not supported yet\n";
02244       break;
02245     case IFF:
02246       if(e.arity() == 2)
02247   os << "(IFF " << e[0]  << " " << e[1] << ")";
02248       else
02249   e.print(os);
02250       break;
02251     case IMPLIES:
02252       os << "(IMPLIES " <<e[0] << " " << e[1]  << ")";
02253       break;
02254       // Commands
02255     case ASSERT:
02256       os << "(BG_PUSH " << e[0] <<  ")\n";
02257       break;
02258     case TRANSFORM:
02259       os << "ERROR:TRANSFORM:not supported in Simplify " << push << e[0] << push << "\n";
02260       break;
02261     case QUERY:
02262       os << e[0] <<"\n";
02263       break;
02264     case WHERE:
02265       os << "ERROR:WHERE:not supported in Simplify\n";
02266       break;
02267     case ASSERTIONS:
02268       os << "ERROR:ASSERTIONS:not supported in Simplify\n";
02269       break;
02270     case ASSUMPTIONS:
02271       os << "ERROR:ASSUMPTIONS:not supported in Simplify\n";
02272       break;
02273     case COUNTEREXAMPLE:
02274       os << "ERROR:COUNTEREXAMPLE:not supported in Simplify\n";
02275       break;
02276     case COUNTERMODEL:
02277       os << "ERROR:COUNTERMODEL:not supported in Simplify\n";
02278       break;
02279     case PUSH:
02280     case POP:
02281     case POPTO:
02282     case PUSH_SCOPE:
02283     case POP_SCOPE:
02284     case POPTO_SCOPE:
02285     case RESET:
02286       os << "ERROR:PUSH and POP:not supported in Simplify\n";
02287       break;
02288       //    case CONSTDEF:
02289     case LETDECL:
02290       os << "LETDECL not supported in Simplify\n";
02291       break;
02292     case LET: {
02293       // (LET (LETDECLS (LETDECL var [ type ] val) .... ) body)
02294       /*      bool first(true);
02295       os << "(" << push << "LET" << space << push;
02296       for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) {
02297   if(!first) os << push << "," << pop << endl;
02298   else first = false;
02299   if(i->arity() == 3) {
02300     os << (*i)[0] << ":" << space << push << (*i)[1]
02301        << space << "= " << push << nodag << (*i)[2] << pop << pop;
02302   } else {
02303     os << (*i)[0];
02304     Type tp((*i)[0].lookupType());
02305     if(!tp.isNull()) os << ":" << space << push << tp.getExpr();
02306     else os << push;
02307     os << space << "= " << push << nodag << (*i)[1] << pop << pop;
02308   }
02309       }
02310       os << pop << endl << "IN" << space << push << e[1] << push << ")";
02311       */
02312       os << "LET not supported in Simplify\n";
02313       break;
02314 
02315     }
02316     case BOUND_VAR:
02317       //      os << e.getName()+"_"+e.getUid(); // by yeting for a neat output
02318       os << e.getName();
02319       break;
02320     case SKOLEM_VAR:
02321       os << "SKOLEM_" + int2string((int)e.getIndex());
02322       break;
02323     case PF_APPLY: // FIXME: this will eventually go to the "symsim" theory
02324       /*      DebugAssert(e.arity() > 0, "TheoryCore::print(): "
02325       "Proof rule application must have at "
02326       "least one argument (rule name):\n "+e.toString());
02327       os << e[0];
02328       if(e.arity() > 1) { // Print the arguments
02329   os << push << "(" << push;
02330   bool first(true);
02331   for(int i=1; i<e.arity(); i++) {
02332     if(first) first=false;
02333     else os << push << "," << pop << space;
02334     os << e[i];
02335   }
02336   os << push << ")";
02337   }*/
02338 
02339       os << "PR_APPLY not supported in Simplify\n";
02340       break;
02341     case RAW_LIST: {
02342       /*      os << "[" << push;
02343       bool firstTime(true);
02344       for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
02345   if(firstTime) firstTime = false;
02346   else os << push << "," << pop << space;
02347   os << *i;
02348       }
02349       os << push << "]";*/
02350       os << "RAW_LIST not supported in Simplify\n";
02351       break;
02352     }
02353     case PF_HOLE: // FIXME: implement this (now fall through to default)
02354     default:
02355       // Print the top node in the default LISP format, continue with
02356       // pretty-printing for children.
02357       e.print(os);
02358     }
02359     break; // end of case simplify_LANG
02360 
02361   case TPTP_LANG: {
02362     static int axiom_counter =0;
02363     switch(e.getKind()) {
02364     case TRUE_EXPR: os << "$true"; break;
02365     case FALSE_EXPR: os << "$false"; break;
02366     case TYPE:
02367       break;
02368       if(e.arity() == 0) os << "TYPE";
02369       else if(e.arity() == 1) {
02370         for (int i=0; i < e[0].arity(); ++i) {
02371           if (i != 0) os << endl;
02372           os << e[0][i] << ": TYPE;";
02373         }
02374       }
02375       else if(e.arity() == 2)
02376   os << e[0] << ":" << push << " TYPE = " << e[1] << push << ";";
02377       else e.printAST(os);
02378       break;
02379     case ID:
02380       if(e.arity() == 1 && e[0].isString()) os << e[0].getString();
02381       else e.print(os);
02382       break;
02383     case CONST:
02384       if(e.arity() == 2) {
02385   string ename = to_lower(e[0].toString());
02386   os << "tff(" << ename << "_type, type,\n    " << ename;
02387   os << ": " <<  e[1] << "). \n";
02388       }
02389       else {
02390   os << "ERROR: CONST's arity > 2";
02391       }
02392       break;
02393 
02394     case SUBTYPE:
02395       break;
02396     case TYPEDEF: {
02397       break;
02398     }
02399     case EQ:
02400       os << e[0] << " = " << e[1];
02401       break;
02402 
02403     case DISTINCT: {
02404       int i=0, iend=e.arity();
02405       os << "$distinct(" ;
02406       os << e[i] ;
02407       i++;
02408       for(; i!=iend; ++i) os  << ", " << e[i] ;
02409       os <<  ")";
02410       break;
02411     }
02412 
02413     case NOT:
02414       os << "~(" << e[0]<<")" ;
02415       break;
02416 
02417    case AND: {
02418       int i=0, iend=e.arity();
02419       if(iend == 1) {
02420   os << e[i];
02421       }
02422 
02423       else if(iend > 1) {
02424   for(i=0 ; i < iend-1; i++) {
02425     os << "(" << e[i] << " \n& " ;
02426   }
02427   os << e[iend-1];
02428   for(i=0 ; i < iend-1; i++) {
02429     os << ")";
02430   }
02431       }
02432       else{
02433   os <<"ERROR:AND has less than 1 parameter\n";
02434       }
02435       break;
02436   }
02437     case OR: {
02438       int i=0, iend=e.arity();
02439       if(iend == 1) {
02440   os << e[i];
02441       }
02442 
02443       else if(iend > 1) {
02444   for(i=0 ; i < iend-1; i++) {
02445     os << "(" << e[i] << " \n| " ;
02446   }
02447   os << e[iend-1];
02448   for(i=0 ; i < iend-1; i++) {
02449     os << ")";
02450   }
02451       }
02452       else{
02453   os <<"ERROR:OR has less than 1 parameter\n";
02454       }
02455       break;
02456   }
02457     case ITE:
02458       os<<"ERROR:ITE:not supported in TPTP yet\n";
02459       /* os <<  "(AND (IMPLIES "<< e[0] << " " << e[1]<<")"
02460    <<  "(IMPLIES (NOT " <<e[0] << ")" << e[2] <<"))";
02461       */
02462       break;
02463     case IFF:
02464       if(e.arity() == 2)
02465   os << "(" <<  e[0]  << " \n<=> " << e[1] << ")" ;
02466       else
02467   e.print(os);
02468       break;
02469     case IMPLIES:
02470       os << "(" << e[0] << " \n=> " << e[1] << ")"  ;
02471       break;
02472       // Commands
02473     case ASSERT:
02474       os << "tff(" << axiom_counter++ << ", axiom, \n    " <<e[0] <<  ").\n";
02475 
02476       break;
02477     case TRANSFORM:
02478       os << "ERROR:TRANSFORM:not supported in TPTP " << push << e[0] << push << "\n";
02479       break;
02480     case QUERY:
02481       if(getFlags()["negate-query"].getBool() == true){
02482   if (e[0].isNot()){
02483     os << "tff(" << axiom_counter++ << ", conjecture, \n    " <<e[0][0] <<  ").\n";
02484   }
02485   else{
02486     os << "tff(" << axiom_counter++ << ", conjecture, \n    ~(" << e[0] <<  ")).\n";
02487   }
02488       }
02489       else{
02490   os << "tff(" << axiom_counter++ << ", conjecture, \n    " <<e[0] <<  ").\n";
02491       }
02492       break;
02493     case WHERE:
02494       os << "ERROR:WHERE:not supported in TPTP\n";
02495       break;
02496     case ASSERTIONS:
02497       os << "ERROR:ASSERTIONS:not supported in TPTP\n";
02498       break;
02499     case ASSUMPTIONS:
02500       os << "ERROR:ASSUMPTIONS:not supported in TPTP\n";
02501       break;
02502     case COUNTEREXAMPLE:
02503       os << "ERROR:COUNTEREXAMPLE:not supported in TPTP\n";
02504       break;
02505     case COUNTERMODEL:
02506       os << "ERROR:COUNTERMODEL:not supported in TPTP\n";
02507       break;
02508     case PUSH:
02509     case POP:
02510     case POPTO:
02511     case PUSH_SCOPE:
02512     case POP_SCOPE:
02513     case POPTO_SCOPE:
02514     case RESET:
02515       os << "ERROR:PUSH and POP:not supported in TPTP\n";
02516       break;
02517       //    case CONSTDEF:
02518     case LETDECL:
02519       os << "LETDECL not supported in Simplify\n";
02520       break;
02521     case LET: {
02522       bool first(true);
02523       os << " := [" ;
02524       for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) {
02525   if(!first) os << " , "  ;
02526   else first = false;
02527   if(i->arity() == 3) {
02528     os << (*i)[0] << ":" << (*i)[1]
02529        <<  " ERROR= " <<  nodag << (*i)[2] ;
02530   } else {
02531     os << (*i)[0];
02532     os <<  " := " << nodag << (*i)[1] ;
02533   }
02534   os <<endl;
02535       }
02536       os <<  "] : " << endl << "(" <<  e[1] << ")";
02537       break;
02538 
02539     }
02540 
02541     case BOUND_VAR:{
02542       //      os << e.getName()+"_"+e.getUid() ; // by yeting
02543       os<< to_upper(e.getName());
02544       break;
02545     }
02546     case SKOLEM_VAR:
02547       os << "SKOLEM_VAR is not supported in TPTP\n";
02548       break;
02549 
02550     case PF_APPLY: // FIXME: this will eventually go to the "symsim" theory
02551       /*      DebugAssert(e.arity() > 0, "TheoryCore::print(): "
02552       "Proof rule application must have at "
02553       "least one argument (rule name):\n "+e.toString());
02554       os << e[0];
02555       if(e.arity() > 1) { // Print the arguments
02556   os << push << "(" << push;
02557   bool first(true);
02558   for(int i=1; i<e.arity(); i++) {
02559     if(first) first=false;
02560     else os << push << "," << pop << space;
02561     os << e[i];
02562   }
02563   os << push << ")";
02564   }*/
02565 
02566       os << "PR_APPLY not supported in TPTP\n";
02567       break;
02568     case RAW_LIST: {
02569       /*      os << "[" << push;
02570       bool firstTime(true);
02571       for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
02572   if(firstTime) firstTime = false;
02573   else os << push << "," << pop << space;
02574   os << *i;
02575       }
02576       os << push << "]";*/
02577       os << "RAW_LIST not supported in TPTP\n";
02578       break;
02579     }
02580     case PF_HOLE:
02581       os << "PF_HOLE not supported in TPTP\n";
02582       break;
02583     case UCONST:
02584       {string name = e.getName();
02585       if(name.length() >= 5){
02586   if ('C' == name[0] && 'V' == name[1] && 'C' == name[2] && '_' == name[3] && isdigit(name[4])){
02587     os << to_upper(name);
02588   }
02589   else {
02590     os << to_lower(name);
02591   }
02592       }
02593       else {
02594   os<<to_lower(name);
02595       }
02596       //
02597       //      e.print(os); break;
02598       break;
02599       }
02600     case STRING_EXPR:
02601       os <<"ERROR:STRING_EXPR is not suppoerted in TPTP\n";
02602       e.print(os); break;
02603     case BOOLEAN:
02604       os << "$o";
02605       break;
02606     default:
02607       // Print the top node in the default LISP format, continue with
02608       // pretty-printing for children.
02609       os<<"unknown ";
02610       //      cout<<e.toString(PRESENTATION_LANG)<<endl;
02611       //      cout<<getEM()->getKindName(e.getKind())<<endl;
02612       e.print(os);
02613     }
02614     break; // end of case TPTP_LANG
02615   }
02616 
02617 
02618   case PRESENTATION_LANG:
02619     switch(e.getKind()) {
02620     case TRUE_EXPR:
02621       os << "TRUE";
02622       break;
02623     case FALSE_EXPR:
02624       os << "FALSE";
02625       break;
02626     case BOOLEAN:
02627       os << "BOOLEAN";
02628       break;
02629     case UCONST:
02630     case STRING_EXPR:
02631       e.print(os); break;
02632     case TYPE:
02633       if(e.arity() == 0) os << "TYPE";
02634       else if(e.arity() == 1) {
02635         for (int i=0; i < e[0].arity(); ++i) {
02636           if (i != 0) os << endl;
02637           os << e[0][i] << ": TYPE;";
02638         }
02639       }
02640       else if(e.arity() == 2)
02641   os << e[0] << ":" << push << " TYPE = " << e[1] << push << ";";
02642       else e.printAST(os);
02643       break;
02644     case ID:
02645       if(e.arity() == 1 && e[0].isString()) os << e[0].getString();
02646       else e.printAST(os);
02647       break;
02648     case CONST:
02649       if(e.arity() == 2) {
02650   if(e[0].getKind() == RAW_LIST) {
02651     bool first(true);
02652     for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) {
02653       if(first) first = false;
02654       else os << push << "," << pop << space;
02655       os << (*i);
02656     }
02657   }
02658   else
02659     os << e[0];
02660   os << ":" << push << space << e[1] << push << ";";
02661       } else if(e.arity() == 3)
02662   os << e[0] << ":" << push << space << e[1]
02663      << space << "=" << space << push << e[2] << push << ";";
02664       else
02665   e.printAST(os);
02666       break;
02667     case SUBTYPE:
02668       os << "SUBTYPE(" << push << e[0] << push << ")";
02669       break;
02670     case TYPEDEF: {
02671       // This is used when dumping declarations to file.  Print just
02672       // the name of the type, unless it's a messed-up expression.
02673       if(e.arity() != 2) e.printAST(os);
02674       else if(e[0].isString()) os << e[0].getString();
02675       else e[0].print(os);
02676       break;
02677     }
02678     case EQ:
02679       // When a separator starts with a space (like " = "), add the
02680       // leading space with 'space' modifier.  If this separator goes
02681       // to the next line, the leading spaces must be eaten up to get
02682       // the indentation right; 'space' will tell the indentation
02683       // engine that it is a space that can be eaten.  A space in a
02684       // string (like " ") will never be eaten.
02685       os << "(" << push << e[0] << space << "= " << e[1] << push << ")";
02686       break;
02687     case DISTINCT: {
02688        os << "DISTINCT(" << push;
02689        bool first(true);
02690        for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
02691          if (!first) os << push << "," << pop << space;
02692          else first = false;
02693          os << (*i);
02694        }
02695        os << push << ")";
02696      }
02697      break;
02698     case NOT: os << "NOT " << e[0]; break;
02699     case AND: {
02700       int i=0, iend=e.arity();
02701       os << "(" << push;
02702       if(i!=iend) { os << e[i]; ++i; }
02703       for(; i!=iend; ++i) os << space << "AND " << e[i];
02704       os << push << ")";
02705     }
02706       break;
02707     case OR: {
02708       int i=0, iend=e.arity();
02709       os << "(" << push;
02710       if(i!=iend) { os << e[i]; ++i; }
02711       for(; i!=iend; ++i) os << space << "OR " << e[i];
02712       os << push << ")";
02713     }
02714       break;
02715     case XOR: {
02716       int i=0, iend=e.arity();
02717       os << "(" << push;
02718       if(i!=iend) { os << e[i]; ++i; }
02719       for(; i!=iend; ++i) os << space << "XOR " << e[i];
02720       os << push << ")";
02721     }
02722       break;
02723     case ITE:
02724       os << push << "IF " << push << e[0] << popSave
02725    << space << "THEN " << pushRestore << e[1] << popSave
02726    << space << "ELSE " << pushRestore << e[2] << pop
02727    << space << "ENDIF";
02728       break;
02729     case IFF:
02730       if(e.arity() == 2)
02731   os << "(" << push << e[0] << space << "<=> " << e[1] << push << ")";
02732       else
02733   e.printAST(os);
02734       break;
02735     case IMPLIES:
02736       os << "(" << push << e[0] << space << "=> " << e[1] << push << ")";
02737       break;
02738       // Commands
02739     case ASSERT:
02740       os << "ASSERT " << push << e[0] << push << ";";
02741       break;
02742     case TRANSFORM:
02743       os << "TRANSFORM " << push << e[0] << push << ";";
02744       break;
02745     case QUERY:
02746       os << "QUERY " << push << e[0] << push << ";";
02747       break;
02748     case WHERE:
02749       os << "WHERE;";
02750       break;
02751     case ASSERTIONS:
02752       os << "ASSERTIONS;";
02753       break;
02754     case ASSUMPTIONS:
02755       os << "ASSUMPTIONS;";
02756       break;
02757     case COUNTEREXAMPLE:
02758       os << "COUNTEREXAMPLE;";
02759       break;
02760     case COUNTERMODEL:
02761       os << "COUNTERMODEL;";
02762       break;
02763     case PUSH:
02764       if(e.arity()==0)
02765   os << "PUSH;";
02766       else
02767   os << "PUSH" << space << e[0] << push << ";";
02768       break;
02769     case POP:
02770       if(e.arity()==0)
02771   os << "POP;";
02772       else
02773   os << "POP" << space << e[0] << push << ";";
02774       break;
02775     case POPTO:
02776       os << "POPTO" << space << e[0] << push << ";"; break;
02777     case PUSH_SCOPE:
02778       if(e.arity()==0)
02779   os << "PUSH_SCOPE;";
02780       else
02781   os << "PUSH_SCOPE" << space << e[0] << push << ";";
02782       break;
02783     case POP_SCOPE:
02784       if(e.arity()==0)
02785   os << "POP_SCOPE;";
02786       else
02787   os << "POP_SCOPE" << space << e[0] << push << ";";
02788       break;
02789     case POPTO_SCOPE:
02790       os << "POPTO_SCOPE" << space << e[0] << push << ";"; break;
02791     case RESET:
02792       os << "RESET;";
02793       break;
02794     case LETDECL:
02795       if(e.arity() == 2) os << e[1];
02796       else e.printAST(os);
02797       break;
02798     case LET: {
02799       // (LET (LETDECLS (LETDECL var [ type ] val) .... ) body)
02800       bool first(true);
02801       os << "(" << push << "LET" << space << push;
02802       for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) {
02803   if(!first) os << push << "," << pop << endl;
02804   else first = false;
02805   if(i->arity() == 3) {
02806     os << (*i)[0] << ":" << space << push << (*i)[1]
02807        << space << "= " << push << nodag << (*i)[2] << pop << pop;
02808   } else {
02809     os << (*i)[0];
02810     Type tp((*i)[0].lookupType());
02811     if(!tp.isNull()) os << ":" << space << push << tp.getExpr();
02812     else os << push;
02813     os << space << "= " << push << nodag << (*i)[1] << pop << pop;
02814   }
02815       }
02816       os << pop << endl << "IN" << space << push << e[1] << push << ")";
02817       break;
02818     }
02819     case BOUND_VAR:
02820       //      os << e.getName()+"_"+e.getUid();
02821 
02822       //by yeting, as requested by Sascha Boehme for proofs
02823       if(getFlags()["print-var-type"].getBool()) {
02824   os << e.getName() << "(" << e.getType() << ")";
02825       }
02826       else {
02827   os << e.getName(); //for better support of proof translation yeting
02828       }
02829       break;
02830     case SKOLEM_VAR:
02831       os << "SKOLEM_" + int2string((int)e.getIndex());
02832       break;
02833     case PF_APPLY: // FIXME: this will eventually go to the "symsim" theory
02834       DebugAssert(e.arity() > 0, "TheoryCore::print(): "
02835       "Proof rule application must have at "
02836       "least one argument (rule name):\n "+e.toString());
02837       //      os << e[0]; by yeting
02838       os << e[0] << "\n" ;
02839       if(e.arity() > 1) { // Print the arguments
02840   os << push << "(" << push;
02841   bool first(true);
02842   for(int i=1; i<e.arity(); i++) {
02843     if(first) first=false;
02844     else os << push << "," << pop << space;
02845     //    os << e[i]; by yeting
02846     os << e[i] << "\n";
02847   }
02848   os << push << ")";
02849       }
02850       break;
02851     case RAW_LIST: {
02852       os << "[" << push;
02853       bool firstTime(true);
02854       for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
02855   if(firstTime) firstTime = false;
02856   else os << push << "," << pop << space;
02857   os << *i;
02858       }
02859       os << push << "]";
02860       break;
02861     }
02862     case ANY_TYPE:
02863       os << "ANY_TYPE";
02864       break;
02865     case ARITH_VAR_ORDER: {
02866       os << "ARITH_VAR_ORDER(" << push;
02867       bool firstTime(true);
02868       for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
02869   if(firstTime) firstTime = false;
02870   else os << push << "," << pop << space;
02871   os << *i;
02872       }
02873       os << push << ");";
02874       break;
02875     }
02876     case ANNOTATION: {
02877       os << "%% ";
02878       os << e[0];
02879       if (e.arity() > 1) {
02880         os << ": " << e[1];
02881       }
02882     }
02883     case PF_HOLE: // FIXME: implement this (now fall through to default)
02884     default:
02885       // Print the top node in the default LISP format, continue with
02886       // pretty-printing for children.
02887       e.printAST(os);
02888     }
02889     break; // end of case PRESENTATION_LANG
02890 
02891   /* There's a lot of overlap between SMT-LIB v1 and v2, so we'll only handle
02892    * v1-specific stuff here, then goto (!) then end of the v2 block below.
02893    */
02894   case SMTLIB_LANG:
02895     switch(e.getKind()) {
02896     case TYPE:
02897       if (e.arity() == 1) {
02898         os << "  :extrasorts (";
02899         for (int i=0; i < e[0].arity(); ++i) {
02900           if (i != 0) os << push << space;
02901           os << push << e[0][i];
02902         }
02903         os << push << ")";
02904       }
02905       else if (e.arity() == 2) {
02906         break;
02907       }
02908       else {
02909         throw SmtlibException("TheoryCore::print: SMTLIB: Unexpected TYPE expression");
02910       }
02911       break;
02912 
02913     case CONST:
02914       if(e.arity() == 2) {
02915         if (e[1].getKind() == BOOLEAN) {
02916           os << "  :extrapreds ((" << push << d_translator->fixConstName(e[0][0].getString())
02917              << push << "))";
02918         }
02919         else if (e[1].getKind() == ARROW && e[1][e[1].arity()-1].getKind() == BOOLEAN) {
02920           os << "  :extrapreds ((" << push << d_translator->fixConstName(e[0][0].getString())
02921              << space << nodag << e[1] << push << "))";
02922         }
02923         else {
02924           os << "  :extrafuns ((" << push << d_translator->fixConstName(e[0][0].getString())
02925              << space << nodag << e[1] << push << "))";
02926         }
02927       }
02928       else if (e.arity() == 0) e.printAST(os);
02929       else {
02930         throw SmtlibException("TheoryCore::print: SMTLIB: CONST not implemented");
02931       }
02932       break;
02933 
02934     case ID: // FIXME: when lisp becomes case-insensitive, fix printing of IDs
02935       if(e.arity() == 1 && e[0].isString()) os << e[0].getString();
02936       else e.printAST(os);
02937       break;
02938 
02939     case IMPLIES:
02940       os << "(" << push << "implies" << space
02941          << e[0] << space << e[1] << push << ")";
02942       break;
02943 
02944     case IFF:
02945       os << "(" << push << "iff" << space
02946          << e[0] << space << e[1] << push << ")";
02947       break;
02948 
02949     case ITE:
02950       os << "(" << push;
02951       if (e.getType().isBool()) os << "if_then_else";
02952       else os << "ite";
02953       os << space << e[0]
02954          << space << e[1] << space << e[2] << push << ")";
02955       break;
02956 
02957       // Commands
02958     case ASSERT:
02959       os << "  :assumption" << space << push << e[0];
02960       break;
02961 
02962     case QUERY:
02963       os << "  :formula" << space << push << e[0].negate();
02964       break;
02965 
02966     case LET: {
02967       // (LET ((var [ type ] val) .... ) body)
02968       for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) {
02969         os << "(" << push;
02970         Type tp(i->arity() == 3 ? (*i)[2].getType() : (*i)[1].getType());
02971         DebugAssert(!tp.isNull(), "Unexpected Null type");
02972         if (tp.getExpr().getKind() == BOOLEAN) {
02973           os << "flet" << space << "(" << push;
02974         }
02975         else {
02976           os << "let" << space << "(" << push;
02977         }
02978         if(i->arity() == 3) {
02979           os << (*i)[0] << space << nodag << (*i)[2];
02980         } else {
02981           os << (*i)[0] << space << nodag << (*i)[1];
02982         }
02983         os << push << ")" << pop << pop << space;
02984       }
02985       os << e[1] << push;
02986       for (int j = 0; j < e[0].arity(); ++j)
02987         os << ")";
02988       break;
02989     }
02990 
02991     case BOUND_VAR: {
02992       //      os << push << "?" << e.getName()+"_"+e.getUid();
02993       string str = e.getName();
02994       if (str[0] == '_') str[0] = '?';
02995       os << push << str;
02996       break;
02997     }
02998     case SKOLEM_VAR:
02999       os << push << "SKOLEM_" + int2string((int)e.getIndex());
03000       break;
03001 
03002     case WHERE:
03003       os << "  :cvc_command \"WHERE\"";
03004       break;
03005     case ASSERTIONS:
03006       os << "  :cvc_command \"ASSERTIONS\"";
03007       break;
03008     case ASSUMPTIONS:
03009       os << "  :cvc_command \"ASSUMPTIONS\"";
03010       break;
03011     case COUNTEREXAMPLE:
03012       os << "  :cvc_command \"COUNTEREXAMPLE\"";
03013       break;
03014     case COUNTERMODEL:
03015       os << "  :cvc_command \"COUNTERMODEL\"";
03016       break;
03017     case PUSH:
03018       os << "  :cvc_command" << space;
03019       if(e.arity()==0)
03020         os << "\"PUSH\"";
03021       else
03022         os << "\"PUSH" << space << e[0] << push << "\"";
03023       break;
03024     case POP:
03025       os << "  :cvc_command" << space;
03026       if(e.arity()==0)
03027         os << "\"POP\"";
03028       else
03029         os << "\"POP" << space << e[0] << push << "\"";
03030       break;
03031     case POPTO:
03032       os << "  :cvc_command" << space;
03033       os << "\"POPTO" << space << e[0] << push << "\""; break;
03034     case PUSH_SCOPE:
03035       os << "  :cvc_command" << space;
03036       if(e.arity()==0)
03037         os << "\"PUSH_SCOPE\"";
03038       else
03039         os << "\"PUSH_SCOPE" << space << e[0] << push << "\"";
03040       break;
03041     case POP_SCOPE:
03042       os << "  :cvc_command" << space;
03043       if(e.arity()==0)
03044         os << "\"POP_SCOPE\"";
03045       else
03046         os << "\"POP_SCOPE" << space << e[0] << push << "\"";
03047       break;
03048     case POPTO_SCOPE:
03049       os << "  :cvc_command" << space;
03050       os << "\"POPTO_SCOPE" << space << e[0] << push << "\""; break;
03051       break;
03052     case RESET:
03053       os << "  :cvc_command" << space;
03054       os << "\"RESET\""; break;
03055       break;
03056     case ANNOTATION: {
03057       os << "  :" << e[0].getString();
03058       if (e[0].getString() == "notes") {
03059         os << space << e[1];
03060       }
03061       else if (e.arity() > 1) {
03062         os << space << "{" << e[1].getString() << "}";
03063       }
03064       break;
03065     }
03066 
03067     default: /* Must be shared, jump to the end of SMT-LIB v2 symbols */
03068       printSmtLibShared(os,e);
03069     }
03070     break;
03071 
03072   case SMTLIB_V2_LANG:
03073 
03074     switch(e.getKind()) {
03075     case TYPE:
03076       if (e.arity() == 1) {
03077         for (int i=0; i < e[0].arity(); ++i) {
03078           if( i!=0 ) {
03079             os << endl;
03080           }
03081           os << "(declare-sort" << space
03082              << push << nodag << e[0][i] << " 0)" << pop;
03083         }
03084       } else if (e.arity() == 2) {
03085         break;
03086       } else {
03087         throw SmtlibException("TheoryCore::print: SMTLIB: Unexpected TYPE expression");
03088       }
03089       break;
03090 
03091     case BOOLEAN:
03092       os << "Bool";
03093       break;
03094 
03095     case CONST:
03096       if(e.arity() == 2) {
03097         os << "(declare-fun" << space << push
03098            << d_translator->escapeSymbol(d_translator->fixConstName(e[0][0].getString()))
03099            << space;
03100         if( e[1].getKind() == ARROW ) {
03101           os << nodag << e[1];
03102         } else {
03103           os << "()" << space << nodag << e[1];
03104         }
03105         os << ")" << pop;
03106       }
03107       else if (e.arity() == 0) e.printAST(os);
03108       else {
03109         throw SmtlibException("TheoryCore::print: SMTLIB: CONST not implemented");
03110       }
03111       break;
03112 
03113     case ID: // FIXME: when lisp becomes case-insensitive, fix printing of IDs
03114       if(e.arity() == 1 && e[0].isString()) os << d_translator->escapeSymbol(e[0].getString());
03115       else e.printAST(os);
03116       break;
03117 
03118     case IMPLIES:
03119       os << "(" << push << "=>" << space
03120          << e[0] << space << e[1] << push << ")";
03121       break;
03122 
03123     case IFF:
03124       os << "(" << push << "=" << space
03125          << e[0] << space << e[1] << push << ")";
03126       break;
03127 
03128     case ITE:
03129       os << "(" << push << "ite";
03130       os << space << e[0]
03131          << space << e[1] << space << e[2] << push << ")";
03132       break;
03133 
03134       // Commands
03135     case ASSERT:
03136       os << "(assert" << space << push << e[0] << ")" << pop;
03137       break;
03138 
03139     case QUERY:
03140       if (e[0] != falseExpr() && e[0].negate() != trueExpr()) {
03141         os << push << "(assert" << space << push << e[0].negate() << pop << ")" << pop << endl;
03142       }
03143       os << "(check-sat)";
03144       break;
03145 
03146     case LET: {
03147       // (LET ((var [ type ] val) .... ) body)
03148       Expr var, def;
03149       bool first = true;
03150       int letCount = 0;
03151       ExprHashMap<bool> defs;
03152       for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) {
03153         Type tp(i->arity() == 3 ? (*i)[2].getType() : (*i)[1].getType());
03154         DebugAssert(!tp.isNull(), "Unexpected Null type");
03155         var = (*i)[0];
03156         if(i->arity() == 3) {
03157           def = (*i)[2];
03158         }
03159         else {
03160           def = (*i)[1];
03161         }
03162         if (first || contains(def, defs)) {
03163           if (!first) {
03164             os << push << ")" << pop << pop << space;
03165             defs.clear();
03166           }
03167           os << "(" << push << "let" << space << "(" << push;
03168           ++letCount;
03169           first = false;
03170         }
03171         else {
03172           os << space;
03173         }
03174         defs[def] = true;
03175         os << "(" << push << var << space << nodag << def << ")" << pop;
03176       }
03177       DebugAssert(!first, "Expected at least one child");
03178       os << push << ")" << pop << pop << space << e[1];
03179       for (int j = 0; j < letCount; ++j)
03180         os << ")" << pop;
03181       break;
03182     }
03183     case BOUND_VAR: {
03184       string str = e.getName();
03185       if (str[0] == '_') str[0] = '?';
03186       os << push << d_translator->escapeSymbol(str);
03187       break;
03188     }
03189     case SKOLEM_VAR:
03190       os << "SKOLEM_" + int2string((int)e.getIndex());
03191       break;
03192 
03193     case WHERE:
03194     case ASSERTIONS:
03195     case ASSUMPTIONS:
03196       os << "(get-assertions)";
03197       break;
03198     case COUNTEREXAMPLE:
03199       os << "(get-unsat-core)";
03200       break;
03201     case COUNTERMODEL:
03202       os << "(get-model)";
03203       break;
03204     case PUSH:
03205     case PUSH_SCOPE:
03206       if(e.arity()==0)
03207         os << "(push 1)";
03208       else
03209         os << "(push" << space << push << e[0] << ")" << pop;
03210       break;
03211     case POP:
03212     case POP_SCOPE:
03213       if(e.arity()==0)
03214         os << "(pop 1)";
03215       else
03216         os << "(pop" << space << push << e[0] << ")" << pop;
03217       break;
03218     case POPTO:
03219       os << "  :cvc_command" << space
03220         << "\"POPTO" << space << e[0] << push << "\""; break;
03221     case POPTO_SCOPE:
03222       os << "  :cvc_command" << space
03223         << "\"POPTO_SCOPE" << space << push << e[0] << "\"" << pop;
03224       break;
03225     case RESET:
03226       os << "  :cvc_command" << space;
03227       os << "\"RESET\""; break;
03228       break;
03229     case ANNOTATION: {
03230       os << "(set-info :" << e[0].getString();
03231       if (e.arity() > 1)
03232         os << space << d_translator->quoteAnnotation(e[1].getString());
03233       os << ")";
03234       break;
03235     }
03236 
03237     default: // fall-through to shared symbols
03238       printSmtLibShared(os,e);
03239     }
03240     break;
03241 
03242   case LISP_LANG:
03243     switch(e.getKind()) {
03244     case TRUE_EXPR:
03245     case FALSE_EXPR:
03246     case UCONST:
03247       e.print(os); break;
03248     case TYPE:
03249       if(e.arity() == 0) os << "TYPE";
03250       else if(e.arity() == 1)
03251   os << "(" << push << "TYPE" << space << e[0] << push << ")";
03252       else if(e.arity() == 2)
03253   os << "(" << push << "TYPE" << space << e[0]
03254      << space << e[1] << push << ")";
03255       else e.printAST(os);
03256       break;
03257     case ID: // FIXME: when lisp becomes case-insensitive, fix printing of IDs
03258       if(e.arity() == 1 && e[0].isString()) os << e[0].getString();
03259       else e.printAST(os);
03260       break;
03261     case CONST:
03262       if(e.arity() == 2)
03263   os << "(" << push << "CONST" << space << e[0]
03264      << space << e[1] << push << ")";
03265       else
03266   e.printAST(os);
03267       break;
03268     case SUBTYPE:
03269       os << "SUBTYPE(" << push << e[0] << push << ")";
03270       break;
03271     case TYPEDEF: {
03272       // This is used when dumping declarations to file.  Print just
03273       // the name of the type, unless it's a messed-up expression.
03274       if(e.arity() != 2) e.printAST(os);
03275       else if(e[0].isString()) os << e[0].getString();
03276       else e[0].print(os);
03277       break;
03278     }
03279     case EQ:
03280       // When a separator starts with a space (like " = "), add the
03281       // leading space with 'space' modifier.  If this separator goes
03282       // to the next line, the leading spaces must be eaten up to get
03283       // the indentation right; 'space' will tell the indentation
03284       // engine that it is a space that can be eaten.  A space in a
03285       // string (like " ") will never be eaten.
03286       os << "(" << push << "=" << space << e[0]
03287    << space << e[1] << push << ")";
03288       break;
03289     case NOT:
03290       os << "(" << push << "NOT" << space << e[0] << push << ")";
03291       break;
03292     case AND: {
03293       int i=0, iend=e.arity();
03294       os << "(" << push << "AND";
03295       for(; i!=iend; ++i) os << space << e[i];
03296       os << push << ")";
03297     }
03298       break;
03299     case OR: {
03300       int i=0, iend=e.arity();
03301       os << "(" << push << "OR";
03302       for(; i!=iend; ++i) os << space << e[i] << space;
03303       os << push << ")";
03304     }
03305       break;
03306     case ITE:
03307       os << "(" << push << "IF" << space << e[0]
03308    << space << e[1] << space << e[2] << push << ")";
03309       break;
03310     case IFF:
03311       os << "(" << push << "<=>" << space
03312    << e[0] << space << e[1] << push << ")";
03313       break;
03314     case IMPLIES:
03315       os << "(" << push << "=>" << space
03316    << e[0] << space << e[1] << push << ")";
03317       break;
03318       // Commands
03319     case ASSERT:
03320       os << "(" << push << "ASSERT" << space << e[0] << push << ")";
03321       break;
03322     case TRANSFORM:
03323       os << "(" << push << "TRANSFORM" << space << e[0] << push << ")";
03324       break;
03325     case QUERY:
03326       os << "(" << push << "QUERY" << space << e[0] << push << ")";
03327       break;
03328     case PUSH:
03329       os << "(PUSH)"; break;
03330     case POP:
03331       os << "(POP)"; break;
03332     case POPTO:
03333       os << "(" << push << "POPTO" << space << e[0] << push << ")"; break;
03334     case RESET:
03335       os << "(" << push << "RESET" << push << ")"; break;
03336     case LETDECL:
03337       if(e.arity() == 2) os << e[1];
03338       else if(e.arity()==3) // It's a declaration of a named Expr
03339   os << e[0] << push << ":" << space << push << e[1] << push << " ="
03340      << pop << pop << space << e[2];
03341       else e.printAST(os);
03342       break;
03343     case LET: {
03344       // (LET ((var [ type ] val) .... ) body)
03345       bool first(true);
03346       os << "(" << push << "LET" << space << "(" << push;
03347       for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) {
03348   if(!first) os << space;
03349   else first = false;
03350   os << "(" << push;
03351   if(i->arity() == 3) {
03352     os << (*i)[0] << space << (*i)[1]
03353        << space << nodag << (*i)[2];
03354   } else {
03355     os << (*i)[0];
03356     Type tp((*i)[0].lookupType());
03357     if(!tp.isNull()) os << space << tp.getExpr();
03358     os << space << nodag << (*i)[1];
03359   }
03360   os << push << ")" << pop << pop;
03361       }
03362       os << push << ")" << pop << pop << space << e[1] << push << ")";
03363       break;
03364     }
03365     case BOUND_VAR:
03366       //      os << e.getName()+"_"+e.getUid(); by yeting
03367       os << e.getName();
03368       break;
03369     case SKOLEM_VAR:
03370       os << "SKOLEM_" + int2string((int)e.getIndex());
03371       break;
03372     case PF_APPLY: {// FIXME: this will eventually go to the "symsim" theory
03373       DebugAssert(e.arity() > 0, "TheoryCore::print(): "
03374       "Proof rule application must have at "
03375       "least one argument (rule name):\n "+e.toString());
03376       os << push << "(" << push;
03377       bool first(true);
03378       for(int i=0; i<e.arity(); i++) {
03379   if(first) first=false;
03380   else os << space;
03381   os << e[i];
03382       }
03383       os << push << ")";
03384       break;
03385     }
03386     case RAW_LIST: {
03387       os << "(" << push;
03388       bool firstTime(true);
03389       for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
03390   if(firstTime) firstTime = false;
03391   else os << space;
03392   os << *i;
03393       }
03394       os << push << ")";
03395       break;
03396     }
03397     case ANY_TYPE:
03398       os << "ANY_TYPE";
03399       break;
03400     case PF_HOLE: // FIXME: implement this (now fall through to default)
03401     default:
03402       // Print the top node in the default LISP format, continue with
03403       // pretty-printing for children.
03404       e.printAST(os);
03405     }
03406     break; // end of case LISP_LANGUAGE
03407   default:
03408     // Print the top node in the default LISP format, continue with
03409     // pretty-printing for children.
03410     e.printAST(os);
03411   }
03412   return os;
03413 }
03414 
03415 bool TheoryCore::refineCounterExample(Theorem& thm)
03416 {
03417   // Theory 0 is TheoryCore, skip it
03418   for(int i = 1; i<getNumTheories(); i++) {
03419     if(d_theories[i] != this)
03420       d_theories[i]->refineCounterExample();
03421       if(inconsistent()) {
03422         thm = inconsistentThm();
03423         return false;
03424       }
03425   }
03426   return true;
03427 }
03428 
03429 void TheoryCore::refineCounterExample()
03430 {
03431   // Theory 0 is TheoryCore, skip it
03432   for(int i = 1; i<getNumTheories(); i++) {
03433     if(d_theories[i] != this)
03434       d_theories[i]->refineCounterExample();
03435     if(inconsistent()) {
03436       vector<Expr> assump;
03437       inconsistentThm().getLeafAssumptions(assump);
03438       Expr a = Expr(RAW_LIST, assump, d_em);
03439       throw EvalException("Theory["+d_theories[i]->getName()
03440           +"]: Model Creation failed due "
03441           "to the following assumptions:\n\n"
03442           +a.toString()
03443           +"\n\nYou might be using an incomplete logical fragment.");
03444     }
03445   }
03446 }
03447 
03448 
03449 void TheoryCore::computeModelBasic(const vector<Expr>& v) {
03450   for(vector<Expr>::const_iterator i=v.begin(), iend=v.end(); i!=iend; ++i) {
03451     TRACE("model", "Model var "+i->toString()+" = ", find(*i).getRHS(), "");
03452     DebugAssert((*i).getType().isBool(), "TheoryCore::computeModel: *i = "
03453     +(*i).toString());
03454     Expr val = find(*i).getRHS();
03455     if(!val.isBoolConst()) val = d_em->trueExpr();
03456     assignValue(*i, val);
03457   }
03458 }
03459 
03460 
03461 /*****************************************************************************/
03462 /*
03463  * User-level API methods
03464  */
03465 /*****************************************************************************/
03466 
03467 
03468 void TheoryCore::addFact(const Theorem& e)
03469 {
03470   //<<<<<<< theory_core_sat.cpp
03471   //  cout<<"theory_core_sat.cpp asserted fact:"<<e<<endl;
03472   //  IF_DEBUG(string indentStr(getCM()->scopeLevel(), ' ');)
03473   //  TRACE("addFact", indentStr, "Assert: ", e.getExpr().toString(PRESENTATION_LANG));
03474   //=======
03475   IF_DEBUG(string indentStr(getCM()->scopeLevel(), ' ');)
03476   TRACE("addFact", indentStr, "Assert: ", e.getExpr().toString(PRESENTATION_LANG));
03477   //>>>>>>> 1.7
03478   DebugAssert(!d_inAddFact, "Recursive call to addFact() is not allowed");
03479   DebugAssert(d_queue.empty(), "addFact[start]: Expected empty queue");
03480   //  DebugAssert(d_queueSE.empty(), "addFact[start]: Expected empty queue");
03481   DebugAssert(d_update_thms.empty() && d_update_data.empty(),
03482               "addFact[start]: Expected empty update list");
03483   ScopeWatcher sw(&d_inAddFact);
03484 
03485   if(!d_inconsistent && !outOfResources()) {
03486     getResource();
03487     d_queue.push(e);
03488 
03489     //    cout<<"queue pushed" <<e<<endl;
03490     //    cout<<"queue pushed id" <<e.getQuantLevel()<<endl;
03491 
03492     if (outOfResources()) {
03493       // No more resources: ignore all the remaining facts and fail
03494       // gracefully
03495       setIncomplete("Exhausted user-specified resource");
03496     }
03497     processFactQueue();
03498   }
03499 
03500   DebugAssert(d_queue.empty(), "addFact[end]: Expected empty queue");
03501   DebugAssert(d_queueSE.empty(), "addFact[end]: Expected empty queue");
03502   DebugAssert(d_update_thms.empty() && d_update_data.empty(),
03503               "addFact[end]: Expected empty update list");
03504 }
03505 
03506 
03507 bool TheoryCore::checkSATCore()
03508 {
03509   DebugAssert(d_queue.empty(), "checkSATCore[start]: Expected empty queue");
03510   DebugAssert(d_queueSE.empty(), "checkSATCore[start]: Expected empty queue");
03511   DebugAssert(!d_inCheckSATCore, "Recursive call to checkSATCore is not allowed!");
03512   ScopeWatcher sw(&d_inCheckSATCore);
03513   IF_DEBUG(debugger.counter("DP checkSAT(fullEffort) calls")++;)
03514   DebugAssert(d_update_thms.empty() && d_update_data.empty(),
03515               "addFact[start]: Expected empty update list");
03516 
03517   bool lemmas = processFactQueue(FULL);
03518 
03519   DebugAssert(d_queue.empty(), "checkSATCore[start]: Expected empty queue");
03520   DebugAssert(d_queueSE.empty(), "checkSATCore[start]: Expected empty queue");
03521   DebugAssert(d_update_thms.empty() && d_update_data.empty(),
03522               "addFact[end]: Expected empty update list");
03523 
03524   return !lemmas;
03525 }
03526 
03527 
03528 bool TheoryCore::incomplete(vector<string>& reasons)
03529 {
03530   if(d_incomplete.size() > 0) {
03531     for(CDMap<string,bool>::iterator i=d_incomplete.begin(),
03532     iend=d_incomplete.end(); i!=iend; ++i)
03533       reasons.push_back((*i).first);
03534     return true;
03535   }
03536   else
03537     return false;
03538 }
03539 
03540 
03541 void TheoryCore::registerAtom(const Expr& e, const Theorem& thm)
03542 {
03543   DebugAssert(!e.isEq() || e[0] != e[1], "expected non-reflexive");
03544   DebugAssert(!e.isRegisteredAtom(), "atom registered more than once");
03545   //  if (e.isQuantifier()) return;
03546   e.setRegisteredAtom();
03547   if(d_termTheorems.find(e) != d_termTheorems.end()){
03548     //    cout<<"found this before 1 : "<<e<<endl;
03549   }
03550   //  cout<<"#1# get into "<<e<<endl;
03551   d_termTheorems[e] = thm;
03552   DebugAssert(e.isAbsAtomicFormula(), "Expected atomic formula");
03553   ScopeWatcher sw(&d_inRegisterAtom);
03554   Theorem thm2 = simplify(e);
03555   if (thm2.getRHS().isTrue()) {
03556     setFindLiteral(d_commonRules->iffTrueElim(thm2));
03557   }
03558   else if (thm2.getRHS().isFalse()) {
03559     setFindLiteral(d_commonRules->iffFalseElim(thm2));
03560   }
03561   else {
03562     //TODO: why does arith need thm2.getRHS() instead of e?
03563     //    theoryOf(e)->registerAtom(e);
03564     theoryOf(thm2.getRHS())->registerAtom(thm2.getRHS());
03565     setupSubFormulas(thm2.getRHS(), e, thm);
03566   }
03567   processFactQueue(LOW);
03568 }
03569 
03570 
03571 Theorem TheoryCore::getImpliedLiteral(void)
03572 {
03573   Theorem res;
03574   if (d_impliedLiteralsIdx < d_impliedLiterals.size()) {
03575     res = d_impliedLiterals[d_impliedLiteralsIdx];
03576     d_impliedLiteralsIdx = d_impliedLiteralsIdx + 1;
03577   }
03578   return res;
03579 }
03580 
03581 
03582 Theorem TheoryCore::getImpliedLiteralByIndex(unsigned index)
03583 {
03584   DebugAssert(index < d_impliedLiterals.size(), "index out of bounds");
03585   return d_impliedLiterals[index];
03586 }
03587 
03588 
03589 Expr TheoryCore::parseExpr(const Expr& e)
03590 {
03591   // check cache
03592   ExprMap<Expr>::iterator iParseCache = d_parseCache->find(e);
03593   if (iParseCache != d_parseCache->end()) {
03594     return (*iParseCache).second;
03595   }
03596   // Remember the current size of the bound variable stack
03597   size_t boundVarSize = d_boundVarStack.size();
03598 
03599   // Compute the kind to determine what to do with the expression
03600   int kind = NULL_KIND;
03601   Expr res;
03602 
03603   switch(e.getKind()) {
03604   case ID: {
03605     const Expr c1 = e[0];
03606     kind = getEM()->getKind(c1.getString());
03607     if(kind == NULL_KIND) { // It's an identifier; try to resolve it
03608       res = resolveID(e[0].getString());
03609       if(res.isNull())
03610   throw ParserException("cannot resolve an identifier: "
03611             +e[0].toString());
03612       else {
03613         DebugAssert(!e.isApply(), "Unexpected apply function");
03614       }
03615     }
03616     // Otherwise exit the switch and use DP-specific parsing
03617     break;
03618   }
03619   case RAW_LIST: {
03620     if(e.arity() == 0)
03621       throw ParserException("Empty list is not an expression!");
03622     const Expr& op = e[0];
03623     // First, resolve the operator
03624     switch(op.getKind()) {
03625     case ID: { // The operator in the list is ID: is it keyword or variable?
03626       kind = getEM()->getKind(op[0].getString());
03627       if(kind == NULL_KIND) {
03628   // It's a named function application.  Resolve the ID.
03629   res = resolveID(op[0].getString());
03630   if(res.isNull()){
03631     //    cout<<"stop here: " << e << endl;
03632     //    cout<<"stop here op: " << op << endl;
03633     //    cout<<"stop here op[0]: " << op[0] << endl;
03634     throw ParserException("cannot resolve an identifier: "
03635         +op[0].toString());
03636   }
03637         if(e.arity() < 2)
03638           throw ParserException("Bad function application: "+e.toString());
03639         Expr::iterator i=e.begin(), iend=e.end();
03640         ++i;
03641         vector<Expr> args;
03642         for(; i!=iend; ++i) args.push_back(parseExpr(*i));
03643         res = Expr(res.mkOp(), args);
03644       }
03645       // Proceed to DP-specific parsing
03646       break;
03647     }
03648     case RAW_LIST:
03649       // This can only be a lambda expression application.
03650       kind = LAMBDA;
03651       break;
03652     case STRING_EXPR: {
03653         vector<Expr> assignmentVars;
03654         if(op.getString() == "_ANNOTATION") {
03655           for(int i = 0; i < e[2].arity(); ++i) {
03656             if(e[2][i][0][0].getString() == ":named") {
03657               FatalAssert(e[2][i].arity() == 2 && e[2][i][1].getKind() == ID,
03658                         ":named annotation must take a name");
03659               assignmentVars.push_back(e[2][i][1]);
03660             }
03661           }
03662           Expr parsed = parseExpr(e[1]);
03663           for(unsigned i = 0; i < assignmentVars.size(); ++i) {
03664             d_assignment.push_back(make_pair(assignmentVars[i], parsed));
03665           }
03666           // Return rather than break; nothing more to do with the
03667           // annotation expr itself; it is stripped away.
03668           return parsed;
03669         }
03670         /* else fall through... */
03671       }
03672     default:
03673       throw ParserException("Bad operator in "+e.toString());
03674     }
03675     break; // Exit the top-level switch, proceed to DP-specific parsing
03676   }
03677   default: // Can only be a string or a number.
03678     res = e;
03679   }
03680 
03681   // DP-specific parsing
03682   if(res.isNull()) {
03683     if (hasTheory(kind)) {
03684       res = theoryOf(kind)->parseExprOp(e);
03685       // Restore the bound variable stack
03686       if (d_boundVarStack.size() > boundVarSize) {
03687         d_parseCache->clear();
03688         if (boundVarSize == 0) {
03689           d_parseCache = &d_parseCacheTop;
03690         }
03691         while(d_boundVarStack.size() > boundVarSize) {
03692           pair<string,Expr>& bv = d_boundVarStack.back();
03693           hash_map<string,Expr>::iterator iBoundVarMap = d_boundVarMap.find(bv.first);
03694           DebugAssert(iBoundVarMap != d_boundVarMap.end(), "Expected bv in map");
03695           if ((*iBoundVarMap).second.getKind() == RAW_LIST) {
03696             (*iBoundVarMap).second = (*iBoundVarMap).second[1];
03697           }
03698           else d_boundVarMap.erase(bv.first);
03699           d_boundVarStack.pop_back();
03700         }
03701       }
03702     }
03703     else {
03704       res = e;
03705     }
03706   }
03707   (*d_parseCache)[e] = res;
03708   if (!getEM()->isTypeKind(res.getOpKind())) res.getType();
03709   return res;
03710 }
03711 
03712 
03713 void TheoryCore::assignValue(const Expr& t, const Expr& val)
03714 {
03715   DebugAssert(d_varAssignments.count(t) == 0
03716         || d_varAssignments[t].getRHS() == val,
03717         "TheoryCore::assignValue("+t.toString()+" := "+val.toString()
03718         +")\n variable already has a different value");
03719   // Check if the assignment theorem can be derived from the find of t
03720   Theorem thm(find(t));
03721   Expr t2 = thm.getRHS();
03722 
03723   if(t2!=val) {
03724     bool isBool(t2.getType().isBool());
03725     Expr assump = (isBool)? t2.iffExpr(val) : t2.eqExpr(val);
03726     Theorem assertThm = d_coreSatAPI->addAssumption(assump);
03727     addFact(assertThm);
03728     thm = transitivityRule(thm, assertThm);
03729   }
03730   d_varAssignments[t] = thm;
03731 }
03732 
03733 
03734 void TheoryCore::assignValue(const Theorem& thm)
03735 {
03736   DebugAssert(thm.isRewrite(), "TheoryCore::assignValue("+thm.toString()+")");
03737   const Expr& t = thm.getLHS();
03738   const Expr& val = thm.getRHS();
03739   DebugAssert(d_varAssignments.count(t) == 0
03740         || d_varAssignments[t].getRHS() == val,
03741         "TheoryCore::assignValue("+thm.getExpr().toString()
03742         +")\n variable already has a different value:\n "
03743         +d_varAssignments[t].getExpr().toString());
03744   d_varAssignments[t] = thm;
03745   // Check if the assignment theorem can be derived from the find of t
03746   Theorem findThm(find(t));
03747   const Expr& t2 = findThm.getRHS();
03748 
03749   if(t2!=val) {
03750     Theorem thm2 = transitivityRule(symmetryRule(findThm), thm);
03751     addFact(thm2);
03752   }
03753 }
03754 
03755 
03756 void TheoryCore::addToVarDB(const Expr&  e)
03757 {
03758   TRACE("model", "TheoryCore::addToVarDB(", e, ")");
03759   d_vars.push_back(e);
03760 }
03761 
03762 
03763 void TheoryCore::collectBasicVars()
03764 {
03765   TRACE_MSG("model", "collectBasicVars() {");
03766   // Clear caches
03767   d_varModelMap.clear();
03768   d_varAssignments.clear();
03769   d_basicModelVars.clear();
03770   d_simplifiedModelVars.clear();
03771   // Current stack of variables to process
03772   vector<Expr> stack(d_vars.begin(), d_vars.end());
03773   size_t lastSize(0);
03774   while(stack.size() > 0) {
03775     Expr var(stack.back());
03776     stack.pop_back();
03777     if(d_varModelMap.count(var) > 0) continue; // Already processed
03778     Theorem findThm(find(var));
03779     if(findThm.getRHS()!=var) { // Replace var with its find
03780       d_simplifiedModelVars[var] = findThm;
03781       stack.push_back(findThm.getRHS());
03782       TRACE("model", "collectBasicVars: simplified var: ", findThm.getExpr(), "");
03783       continue; // Recycle to the beginning of the loop
03784     }
03785     lastSize = stack.size();
03786     TRACE("model", "getModelTerm(", var, ") {");
03787     getModelTerm(var, stack);
03788     TRACE("model", "getModelTerm => ",
03789     Expr(RAW_LIST, stack, getEM()), " }");
03790     if(stack.size() == lastSize) {
03791       // Add a primitive variable
03792       TRACE("model", "collectBasicVars: adding primitive var: ", var, "");
03793       d_basicModelVars.push_back(var);
03794       if(var.isTerm()) {
03795   Theory* t1 = theoryOf(var);
03796   Theory* t2 = theoryOf(getBaseType(var).getExpr().getKind());
03797   if(t1 != t2) {
03798     TRACE("model", "collectBasicVars: adding shared var: ", var, "");
03799     t1->addSharedTerm(var);
03800     t2->addSharedTerm(var);
03801   }
03802       }
03803     } else { // Record the descendants of var
03804       vector<Expr>& kids = d_varModelMap[var];
03805       for(size_t i=lastSize; i<stack.size(); ++i) {
03806   DebugAssert(stack[i] != var, "Primitive var was pushed on "
03807         "the stack in computeModelTerm(): "+var.toString());
03808   kids.push_back(stack[i]);
03809       }
03810       TRACE("model", "collectBasicVars: var="+var.toString()
03811       +" maps into vars=", Expr(RAW_LIST, kids, getEM()), "");
03812     }
03813   }
03814   TRACE_MSG("model", "collectBasicVars() => }");
03815 }
03816 
03817 bool TheoryCore::buildModel(Theorem& thm)
03818 {
03819   size_t numTheories = getNumTheories();
03820   // Use STL set to prune duplicate variables in theories
03821   vector<set<Expr> > theoryExprs(numTheories+1);
03822 
03823   // Sort out model vars by theories
03824   for(size_t j = 0 ; j<d_basicModelVars.size() ; j++) {
03825     const Expr& var = d_basicModelVars[j];
03826     Theorem findThm(find(var));
03827     if(findThm.getRHS()!=var) { // Replace var with its find and skip it
03828       TRACE("model", "buildModel: replace var="+var.toString(), " with find(var)=", findThm.getRHS());
03829       d_simplifiedModelVars[var] = findThm;
03830       continue;
03831     }
03832 
03833     Theory *th = theoryOf(getBaseType(var).getExpr().getKind());
03834     size_t i=0;
03835     for(; i<numTheories && d_theories[i] != th; ++i);
03836     DebugAssert(i<numTheories && d_theories[i] == th, "TheoryCore::buildModel: cannot find the theory [" +th->getName()+"] for the variable: " +var.toString());
03837     theoryExprs[i].insert(var);
03838     TRACE("model", "buildModel: adding ", var, " to theory "+d_theories[i]->getName());
03839   }
03840 
03841   // Build a model for the basic-type variables
03842   for(int i=0; i<getNumTheories(); i++) {
03843     if(theoryExprs[i].size() > 0) {
03844       TRACE("model", "computeModelBasic[", d_theories[i]->getName(), "] {");
03845       // Copy the corresponding variables into a vector
03846       vector<Expr> vars;
03847       vars.insert(vars.end(), theoryExprs[i].begin(), theoryExprs[i].end());
03848       d_theories[i]->computeModelBasic(vars);
03849       TRACE("model", "computeModelBasic[", d_theories[i]->getName(), "] => }");
03850       if(inconsistent()) {
03851         vector<Expr> assump;
03852         thm = inconsistentThm();
03853         return false;
03854       }
03855     }
03856   }
03857 
03858   return true;
03859 }
03860 
03861 
03862 void TheoryCore::buildModel(ExprMap<Expr>& m)
03863 {
03864   TRACE_MSG("model", "buildModel() {");
03865 
03866   size_t numTheories = getNumTheories();
03867   // Use STL set to prune duplicate variables in theories
03868   vector<set<Expr> > theoryExprs(numTheories+1);
03869   // Sort out model vars by theories
03870   for(size_t j = 0 ; j<d_basicModelVars.size() ; j++) {
03871     const Expr& var = d_basicModelVars[j];
03872     Theorem findThm(find(var));
03873     if(findThm.getRHS()!=var) { // Replace var with its find and skip it
03874       TRACE("model", "buildModel: replace var="+var.toString(),
03875       " with find(var)=", findThm.getRHS());
03876       d_simplifiedModelVars[var] = findThm;
03877       continue;
03878     }
03879 
03880     Theory *th = theoryOf(getBaseType(var).getExpr().getKind());
03881     size_t i=0;
03882     for(; i<numTheories && d_theories[i] != th; ++i);
03883     DebugAssert(i<numTheories && d_theories[i] == th,
03884     "TheoryCore::buildModel: cannot find the theory ["
03885     +th->getName()+"] for the variable: "
03886     +var.toString());
03887     theoryExprs[i].insert(var);
03888     TRACE("model", "buildModel: adding ", var,
03889     " to theory "+d_theories[i]->getName());
03890   }
03891   // Build a model for the basic-type variables
03892   for(int i=0; i<getNumTheories(); i++) {
03893     if(theoryExprs[i].size() > 0) {
03894       TRACE("model", "computeModelBasic[", d_theories[i]->getName(), "] {");
03895       // Copy the corresponding variables into a vector
03896       vector<Expr> vars;
03897       vars.insert(vars.end(), theoryExprs[i].begin(), theoryExprs[i].end());
03898       d_theories[i]->computeModelBasic(vars);
03899       TRACE("model", "computeModelBasic[", d_theories[i]->getName(), "] => }");
03900       if(inconsistent()) {
03901   vector<Expr> assump;
03902   inconsistentThm().getLeafAssumptions(assump);
03903   Expr a = Expr(RAW_LIST, assump, d_em);
03904   throw EvalException
03905     ("Model Creation failed in Theory["
03906      +d_theories[i]->getName()
03907      +"] due to the following assumptions:\n\n"
03908      +a.toString()
03909      +"\n\nYou might be using an incomplete logical fragment.");
03910       }
03911     }
03912   }
03913   // Recombine the values for the compound-type variables
03914   ExprHashMap<Theorem>::iterator k, kend=d_simplifiedModelVars.end();
03915   for(vector<Expr>::const_iterator i=d_vars.begin(), iend=d_vars.end(); i!=iend; ++i) {
03916     Expr var(*i);
03917     TRACE("model", "buildModel: recombining var=", var, "");
03918     k=d_simplifiedModelVars.find(var);
03919     Theorem simp; // Null by default
03920     if(k!=kend) { // This var is simplified
03921       simp = k->second;
03922       TRACE("model", "buildModel: simplified var="+var.toString()+" to ",
03923       simp.getRHS(), "");
03924       var = simp.getRHS();
03925     }
03926     collectModelValues(var, m);
03927     if(d_varAssignments.count(var) > 0) {
03928       if(!simp.isNull()) {
03929   Theorem thm(transitivityRule(simp, d_varAssignments[var]));
03930   assignValue(thm);
03931   DebugAssert(thm.getLHS() == *i, "");
03932   m[*i] = thm.getRHS();
03933       } else
03934   m[*i] = d_varAssignments[var].getRHS();
03935     }
03936 //     else if(simp.isNull())
03937 //       m[*i] = *i;
03938 //     else
03939 //       m[*i] = simp.getRHS();
03940   }
03941   TRACE_MSG("model", "buildModel => }");
03942 }
03943 
03944 
03945 // Recursively build a compound-type variable assignment for e
03946 /*! Not all theories may implement aggregation of compound values.  If
03947  *  a compound variable is not assigned by a theory, add the more
03948  *  primitive variable assignments to 'm'.
03949  *
03950  * Some variables may simplify to something else (simplifiedVars map).
03951  * INVARIANT: e is always simplified (it's not in simplifiedVars map).
03952  * Also, if v simplifies to e, and e is assigned, then v must be assigned.
03953  */
03954 void TheoryCore::collectModelValues(const Expr& e, ExprMap<Expr>& m)
03955 {
03956   TRACE("model", "collectModelValues(", e, ") {");
03957   if(d_varAssignments.count(e) > 0) {
03958     TRACE("model", "collectModelValues[cached] => ",
03959     d_varAssignments[e].getRHS(), " }");
03960     return; // Got it already
03961   }
03962   ExprHashMap<Theorem>::iterator k, kend=d_simplifiedModelVars.end();
03963   k=d_simplifiedModelVars.find(e);
03964   if(k!=kend) {
03965     const Theorem& findThm = k->second;
03966     const Expr& ee = findThm.getRHS();
03967     collectModelValues(ee, m);
03968     if(d_varAssignments.count(ee) > 0) {
03969       Theorem thm = transitivityRule(findThm, d_varAssignments[ee]);
03970       assignValue(thm);
03971     }
03972     TRACE("model", "collectModelValues[simplified] => ",
03973     d_varAssignments[e].getRHS(), " }");
03974     return;
03975   }
03976   if(d_varModelMap.count(e) == 0) { // Consider it a value of itself
03977     assignValue(reflexivityRule(e));
03978     TRACE("model", "collectModelValues[e=e] => ", e, " }");
03979     return; // Got it already
03980   }
03981   // Get the vector of more primitive vars
03982   const vector<Expr>& vars = d_varModelMap[e];
03983   // Recurse
03984   bool gotAll(true);  // Whether we got all the values
03985   for(vector<Expr>::const_iterator i=vars.begin(), iend=vars.end(); i!=iend; ++i) {
03986     Expr var(*i);
03987 //     k=d_simplifiedModelVars.find(var);
03988 //     Theorem simp; // Null by default
03989 //     if(k!=kend) { // This var is simplified
03990 //       simp = k->second;
03991 //       var = simp.getRHS();
03992 //     }
03993     collectModelValues(var, m);
03994     if(d_varAssignments.count(var) == 0) {
03995       gotAll = false;
03996     }
03997 //     else if(!simp.isNull()) {
03998 //       Theorem thm(transitivityRule(simp, d_varAssignments[var]));
03999 //       DebugAssert(thm.getLHS() == *i, "");
04000 //       assignValue(thm);
04001 //     }
04002   }
04003   IF_DEBUG(vector<Expr> res;)
04004   if(gotAll) {
04005     vector<Expr> assigned; // What DP actually assigns
04006     Theory* th = theoryOf(getBaseType(e).getExpr());
04007     TRACE("model", "computeModel["+th->getName()+"](", e, ") {");
04008     th->computeModel(e, assigned);
04009     TRACE("model", "computeModel["+th->getName()+"] => ",
04010     Expr(RAW_LIST, assigned, getEM()), " }");
04011     // Check if the assigned vars are different from e
04012     if(!(assigned.size()==1 && assigned[0]==e)) {
04013       //    if(d_varAssignments.count(e) == 0) {
04014       for(vector<Expr>::iterator i=assigned.begin(), iend=assigned.end();
04015     i!=iend; ++i) {
04016   if(*i == e) continue; // Skip the original var
04017   m[*i] = getModelValue(*i).getRHS();
04018   IF_DEBUG(res.push_back(getModelValue(*i).getExpr());)
04019       }
04020     } else {
04021       IF_DEBUG(res.push_back(getModelValue(e).getExpr());)
04022     }
04023   }
04024   TRACE("model", "collectModelValues => ",
04025   Expr(RAW_LIST, res, getEM()), " }");
04026 }
04027 
04028 
04029 Theorem TheoryCore::rewriteLiteral(const Expr& e) {
04030   DebugAssert(e.isAbsLiteral(), "rewriteLiteral("+e.toString()
04031         +")\nExpected a literal.");
04032   Theorem res;
04033   //Theory* i = theoryOf(getBaseType(e).getExpr());
04034   bool neg(e.isNot());
04035   const Expr a = neg? e[0] : e;
04036   Theory * i;
04037   if(a.isEq())
04038     i = theoryOf(getBaseType(a[0]).getExpr());
04039   else if (a.arity() > 1)
04040     i = theoryOf(getBaseType(a[0]).getExpr());
04041   else
04042     i = theoryOf(a);
04043   res = i->rewriteAtomic(a);
04044   if(neg) res = d_commonRules->iffContrapositive(res);
04045   return res;
04046 }
04047 
04048 
04049 
04050 
04051 
04052 
04053 void TheoryCore::setTimeLimit(unsigned limit) {
04054   initTimeLimit();
04055   d_timeLimit = limit;
04056 }
04057 
04058 void TheoryCore::initTimeLimit() {
04059   d_timeBase = clock() / (CLOCKS_PER_SEC / 10);
04060 }
04061 
04062 bool TheoryCore::timeLimitReached() {
04063   if (d_timeLimit > 0
04064       && d_timeLimit < (unsigned)(clock() / (CLOCKS_PER_SEC / 10)) - d_timeBase) {
04065     setIncomplete("Exhausted user-specified time limit");
04066     return true;
04067   } else {
04068     return false;
04069   }
04070 }
04071 
04072 
04073 
04074 /*****************************************************************************/
04075 /*
04076  * Methods provided for benefit of theories
04077  */
04078 /*****************************************************************************/
04079 
04080 
04081 /*!
04082  * Invariants:
04083  * - The input theorem e is either an equality or a conjunction of
04084  *   equalities;
04085  * - In each equality e1=e2, the RHS e2 i-leaf-simplified;
04086  * - At the time of calling update(), all equalities in the queue are
04087  *   processed by assertFormula() and the equivalence classes are merged
04088  *   in the union-find database.
04089  *
04090  * In other words, the entire equality queue is processed "in parallel".
04091  */
04092 
04093 void TheoryCore::assertEqualities(const Theorem& e)
04094 {
04095   IF_DEBUG(
04096     string indentStr(getCM()->scopeLevel(), ' ');
04097     TRACE("facts", indentStr, "assertEqualities: ", e);
04098     if (!incomplete()) d_solver->checkAssertEqInvariant(e);
04099   )
04100   TRACE("quant update", "equs in core ", e.getExpr(), "");
04101 
04102   // fast case
04103   if (e.isRewrite()) {
04104     const Expr& lhs = e.getLHS();
04105     const Expr& rhs = e.getRHS();
04106     DebugAssert(lhs.isTerm(), "term expected");
04107     DebugAssert(findReduced(lhs) &&
04108                 findReduced(rhs), "should be find-reduced");
04109     DebugAssert(lhs != rhs, "expected different lhs and rhs");
04110     assertFormula(e);
04111     lhs.setFind(e);
04112     Theorem tmp = lhs.getEqNext();
04113     lhs.setEqNext(transitivityRule(e, rhs.getEqNext()));
04114     rhs.setEqNext(transitivityRule(symmetryRule(e), tmp));
04115     d_em->invalidateSimpCache();
04116     NotifyList *L;
04117     L = lhs.getNotify();
04118     if (L) processNotify(e, L);
04119     processNotify(e, &d_notifyEq);
04120   }
04121   else if (e.getExpr().isFalse()) {
04122     setInconsistent(e);
04123   }
04124   else {
04125     Expr conj = e.getExpr();
04126     DebugAssert(conj.isAnd(), "Expected conjunction");
04127     vector<Theorem> eqs;
04128     Theorem t;
04129     int index;
04130 
04131     for (index = 0; index < conj.arity(); ++index) {
04132       t = d_commonRules->andElim(e, index);
04133       eqs.push_back(t);
04134       if (t.getExpr().isFalse()) {
04135         setInconsistent(t);
04136         return;
04137       }
04138       DebugAssert(t.isRewrite(), "Expected rewrite");
04139       DebugAssert(t.getLHS().isTerm(), "term expected");
04140       DebugAssert(findReduced(t.getLHS()) &&
04141                   findReduced(t.getRHS()), "should be find-reduced");
04142       assertFormula(t);
04143       if (d_inconsistent) return;
04144     }
04145 
04146     // Merge the equivalence classes
04147     vector<Theorem>::iterator i = eqs.begin(), iend = eqs.end();
04148     for(; i!=iend; ++i) {
04149       const Theorem& thm = *i;
04150       const Expr& lhs = thm.getLHS();
04151       const Expr& rhs = thm.getRHS();
04152       DebugAssert(find(lhs).getRHS() == lhs,
04153       "find error: thm = "+thm.getExpr().toString()
04154       +"\n\n  find(lhs) = "
04155       +find(lhs).getRHS().toString());
04156       DebugAssert(find(rhs).getRHS() == rhs,
04157       "find error: thm = "+thm.getExpr().toString()
04158       +"\n\n  find(rhs) = "
04159       +find(rhs).getRHS().toString());
04160       lhs.setFind(thm);
04161       Theorem tmp = lhs.getEqNext();
04162       lhs.setEqNext(transitivityRule(thm, rhs.getEqNext()));
04163       rhs.setEqNext(transitivityRule(symmetryRule(thm), tmp));
04164     }
04165 
04166     d_em->invalidateSimpCache();
04167 
04168     // Call the update() functions (process NotifyLists).
04169 
04170     for(i=eqs.begin(); i!=iend && !d_inconsistent; ++i) {
04171       const Theorem& thm = *i;
04172       NotifyList *L = thm.getLHS().getNotify();
04173       if (L) processNotify(thm, L);
04174       processNotify(thm, &d_notifyEq);
04175     }
04176   }
04177 }
04178 
04179 
04180 void TheoryCore::setIncomplete(const string& reason)
04181 {
04182   d_incomplete.insert(reason, true);
04183 }
04184 
04185 
04186 Theorem TheoryCore::typePred(const Expr& e)
04187 {
04188   return d_rules->typePred(e);
04189 }
04190 
04191 
04192 static bool hasBoundVarRec(const Expr& e)
04193 {
04194   if (e.getFlag()) return false;
04195   if (e.isQuantifier()) return false;
04196   if (e.getKind() == BOUND_VAR) return true;
04197   for (int i = 0, ar = e.arity(); i < ar; ++i) {
04198     if (hasBoundVarRec(e[i])) return true;
04199   }
04200   e.setFlag();
04201   return false;
04202 }
04203 
04204 IF_DEBUG(
04205 static bool hasBoundVar(const Expr& e)
04206 {
04207   e.getEM()->clearFlags();
04208   return hasBoundVarRec(e);
04209 }
04210 )
04211 
04212 
04213 void TheoryCore::enqueueFact(const Theorem& e)
04214 {
04215   // The theorem scope shouldn't be higher than current
04216   DebugAssert(e.getScope() <= d_cm->scopeLevel(),
04217         "\n e.getScope()="+int2string(e.getScope())
04218         +"\n scopeLevel="+int2string(d_cm->scopeLevel())
04219         +"\n e = "+e.getExpr().toString());
04220   DebugAssert(okToEnqueue(),
04221         "enqueueFact() is called outside of addFact()"
04222         " or checkSATCore() or registerAtom() or preprocess");
04223   DebugAssert((e.isRewrite() && !hasBoundVar(e.getLHS())
04224                && !hasBoundVar(e.getRHS())) ||
04225               (!e.isRewrite() && !hasBoundVar(e.getExpr())),
04226               "Bound vars shouldn't be free: " + e.toString());
04227 
04228   // No need to enqueue when already inconsistent or out of resources
04229   if (d_inconsistent || outOfResources()) return;
04230 
04231   if (!e.isRewrite() && e.getExpr().isFalse()) {
04232     setInconsistent(e);
04233   } else {
04234     getResource();
04235     d_queue.push(e);
04236     if (outOfResources()) {
04237       // No more resources: ignore all the remaining facts and fail
04238       // gracefully
04239       setIncomplete("Exhausted user-specified resource");
04240     }
04241   }
04242 }
04243 
04244 
04245 void TheoryCore::setInconsistent(const Theorem& e)
04246 {
04247   DebugAssert(e.getExpr() == falseExpr(), "Expected proof of false");
04248   d_inconsistent = true; d_incThm = e;
04249   //  if(!d_queueSE.empty()){
04250   //    cout<<"before SAT 1"<<endl;
04251   //  }
04252   d_queueSE.clear();
04253   // Theory 0 is TheoryCore, skip it
04254   for(unsigned i=1; i < d_theories.size(); ++i) {
04255     d_theories[i]->notifyInconsistent(e);
04256   }
04257 }
04258 
04259 
04260 void TheoryCore::setupTerm(const Expr& t, Theory* i, const Theorem& thm)
04261 {
04262   int k;
04263   // Atomic formulas (non-terms) may have find pointers without the
04264   // subterms being setup.  Recurse down to the terms before checking
04265   // for find pointers.
04266   if (!t.isTerm()) {
04267     if (!t.isStoredPredicate()) {
04268       DebugAssert(t.isAbsLiteral(), "Expected absliteral");
04269       for (k = 0; k < t.arity(); ++k) {
04270         setupTerm(t[k], i, thm);
04271       }
04272       t.setStoredPredicate();
04273       d_predicates.push_back(t);
04274       d_termTheorems[t] = thm;
04275       theoryOf(t)->setup(t);
04276       TRACE("quantlevel", "==========\npushed pred | ", t.getIndex(), "|" + t.toString()+"because : "+thm.toString() );
04277       TRACE("quant","pushed pred ",t,thm);
04278     }
04279     return;
04280   }
04281 
04282   // Even if t is already setup, it may become shared with another theory
04283   Theory* j = theoryOf(t);
04284   if(i != j) {
04285     j->addSharedTerm(t);
04286     i->addSharedTerm(t);
04287   }
04288 
04289   // If already setup, nothing else to do
04290   if (t.hasFind()) return;
04291 
04292   // Proceed with the setup
04293 
04294   // Add the term into the set of all terms
04295   d_terms.push_back(t);
04296   d_termTheorems[t] = thm;
04297   TRACE("quantlevel","=========\npushed term ("+t.toString(), ") with quantlevel: ", thm.getQuantLevel());
04298 
04299   for (k = 0; k < t.arity(); ++k) {
04300     setupTerm(t[k], j, thm);
04301   }
04302   t.setFind(reflexivityRule(t));
04303   t.setEqNext(reflexivityRule(t));
04304   j->setup(t);
04305 
04306   // Assert the subtyping predicate AFTER the setup is complete
04307   Theorem pred = d_rules->typePred(t);
04308   pred = iffMP(pred, simplify(pred.getExpr()));
04309   const Expr& predExpr = pred.getExpr();
04310   if(predExpr.isFalse()) {
04311     IF_DEBUG(debugger.counter("conflicts from type predicate")++;)
04312     setInconsistent(pred);
04313   }
04314   else if(!predExpr.isTrue()) {
04315     Theory* k = theoryOf(t.getType().getExpr());
04316     k->assertTypePred(t, pred);
04317   }
04318 }
04319 
04320 Expr TheoryCore::getAssignment() {
04321   vector<Expr> v;
04322   for(unsigned i = 0; i < d_assignment.size(); ++i) {
04323     Theorem res = d_exprTrans->preprocess(d_assignment[i].second);
04324     Theorem simpThm =  d_theoryCore->simplify(res.getRHS());
04325     vector<Expr> pr;
04326     pr.push_back(d_assignment[i].first);
04327     pr.push_back(simpThm.getRHS());
04328     v.push_back(Expr(RAW_LIST, pr, getEM()));
04329   }
04330   return Expr(RAW_LIST, v, getEM());
04331 }
04332 
04333 Expr TheoryCore::getValue(Expr e) {
04334   Theorem res = d_exprTrans->preprocess(e);
04335   Theorem simpThm =  d_theoryCore->simplify(res.getRHS());
04336   return simpThm.getRHS();
04337 }
04338