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  * Copyright (C) 2003 by the Board of Trustees of Leland Stanford
00011  * Junior University and by New York University. 
00012  *
00013  * License to use, copy, modify, sell and/or distribute this software
00014  * and its documentation for any purpose is hereby granted without
00015  * royalty, subject to the terms and conditions defined in the \ref
00016  * LICENSE file provided with this distribution.  In particular:
00017  *
00018  * - The above copyright notice and this permission notice must appear
00019  * in all copies of the software and related documentation.
00020  *
00021  * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
00022  * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
00023  * 
00024  * <hr>
00025  * 
00026  */
00027 /*****************************************************************************/
00028 
00029 
00030 #include "command_line_flags.h"
00031 #include "expr.h"
00032 #include "notifylist.h"
00033 #include "pretty_printer.h"
00034 #include "common_proof_rules.h"
00035 #include "parser_exception.h"
00036 #include "typecheck_exception.h"
00037 #include "smtlib_exception.h"
00038 #include "eval_exception.h"
00039 #include "theory_core.h"
00040 #include "expr_transform.h"
00041 #include "core_proof_rules.h"
00042 #include "theorem_manager.h"
00043 
00044 
00045 using namespace std;
00046 
00047 
00048 namespace CVCL {
00049 
00050 
00051   //! Implementation of PrettyPrinter class
00052   /*! \ingroup PrettyPrinting */
00053   class PrettyPrinterCore: public PrettyPrinter {
00054   private:
00055     TheoryCore *d_core;
00056     //! Disable the default constructor
00057     PrettyPrinterCore() { }
00058   public:
00059     //! Constructor
00060     PrettyPrinterCore(TheoryCore* core): d_core(core) { }
00061     ExprStream& print(ExprStream& os, const Expr& e) {
00062       if(e.isString())
00063         return e.print(os);
00064       else if (e.isApply())
00065         return d_core->theoryOf(e)->print(os, e);
00066       else if(d_core->hasTheory(e.getKind()))
00067         return d_core->theoryOf(e.getKind())->print(os, e);
00068       else
00069         return e.print(os);
00070     }
00071   };
00072 
00073 
00074   class TypeComputerCore: public ExprManager::TypeComputer {
00075     TheoryCore *d_core;
00076   public:
00077     TypeComputerCore(TheoryCore* core): d_core(core) { }
00078     void computeType(const Expr& e) {
00079       DebugAssert(!e.isVar(), "Variables should have a type: "+e.toString());
00080       Theory* i = d_core->theoryOf(e.getKind());
00081       if (e.isApply()) i = d_core->theoryOf(e);
00082       TRACE("types", "computeType["+i->getName()+"](", e, ") {");
00083       TRACE("types verbose", "kind = ", d_core->getEM()->getKindName(e.getKind()), "");
00084       i->computeType(e);
00085       DebugAssert(!e.lookupType().getExpr().isNull(), "Type not set by computeType");
00086       TRACE("types", "computeType["+i->getName()+"] => ", e.getType(), " }");
00087     }
00088     void checkType(const Expr& e) {
00089       if (!e.isType()) throw Exception
00090           ("Tried to use non-type as a type: "+e.toString());
00091       d_core->theoryOf(e)->checkType(e);
00092       e.setValidType();
00093     }
00094   };
00095 
00096 
00097   ostream& operator<<(ostream& os, const NotifyList& l) {
00098     os << "NotifyList(\n";
00099     for(size_t i=0,iend=l.size(); i<iend; ++i) {
00100       os << "[" << l.getTheory(i)->getName() << ", " << l.getExpr(i) << "]\n";
00101     }
00102     return os << ")";
00103   }
00104 
00105 
00106 }
00107 
00108 
00109 using namespace CVCL;
00110 
00111 
00112 // File-static helper functions
00113 
00114 IF_DEBUG(
00115 //! Check if the vector<Expr> is sorted w.r.t. operator<
00116 static bool isSorted(const vector<Expr>& v) {
00117   Expr prev;
00118   for(vector<Expr>::const_iterator i=v.begin(), iend=v.end(); i!=iend;
00119       prev = *i, ++i) {
00120     if(prev.isNull()) continue;
00121     if(!(prev < *i)) return false;
00122   }
00123   return true;
00124 }
00125 )
00126 
00127 //! Intersection of sorted vectors of Exprs: res := \f$a \cap b\f$
00128 /*! ASSUMPTION: a and b are sorted in ascending order w.r.t. operator<
00129  */
00130 static void intersect(const vector<Expr>& a, const vector<Expr>& b,
00131                vector<Expr>& res) {
00132   DebugAssert(isSorted(a) && isSorted(b), "intersect()");
00133   size_t i(0), j(0), iend(a.size()), jend(b.size());
00134   while(i<iend && j<jend) {
00135     if(a[i] == b[j]) {
00136       res.push_back(a[i]);
00137       i++; j++;
00138     } else if(a[i] < b[j]) i++;
00139     else j++; // a[i] > b[j]
00140   }
00141 }
00142 
00143 //! Set difference of sorted vectors of Exprs: res := a - b
00144 /*! ASSUMPTION: a and b are sorted in ascending order w.r.t. operator<
00145  */
00146 static void difference(const vector<Expr>& a, const vector<Expr>& b,
00147                 vector<Expr>& res) {
00148   DebugAssert(isSorted(a) && isSorted(b), "difference()");
00149   size_t i(0), j(0), iend(a.size()), jend(b.size());
00150   while(i < iend) {
00151     if(j >= jend) { res.push_back(a[i]); i++; }
00152     else if(a[i]==b[j]) { i++; j++; }
00153     else if(a[i]<b[j]) { res.push_back(a[i]); i++; }
00154     else j++; // a[i] > b[j]
00155   }
00156 }
00157 
00158 void
00159 TheoryCore::enqueueSE(const Theorem& thm) {
00160   TRACE("enqueueSE", "enqueueSE(", thm.getExpr(), ")");
00161   DebugAssert(d_inAddFact || d_inCheckSATCore || d_inRegisterAtom, "enqueueSE()");
00162   if(thm.isRewrite() || !thm.getExpr().isTrue())
00163     d_queueSE.push_back(thm);
00164 }
00165 
00166 
00167 Theorem TheoryCore::getModelValue(const Expr& e) {
00168   ExprHashMap<Theorem>::iterator i=d_varAssignments.find(e),
00169     iend=d_varAssignments.end();
00170   if(i!=iend) return (*i).second;
00171   else return find(e);
00172 }
00173 
00174 
00175 ///////////////////////////////////////////////////////////////////////////////
00176 /*!
00177  * Function: TheoryCore::TheoryCore
00178  *
00179  * Author: Clark Barrett
00180  * 
00181  * Created: Sat Feb  8 14:57:36 2003
00182  *
00183  * Description: Constructor.  Since we are in the middle of creating
00184  * TheoryCore, we set the pointer to TheoryCore in the Theory base
00185  * class ourselves.
00186 */
00187 ///////////////////////////////////////////////////////////////////////////////
00188 TheoryCore::TheoryCore(ContextManager* cm,
00189                        ExprManager* em,
00190                        TheoremManager* tm,
00191                        const CLFlags& flags,
00192                        Statistics& statistics)
00193   : Theory(), d_cm(cm), d_tm(tm), d_flags(flags), d_statistics(statistics),
00194     d_inconsistent(cm->getCurrentContext(), false, 0), 
00195     d_incomplete(cm->getCurrentContext()),
00196     d_diseq(cm->getCurrentContext()),
00197     d_incThm(cm->getCurrentContext()),
00198     d_terms(cm->getCurrentContext()),
00199     d_vars(cm->getCurrentContext()),
00200     d_sharedTerms(cm->getCurrentContext()),
00201     d_solver(NULL),
00202     d_simplifyInPlace(&(flags["ip"].getBool())),
00203     d_currentRecursiveSimplifier(NULL),
00204     d_cnfOption(&(flags["cnf"].getBool())),
00205     d_resourceLimit(0),
00206 #ifdef DEBUG
00207     d_dumpTrace(&(flags["dump-trace"].getString())),
00208     d_inCheckSATCore(false), d_inAddFact(false), d_inSimplify(false),
00209     d_inRegisterAtom(false),
00210 #endif
00211     d_notifyObj(this, cm->getCurrentContext()),
00212     d_impliedLiterals(cm->getCurrentContext()),
00213     d_impliedLiteralsIdx(cm->getCurrentContext(), 0, 0),
00214     d_coreSatAPI(NULL)
00215 {
00216   IF_DEBUG(d_diseq.setName("CDList[TheoryCore::d_diseq]"));
00217   d_em = em;
00218   d_theoryCore = this;
00219   d_commonRules = tm->getRules();
00220   d_name = "Core";
00221   d_theoryUsed = false;
00222 
00223   d_rules = createProofRules(tm);
00224   d_printer = new PrettyPrinterCore(this);
00225   d_typeComputer = new TypeComputerCore(this);
00226   d_em->registerTypeComputer(d_typeComputer);
00227   d_exprTrans = new ExprTransform(this);
00228 
00229   // Register the pretty-printer
00230   d_em->registerPrettyPrinter(*d_printer);
00231 
00232   // for (int i = 0; i < LAST_KIND; ++i) d_theoryMap[i] = NULL;
00233 
00234   vector<int> kinds;
00235   kinds.push_back(RAW_LIST);
00236   kinds.push_back(BOOLEAN);
00237   kinds.push_back(SUBTYPE);
00238   kinds.push_back(STRING_EXPR);
00239   kinds.push_back(ID);
00240   kinds.push_back(TRUE);
00241   kinds.push_back(FALSE);
00242   kinds.push_back(UCONST);
00243   kinds.push_back(BOUND_VAR);
00244   kinds.push_back(SKOLEM_VAR);
00245   kinds.push_back(EQ);
00246   kinds.push_back(NEQ);
00247   kinds.push_back(ECHO);
00248   kinds.push_back(DBG);
00249   kinds.push_back(TRACE);
00250   kinds.push_back(UNTRACE);
00251   kinds.push_back(OPTION);
00252   kinds.push_back(HELP);
00253   kinds.push_back(AND);
00254   kinds.push_back(OR);
00255   kinds.push_back(IFTHEN);
00256   kinds.push_back(IF);
00257   kinds.push_back(ELSE);
00258   kinds.push_back(COND);
00259   kinds.push_back(XOR);
00260   kinds.push_back(NOT);
00261   kinds.push_back(ITE);
00262   kinds.push_back(IFF);
00263   kinds.push_back(IMPLIES);
00264   kinds.push_back(APPLY);
00265   // For printing LET expressions (in DAG printing mode)
00266   kinds.push_back(LET);
00267   kinds.push_back(LETDECLS);
00268   kinds.push_back(LETDECL);
00269   // For printing raw parsed quantifier expressions
00270   kinds.push_back(VARLIST);
00271   kinds.push_back(VARDECLS);
00272   kinds.push_back(VARDECL);
00273 
00274   // Type declarations and definitions
00275   kinds.push_back(TYPE);
00276   // For printing type declarations (or definitions)
00277   kinds.push_back(CONST);
00278 
00279   kinds.push_back(CONSTDEF);
00280   kinds.push_back(TYPEDEF);
00281   kinds.push_back(DEFUN);
00282   // Printing proofs
00283   kinds.push_back(PF_APPLY);
00284   kinds.push_back(PF_HOLE);
00285   // Register commands for pretty-printing.  Currently, only ASSERT
00286   // needs to be printed.
00287   kinds.push_back(ASSERT);
00288   kinds.push_back(QUERY);
00289   kinds.push_back(PRINT);
00290 
00291   kinds.push_back(DUMP_PROOF);
00292   kinds.push_back(DUMP_ASSUMPTIONS);
00293   kinds.push_back(DUMP_SIG);
00294   kinds.push_back(DUMP_TCC);
00295   kinds.push_back(DUMP_TCC_ASSUMPTIONS);
00296   kinds.push_back(DUMP_TCC_PROOF);
00297   kinds.push_back(DUMP_CLOSURE);
00298   kinds.push_back(DUMP_CLOSURE_PROOF);
00299   kinds.push_back(TRANSFORM);
00300   kinds.push_back(CALL);
00301   kinds.push_back(WHERE);
00302   kinds.push_back(ASSERTIONS);
00303   kinds.push_back(ASSUMPTIONS);
00304   kinds.push_back(COUNTEREXAMPLE);
00305   kinds.push_back(COUNTERMODEL);
00306   kinds.push_back(PUSH);
00307   kinds.push_back(POP);
00308   kinds.push_back(POPTO);
00309   kinds.push_back(PUSH_SCOPE);
00310   kinds.push_back(POP_SCOPE);
00311   kinds.push_back(POPTO_SCOPE);
00312   kinds.push_back(CONTEXT);
00313   kinds.push_back(FORGET);
00314   kinds.push_back(GET_TYPE);
00315   kinds.push_back(CHECK_TYPE);
00316   kinds.push_back(GET_CHILD);
00317   kinds.push_back(SUBSTITUTE);
00318   kinds.push_back(SEQ);
00319 
00320   
00321   kinds.push_back(AND_R);
00322   kinds.push_back(IFF_R);
00323   kinds.push_back(ITE_R);
00324 
00325   registerTheory(this, kinds);
00326 }
00327 
00328 
00329 TheoryCore::~TheoryCore()
00330 {
00331   delete d_exprTrans;
00332   delete d_rules;
00333   delete d_typeComputer;
00334   d_em->unregisterPrettyPrinter();
00335   delete d_printer;
00336 }
00337 
00338 
00339 ///////////////////////////////////////////////////////////////////////////////
00340 // Theory interface implementaion                                            //
00341 ///////////////////////////////////////////////////////////////////////////////
00342 
00343 void TheoryCore::assertFact(const Theorem& e) {
00344   DebugAssert(e.getExpr().unnegate().getKind() == SKOLEM_VAR ||
00345               e.getExpr().unnegate().getKind() == UCONST,
00346               "TheoryCore::assertFact("+e.toString()+")");
00347 }
00348 
00349 
00350 void TheoryCore::checkSat(bool fullEffort) {
00351   // Handle all asserted disequalities
00352   for (CDList<Theorem>::const_iterator i = d_diseq.begin(), iend=d_diseq.end();
00353        i!=iend; ++i) {
00354     const Expr& expr = ((*i).getExpr())[0];
00355     Theorem thm0 = find(expr[0]);
00356     Theorem thm1 = find(expr[1]);
00357     if (thm0.getRHS() == thm1.getRHS()) {
00358       Theorem leftEqRight = transitivityRule(thm0, symmetryRule(thm1));
00359       IF_DEBUG(debugger.counter("conflicts from disequalities")++);
00360       setInconsistent(iffMP(leftEqRight, d_commonRules->notToIff(*i)));
00361       return;
00362     }
00363   }
00364 }
00365 
00366 
00367 Theorem TheoryCore::rewriteLitCore(const Expr& e)
00368 {
00369   switch (e.getKind()) {
00370     case EQ:
00371       if (e[0] == e[1])
00372         return d_commonRules->rewriteReflexivity(e);
00373       else if (e[0] < e[1])
00374         return d_commonRules->rewriteUsingSymmetry(e);
00375       break;
00376     case NOT:
00377       if (e[0].isTrue())
00378         return d_commonRules->rewriteNotTrue(e);
00379       else if (e[0].isFalse())
00380         return d_commonRules->rewriteNotFalse(e);
00381       else if (e[0].isNot())
00382         return d_commonRules->rewriteNotNot(e);
00383       break;
00384     default:
00385       DebugAssert(false,
00386                   "TheoryCore::rewriteLitCore("
00387                   + e.toString()
00388                   + "): Not implemented");
00389       break;
00390   }
00391   return reflexivityRule(e);
00392 }
00393 
00394 
00395 Theorem TheoryCore::rewriteN(const Expr& e, int n) {
00396   if(n <= 0) return reflexivityRule(e);
00397   if(theoryOf(e) != this) return reflexivityRule(e);
00398   if(n==1) return rewrite(e);
00399   vector<Theorem> thms;
00400   vector<unsigned> changed;
00401   for(int i=0; i<e.arity(); ++i) {
00402     Theorem thm = rewriteN(e[i], n-1);
00403     if(e[i] != thm.getRHS()) {
00404       thms.push_back(thm);
00405       changed.push_back(i);
00406     }
00407   }
00408   Theorem res;
00409   if(changed.size()>0) {
00410     res = substitutivityRule(e, changed, thms);
00411     res = transitivityRule(res, rewrite(res.getRHS()));
00412   } else {
00413     res = rewrite(e);
00414   }
00415   return res;
00416 }
00417 
00418 
00419 Theorem TheoryCore::rewrite(const Expr& e) {
00420   TRACE("core rewrite", "TheoryCore::rewrite(", e, ") {");
00421   Theorem thm;
00422   switch (e.getKind()) {
00423     case TRUE:
00424     case FALSE:
00425     case UCONST:
00426     case BOUND_VAR:
00427     case SKOLEM_VAR:
00428       thm = reflexivityRule(e);
00429       break; // do not rewrite
00430     case LETDECL:
00431       // Replace LETDECL and CONSTDEF with their definitions.  The
00432       // typechecker makes sure it's type-safe to do so.
00433       thm = d_rules->rewriteLetDecl(e);
00434       break;
00435     case CONSTDEF:
00436       thm = d_rules->rewriteConstDef(e);
00437       break;
00438     case EQ:
00439     case NOT:
00440       thm = rewriteLitCore(e);
00441       break;
00442     case IMPLIES: {
00443       thm = d_rules->rewriteImplies(e);
00444       const Expr& rhs = thm.getRHS();
00445       // rhs = OR(!e1, e2).  Rewrite !e1, then top-level OR().
00446       DebugAssert(rhs.isOr() && rhs.arity() == 2,
00447                   "TheoryCore::rewrite[IMPLIES]: rhs = "+rhs.toString());
00448       Theorem rw = rewriteCore(rhs[0]);
00449       if(rw.getLHS() != rw.getRHS()) {
00450         vector<unsigned> changed;
00451         vector<Theorem> thms;
00452         changed.push_back(0);
00453         thms.push_back(rw);
00454         rw = substitutivityRule(rhs, changed, thms);
00455         // Simplify to the find pointer of the result
00456         rw = transitivityRule(rw, find(rw.getRHS()));
00457         // Now rw = Theorem(rhs = rhs')
00458         rw = transitivityRule(rw, rewrite(rw.getRHS()));
00459       } else
00460         rw = rewrite(rhs);
00461       thm = transitivityRule(thm, rw);
00462       //       thm = transitivityRule(thm, simplify(thm.getRHS()));
00463       break;
00464     }
00465     case IFF: {
00466       thm = d_commonRules->rewriteIff(e);
00467       const Expr& e1 = thm.getRHS();
00468       // The only time we need to rewrite the result (e1) is when
00469       // e==(FALSE<=>e[1]) or (e[1]<=>FALSE), so e1==!e[1].
00470       if (e != e1 && e1.isNot())
00471         thm = transitivityRule(thm, rewriteCore(e1));
00472       else if(e1.isIff()) {
00473         TRACE_MSG("core rewrite",
00474                   "rewrite[Core]: checking for (a|b)<=>(a|c)...");
00475         // Check for OR or AND-factoring:
00476         // ((a|b)<=>(a|c))<=>(a|(b<=>c))
00477         // ((a&b)<=>(a&c))<=>(!a | (b<=>c))
00478         vector<Expr> lhs, rhs, av;
00479         int kind(NULL_KIND);
00480         Op op(NULL_KIND);
00481         if ((e1[0].isOr() || e1[0].isAnd()) && e1[0].arity() > 0) {
00482           kind = e1[0].getKind();
00483           op = e1[0].getOp();
00484         }
00485         if (kind==NULL_KIND && (e1[1].isOr() || e1[1].isAnd()) &&
00486             e1[1].arity() > 0) {
00487           kind = e1[1].getKind();
00488           op = e1[1].getOp();
00489         }
00490         if(kind==NULL_KIND) break; // Nothing to do
00491         // Keep matching for the and/or/iff distributivity rules
00492         if(e1[0].getKind()==kind) lhs=e1[0].getKids();
00493         else lhs.push_back(e1[0]);
00494         if(e1[1].getKind()==kind) rhs=e1[1].getKids();
00495         else rhs.push_back(e1[1]);
00496         TRACE("core rewrite", "lhs = ", Expr(RAW_LIST, lhs, d_em), "");
00497         TRACE("core rewrite", "rhs = ", Expr(RAW_LIST, rhs, d_em), "");
00498         intersect(lhs, rhs, av);
00499         TRACE("core rewrite", "intersect(lhs,rhs) = ",
00500               Expr(RAW_LIST, av, d_em), "");
00501         if(av.size()>0) {
00502           vector<Expr> bv, cv;
00503           difference(lhs, av, bv);
00504           difference(rhs, av, cv);
00505           TRACE("core rewrite", "bv = ", Expr(RAW_LIST, bv, d_em), "");
00506           TRACE("core rewrite", "cv = ", Expr(RAW_LIST, cv, d_em), "");
00507           Expr empty((kind==AND)? d_em->trueExpr() : d_em->falseExpr());
00508           Expr a((av.size()==1)? av[0] : Expr(op, av));
00509           Expr b((bv.size()==0)? empty : (bv.size()==1)? bv[0]
00510                  : Expr(op, bv));
00511           Expr c((cv.size()==0)? empty :(cv.size()==1)? cv[0]
00512                  : Expr(op, cv));
00513           TRACE("core rewrite", "a = ", a, "");
00514           TRACE("core rewrite", "b = ", b, "");
00515           TRACE("core rewrite", "c = ", c, "");
00516           // Convert e1 to the "normal" form (a|b)<=>(a|c)
00517           vector<Theorem> thms;
00518           vector<unsigned> changed;
00519           Theorem t = rewrite(Expr(op, a, b));
00520           if(t.getLHS() != t.getRHS()) {
00521             thms.push_back(symmetryRule(t));
00522             changed.push_back(0);
00523           }
00524           t = rewrite(Expr(op, a, c));
00525           if(t.getLHS() != t.getRHS()) {
00526             thms.push_back(symmetryRule(t));
00527             changed.push_back(1);
00528           }
00529           if(changed.size()>0) {
00530             t = substitutivityRule(e1, changed, thms);
00531             thm = transitivityRule(thm, t);
00532           }
00533           TRACE("core rewrite", "normalize => ", thm.getRHS(), "");
00534           thms.clear();
00535           changed.clear();
00536           if(kind==OR)
00537             t =  d_rules->iffOrDistrib(thm.getRHS());
00538           else
00539             t =  d_rules->iffAndDistrib(thm.getRHS());
00540           thm = transitivityRule(thm, t);
00541           TRACE("core rewrite", "iffOrDistrib => ", thm.getRHS(), "");
00542           // Rewrite !a when the kind is AND
00543           if(kind==AND) {
00544             t = simplifyRec(!a); // Push negation all the way down
00545           } else { // otherwise just rewrite 'a'
00546             t = rewriteCore(a);
00547           }
00548           if(t.getLHS() != t.getRHS()) {
00549             thms.push_back(t);
00550             changed.push_back(0);
00551           }
00552           // Rewrite (b<=>c) 2 levels deep (i.e. rewrite b and c)
00553           t = rewriteN(b.iffExpr(c), 2);
00554           if(t.getLHS() != t.getRHS()) {
00555             // If b is FALSE, we get NOT c (resp. NOT b when c is
00556             // FALSE).  In this case, we should re-simplify the result
00557             // to push the negation down.
00558             if(t.getRHS().isNot())
00559               t = transitivityRule(t, simplifyRec(t.getRHS()));
00560             thms.push_back(t);
00561             changed.push_back(1);
00562           }
00563           if(changed.size()>0) {
00564             t = substitutivityRule(thm.getRHS(), changed, thms);
00565             thm = transitivityRule(thm, t);
00566           }
00567           // Finally, rewrite the new top-level OR
00568           thm = transitivityRule(thm, rewrite(thm.getRHS()));
00569         }
00570       }
00571       break;
00572     }
00573     case ITE:
00574       if (e[0].isTrue())
00575         thm = d_rules->rewriteIteTrue(e);
00576       else if (e[0].isFalse())
00577         thm = d_rules->rewriteIteFalse(e);
00578       else if (e[1] == e[2])
00579         thm = d_rules->rewriteIteSame(e);
00580       else if (getFlags()["un-ite-ify"].getBool()) {
00581         // undo the rewriting of Boolean connectives to ITEs.
00582         // helpful for examples converted from SVC.
00583         // must rewrite again because we might create expressions
00584         // that can be further rewritten, and we must normalize.
00585         if (e[1].isFalse() && e[2].isTrue())
00586           thm = rewriteCore(d_rules->rewriteIteToNot(e));
00587         else if (e[1].isTrue())
00588           thm = rewriteCore(d_rules->rewriteIteToOr(e));
00589         else if (e[2].isFalse())
00590           thm = rewriteCore(d_rules->rewriteIteToAnd(e));
00591         else if (e[2].isTrue())
00592           thm = rewriteCore(d_rules->rewriteIteToImp(e));
00593         else if (e[1] == e[2].negate())
00594           thm = rewriteCore(d_rules->rewriteIteToIff(e));
00595         else thm = reflexivityRule(e);
00596       }
00597       else if(getFlags()["ite-cond-simp"].getBool()) {
00598         thm = d_rules->rewriteIteCond(e);
00599         if(e != thm.getRHS())
00600           thm = transitivityRule(thm, simplifyRec(thm.getRHS()));
00601       }
00602       else thm = reflexivityRule(e);    
00603       break;
00604     case AND: {
00605       thm = rewriteAnd(e);
00606       const Expr ee = thm.getRHS();
00607     
00608       //stop further processing if ee is not an AND expr
00609       if(!ee.isAnd()) break;
00610 
00611       TRACE("core rewrite", "rewrite[Core]: checking for (a|b) & (a|c) in ",
00612             ee, "");
00613       
00614       //store the common factor of the OR kids of ee in setIntersect
00615       std::vector<Expr> setIntersect;
00616       //discover the common factor from the OR kids of the AND
00617       if(ee[0].isOr())
00618         setIntersect = ee[0].getKids();
00619       else
00620         setIntersect.push_back(ee[0]);
00621       TRACE("core rewrite", "setIntersect = ",
00622             Expr(RAW_LIST, setIntersect, d_em), "");
00623       for(Expr::iterator i=ee.begin(),iend=ee.end();
00624           i!=iend && !setIntersect.empty();++i) {
00625         vector<Expr> Ai, result;
00626         //isolate the ith kid of the expr ee
00627         if(i->isOr())
00628           Ai = i->getKids();
00629         else
00630           Ai.push_back(*i);
00631         TRACE("core rewrite", "Ai = ", Expr(RAW_LIST, Ai, d_em), "");
00632         //compute the intersection of all Ai's of ee, iteratively
00633         intersect(setIntersect,Ai,result);
00634         setIntersect = result;
00635         TRACE("core rewrite", "setIntersect = ",
00636               Expr(RAW_LIST, setIntersect, d_em), "");
00637       }
00638       //if setIntersect is empty exit this processing and return 'thm' as is
00639       if(setIntersect.empty()) break;
00640 
00641       Expr A = orExpr(setIntersect);
00642       TRACE("core rewrite", "A = ", A, "");
00643       //compute the unique fractor of each AND kid of the OR    
00644       vector<Theorem> substThms;
00645       vector<unsigned> changed;
00646       int j(0);
00647       for(Expr::iterator i=ee.begin(),iend=ee.end();i!=iend; ++i, ++j) {
00648         vector<Expr> Ai, setDiff;
00649         //isolate the ith kid of the input expr ee
00650         if(i->isOr())
00651           Ai = i->getKids();
00652         else
00653           Ai.push_back(*i);
00654         TRACE("core rewrite", "Ai = ", Expr(RAW_LIST, Ai, d_em), "");
00655         //compute (Ai - setIntersect) and return value in 'setDiff'
00656         difference(Ai,setIntersect,setDiff);  
00657         TRACE("core rewrite", "setDiff = ",
00658               Expr(RAW_LIST, setDiff, d_em), "");
00659         Expr Bi = (setDiff.empty())? d_em->falseExpr()
00660           : (setDiff.size()==1)? setDiff[0] : orExpr(setDiff);
00661         //iKid is A | Bi
00662         Expr iKid = A.orExpr(Bi);
00663         TRACE("core rewrite", "Bi = ", Bi, "");
00664         TRACE("core rewrite", "iKid = ", iKid, "");
00665         // Ai <=> A | Bi
00666         Theorem thm0 = symmetryRule(rewriteOr(iKid));
00667         TRACE("core rewrite", "rewriteOr(iKid) = ", thm0.getLHS(), "");
00668         if(thm0.getLHS() != thm0.getRHS()) {
00669           DebugAssert(thm0.getLHS() == ee[j],
00670                       "ee["+int2string(j)+"]="+ee[j].toString()
00671                       +"\n thm0 = "+thm0.getExpr().toString());
00672           substThms.push_back(thm0);
00673           changed.push_back(j);
00674         }
00675       }
00676       Theorem t = substitutivityRule(ee, changed, substThms);
00677       thm = transitivityRule(thm, t);
00678       t = d_rules->andDistributivityRule(thm.getRHS());
00679       thm = transitivityRule(thm, t);
00680       DebugAssert(thm.getRHS().isOr() && thm.getRHS().arity()==2,
00681                   "TheoryCore::rewrite[AND over OR]: thm = "
00682                   +thm.getExpr().toString());
00683       t = rewrite(thm.getRHS()[0]);
00684       substThms.clear();
00685       changed.clear();
00686       if(t.getLHS() != t.getRHS()) {
00687         substThms.push_back(t);
00688         changed.push_back(0);
00689       }
00690       t = rewriteN(thm.getRHS()[1], 2);
00691       if(t.getLHS() != t.getRHS()) {
00692         substThms.push_back(t);
00693         changed.push_back(1);
00694       }
00695       if(changed.size()>0) {
00696         t = substitutivityRule(thm.getRHS(), changed, substThms);
00697         thm = transitivityRule(thm, t);
00698       }
00699       t = rewriteOr(thm.getRHS());
00700       thm = transitivityRule(thm, t);
00701       break;
00702     }
00703     case OR: {
00704       thm = rewriteOr(e);
00705       const Expr ee = thm.getRHS();
00706     
00707       //stop further processing if ee is not an OR expr
00708       if(!ee.isOr()) break;
00709       
00710       TRACE("core rewrite", "rewrite[Core]: checking for (a&b) | (a&c) in ",
00711             ee, "");
00712       
00713       //store the common factor of the AND kids of ee in setIntersect
00714       std::vector<Expr> setIntersect;
00715       //discover the common factor from the AND kids of the OR
00716       if(ee[0].isAnd())
00717         setIntersect = ee[0].getKids();
00718       else
00719         setIntersect.push_back(ee[0]);
00720       TRACE("core rewrite", "setIntersect = ",
00721             Expr(RAW_LIST, setIntersect, d_em), "");
00722       for(Expr::iterator i=ee.begin(),iend=ee.end();
00723           i!=iend && !setIntersect.empty();++i) {
00724         vector<Expr> Ai, result;
00725         //isolate the ith kid of the expr ee
00726         if(i->isAnd())
00727           Ai = i->getKids();
00728         else
00729           Ai.push_back(*i);
00730         TRACE("core rewrite", "Ai = ", Expr(RAW_LIST, Ai, d_em), "");
00731         //compute the intersection of all Ai's of ee, iteratively
00732         intersect(setIntersect,Ai,result);
00733         setIntersect = result;
00734         TRACE("core rewrite", "setIntersect = ",
00735               Expr(RAW_LIST, setIntersect, d_em), "");
00736       }
00737       //if setIntersect is empty exit this processing and return 'thm' as is
00738       if(setIntersect.empty()) break;
00739 
00740       Expr A = andExpr(setIntersect);
00741       TRACE("core rewrite", "A = ", A, "");
00742       //compute the unique fractor of each AND kid of the OR    
00743       vector<Theorem> substThms;
00744       vector<unsigned> changed;
00745       int j(0);
00746       for(Expr::iterator i=ee.begin(),iend=ee.end();i!=iend; ++i, ++j) {
00747         vector<Expr> Ai, setDiff;
00748         //isolate the ith kid of the input expr ee
00749         if(i->isAnd())
00750           Ai = i->getKids();
00751         else
00752           Ai.push_back(*i);
00753         TRACE("core rewrite", "Ai = ", Expr(RAW_LIST, Ai, d_em), "");
00754         //compute (Ai - setIntersect) and return value in 'setDiff'
00755         difference(Ai,setIntersect,setDiff);  
00756         TRACE("core rewrite", "setDiff = ",
00757               Expr(RAW_LIST, setDiff, d_em), "");
00758         Expr Bi = (setDiff.empty())? d_em->trueExpr()
00759           : (setDiff.size()==1)? setDiff[0] : andExpr(setDiff);
00760         //iKid is A & Bi
00761         Expr iKid = A.andExpr(Bi);
00762         TRACE("core rewrite", "Bi = ", Bi, "");
00763         TRACE("core rewrite", "iKid = ", iKid, "");
00764         // Ai <=> A & Bi
00765         Theorem thm0 = symmetryRule(rewriteAnd(iKid));
00766         //thm0 is Ai <=> A & Bi
00767         if(thm0.getLHS() != thm0.getRHS()) {
00768           substThms.push_back(thm0);
00769           changed.push_back(j);
00770         }
00771       }
00772       Theorem t = substitutivityRule(ee, changed, substThms);
00773       thm = transitivityRule(thm, t);
00774       t = d_rules->orDistributivityRule(thm.getRHS());
00775       thm = transitivityRule(thm, t);
00776       DebugAssert(thm.getRHS().isAnd() && thm.getRHS().arity()==2,
00777                   "TheoryCore::rewrite[OR over AND]: thm = "
00778                   +thm.getExpr().toString());
00779       t = rewrite(thm.getRHS()[0]);
00780       substThms.clear();
00781       changed.clear();
00782       if(t.getLHS() != t.getRHS()) {
00783         substThms.push_back(t);
00784         changed.push_back(0);
00785       }
00786       t = rewriteN(thm.getRHS()[1], 2);
00787       if(t.getLHS() != t.getRHS()) {
00788         substThms.push_back(t);
00789         changed.push_back(1);
00790       }
00791       if(changed.size()>0) {
00792         t = substitutivityRule(thm.getRHS(), changed, substThms);
00793         thm = transitivityRule(thm, t);
00794       }
00795       t = rewriteAnd(thm.getRHS());
00796       thm = transitivityRule(thm, t);
00797       break;
00798     }
00799       // Quantifiers
00800     case FORALL:
00801     case EXISTS:
00802       thm = d_commonRules->reflexivityRule(e);      
00803       break;
00804       // don't need to rewrite these
00805     case AND_R:
00806     case IFF_R:
00807     case ITE_R:
00808       thm = reflexivityRule(e);
00809       break;    
00810     default:
00811       DebugAssert(false,
00812                   "TheoryCore::rewrite("
00813                   + e.toString() + " : " + e.getType().toString()
00814                   + "): Not implemented");
00815       break;
00816   }
00817 
00818   DebugAssert(thm.getLHS() == e, "TheoryCore::rewrite("+e.toString()
00819               +") = "+thm.getExpr().toString());
00820   
00821   Expr rhs = thm.getRHS();
00822   // Advanced Boolean rewrites
00823   switch(rhs.getKind()) {
00824   case AND:
00825     if(getFlags()["simp-and"].getBool()) {
00826       Theorem tmp(reflexivityRule(rhs));
00827       for(int i=0, iend=rhs.arity(); i<iend; ++i) {
00828         tmp = transitivityRule
00829           (tmp, d_rules->rewriteAndSubterms(tmp.getRHS(), i));
00830       }
00831       if(tmp.getRHS() != rhs) { // Something changed: simplify recursively
00832         thm = transitivityRule(thm, tmp);
00833         thm = transitivityRule(thm, simplifyRec(thm.getRHS()));
00834         rhs = thm.getRHS();
00835       }
00836     }
00837     break;
00838   case OR:
00839     if(getFlags()["simp-or"].getBool()) {
00840       Theorem tmp(reflexivityRule(rhs));
00841       for(int i=0, iend=rhs.arity(); i<iend; ++i) {
00842         tmp = transitivityRule
00843           (tmp, d_rules->rewriteOrSubterms(tmp.getRHS(), i));
00844       }
00845       if(tmp.getRHS() != rhs) { // Something changed: simplify recursively
00846         thm = transitivityRule(thm, tmp);
00847         thm = transitivityRule(thm, simplifyRec(thm.getRHS()));
00848         rhs = thm.getRHS();
00849       }
00850     }
00851     break;
00852   default:
00853     break;
00854   }
00855   if (theoryOf(rhs) == this) {
00856     // Core rewrites are idempotent (FIXME: are they, still?)
00857     rhs.setRewriteNormal();
00858   }  
00859   TRACE("core rewrite", "TheoryCore::rewrite => ", thm.getExpr(), " }");
00860   return thm;
00861 }
00862 
00863 
00864 Theorem TheoryCore::simplifyOp(const Expr& e) {
00865   TRACE("core simplifyOp", "TheoryCore::simplifyOp(", e, ") {");
00866   int kind(e.getKind());
00867   Theorem res;
00868 
00869   if(getFlags()["ite-lift-unary"].getBool()
00870      && e.arity()==1 && e[0].isITE()) {
00871     res = d_rules->ifLiftUnaryRule(e);
00872     res = transitivityRule(res, simplifyOp(res.getRHS()));
00873     TRACE("core simplifyOp", "TheoryCore::simplifyOp[unary ite] => ",
00874           res.getExpr(), " }");
00875     return res;
00876   }
00877   
00878   switch(kind) {
00879   case AND:
00880   case OR: {
00881     // Stop when a child has this kind
00882     int endKind = (kind==AND)? FALSE : TRUE;
00883     int ar = e.arity();
00884     // Optimization: before simplifying anything recursively, check if
00885     // any kid is already TRUE or FALSE, and just return at that point
00886     int l(0);
00887     for(; l<ar && e[l].getKind() != endKind; ++l);
00888     if(l < ar) { // Found TRUE or FALSE: e simplifies to a const
00889       IF_DEBUG(debugger.counter("simplified AND/OR topdown")++);
00890       if(kind==AND)
00891         res = rewriteAnd(e);
00892       else
00893         res = rewriteOr(e);
00894       break; // Break out of switch()
00895     }
00896     vector<Theorem> newChildrenThm;
00897     vector<unsigned> changed;
00898     for(int k = 0; k < ar; ++k) {
00899       // Recursively simplify the kids
00900       Theorem thm = simplifyRec(e[k]);
00901       if (thm.getLHS() != thm.getRHS()) {
00902         if (thm.getRHS().getKind() == endKind) {
00903           newChildrenThm.clear();
00904           changed.clear();
00905           newChildrenThm.push_back(thm);
00906           changed.push_back(k);
00907           thm = substitutivityRule(e, changed, newChildrenThm);
00908           // Simplify to TRUE or FALSE
00909           if(kind==AND)
00910             thm = transitivityRule(thm, rewriteAnd(thm.getRHS()));
00911           else
00912             thm = transitivityRule(thm, rewriteOr(thm.getRHS()));
00913           IF_DEBUG(debugger.counter("simplified AND/OR: skipped kids")
00914                    += ar-k-1);
00915           TRACE("core simplifyOp",
00916                 "TheoryCore::simplifyOp[TRUE/FALSE in OR/AND] => ",
00917                 thm.getExpr(), " }");
00918           return thm;
00919         } else { // Child simplified to something else
00920           newChildrenThm.push_back(thm);
00921           changed.push_back(k);
00922         }
00923       }
00924     }
00925     if(changed.size() > 0)
00926       res = substitutivityRule(e, changed, newChildrenThm);
00927     break;
00928   }
00929   case ITE: {
00930     DebugAssert(e.arity()==3, "Bad ITE in TheoryCore::simplify(e="
00931                 +e.toString()+")");
00932     // Optimization: check if the two branches are the same, so we
00933     // don't have to simplify the condition
00934     if(e[1]==e[2]) {
00935       res = d_rules->rewriteIteSame(e);
00936       res = transitivityRule(res, simplifyRec(res.getRHS()));
00937       IF_DEBUG(debugger.counter("simplified ITE(c,e,e)")++);
00938       break; // break out of switch()
00939     }
00940     // First, simplify the conditional
00941     vector<Theorem> newChildrenThm;
00942     vector<unsigned> changed;
00943     Theorem thm = simplifyRec(e[0]);
00944     if(thm.getLHS() != thm.getRHS()) {
00945       newChildrenThm.push_back(thm);
00946       changed.push_back(0);
00947     }
00948     const Expr& cond = thm.getRHS();
00949     for(int k=1; k<=2; ++k) {
00950       // If condition value is known, only the appropriate branch
00951       // needs to be simplified
00952       if((k==1 && cond.isFalse()) || (k==2 && cond.isTrue())) {
00953         IF_DEBUG(debugger.counter("simplified ITE: skiped one branch")++);
00954         continue;
00955       }
00956       thm = simplifyRec(e[k]);
00957       if(thm.getLHS() != thm.getRHS()) {
00958         newChildrenThm.push_back(thm);
00959         changed.push_back(k);
00960       }
00961     }
00962     if(changed.size() > 0)
00963       res = substitutivityRule(e, changed, newChildrenThm);
00964     break;
00965   }
00966   case NOT: { // Push negation down
00967     if(getFlags()["pushneg"].getBool()) {
00968       res = d_exprTrans->pushNegation1(e);
00969       if(res.getLHS() != res.getRHS())
00970         // Recurse; there may be shortcuts to take advantage of
00971         res = transitivityRule(res, simplifyOp(res.getRHS()));
00972       else {
00973         res = Theory::simplifyOp(e);
00974         // Try pushing negation once more
00975         Theorem thm = d_exprTrans->pushNegation1(res.getRHS());
00976         if(thm.getLHS() != thm.getRHS()) {
00977           thm = transitivityRule(thm, simplifyRec(thm.getRHS()));
00978           res = transitivityRule(res, thm);
00979         }
00980       }
00981     } else {
00982       res = Theory::simplifyOp(e);
00983     }
00984     break;
00985   }
00986   case IMPLIES:
00987     res = d_rules->rewriteImplies(e);
00988     res = transitivityRule(res, simplifyOp(res.getRHS()));
00989     break;
00990   default:
00991     res = Theory::simplifyOp(e);
00992   }
00993   if(res.isNull())
00994     res = reflexivityRule(e);
00995   TRACE("core simplifyOp", "TheoryCore::simplifyOp => ", res.getExpr(), " }");
00996   return res;
00997 }
00998 
00999 
01000 /*! Only Boolean constants (TRUE and FALSE) and variables of
01001   uninterpreted types should appear here (they come from records and
01002   tuples).  Just ignore them. */
01003 void TheoryCore::setup(const Expr& e) { }
01004 
01005 
01006 /*! We use the update method of theory core to track registered atomic
01007  * formulas.  Updates are recorded and then processed by calling processUpdates
01008  * once all equalities have been processed. */
01009 void TheoryCore::update(const Theorem& e, const Expr& d)
01010 {
01011   d_update_thms.push_back(e);
01012   d_update_data.push_back(d);
01013 }
01014 
01015 void TheoryCore::processUpdates()
01016 {
01017   Theorem e;
01018   Expr d;
01019   DebugAssert(d_update_thms.size() == d_update_data.size(),
01020               "Expected same size");
01021   while (!d_update_thms.empty()) {
01022     e = d_update_thms.back();
01023     d_update_thms.pop_back();
01024     d = d_update_data.back();
01025     d_update_data.pop_back();
01026 
01027     DebugAssert(d.isAbsAtomicFormula(), "Expected atomic formula");
01028     Theorem thm = simplify(d);
01029     if (thm.getRHS().isTrue()) {
01030       if (d.isImpliedLiteral()) continue;
01031       d.setImpliedLiteral();
01032       d_impliedLiterals.push_back(d_commonRules->iffTrueElim(thm));
01033     }
01034     else if (thm.getRHS().isFalse()) {
01035       Expr notd = !d;
01036       if (notd.isImpliedLiteral()) continue;
01037       notd.setImpliedLiteral();
01038       d_impliedLiterals.push_back(d_commonRules->iffFalseElim(thm));
01039     }
01040     else {
01041       DebugAssert(e.isRewrite(), "Unexpected theorem in TheoryCore::update");
01042       if (e.getRHS().getType().isBool()) continue;
01043       find(e.getRHS()).getRHS().addToNotify(this, d);
01044       if (thm.getRHS().isAbsAtomicFormula()) thm.getRHS().addToNotify(this, d);
01045     }
01046   }
01047 }
01048 
01049 
01050 Expr TheoryCore::computeTypePred(const Type& t, const Expr& e)
01051 {
01052   Expr tExpr = t.getExpr();
01053   switch(tExpr.getKind()) {
01054     case SUBTYPE: {
01055       Expr pred = tExpr[0];
01056       // pred may be a named function (CONSTDEF).  Strip CONSTDEFs off.
01057       while(pred.getKind()==CONSTDEF) pred = pred[1];
01058       const Type& argTp = pred.lookupType()[0];
01059       return Expr(pred.mkOp(), e).andExpr(getTypePred(argTp, e));
01060     }
01061     case APPLY: {
01062       Theory* i = theoryOf(e);
01063       if (i != this) return i->computeTypePred(t, e);
01064       // fall through
01065     }
01066     default:
01067       return e.getEM()->trueExpr();
01068   }
01069 }
01070 
01071 
01072 void TheoryCore::checkType(const Expr& e)
01073 {
01074   switch (e.getKind()) {
01075     case BOOLEAN:
01076       if (e.arity() > 0) {
01077         throw Exception("Ill-formed Boolean type:\n\n"+e.toString());
01078       }
01079       break;
01080     case SUBTYPE: {
01081         if (e.arity() != 1)
01082           throw Exception("Ill-formed SUBTYPE expression:\n\n"+e.toString());
01083         Type t = e[0].getType();
01084         if (!t.isFunction())
01085           throw Exception
01086             ("Non-function argument to SUBTYPE:\n\n"
01087              +e.toString());
01088         if (!t[1].isBool())
01089           throw Exception
01090             ("Non-predicate argument to SUBTYPE:\n\n"
01091              +e.toString());
01092       }
01093       break;
01094     default:
01095       DebugAssert(false, "Unexpected kind in TheoryCore::checkType"
01096                   +getEM()->getKindName(e.getKind()));
01097   }
01098 }
01099 
01100 
01101 void TheoryCore::computeType(const Expr& e)
01102 {
01103   switch (e.getKind()) {
01104     case ITE: {
01105       Type t1(getBaseType(e[1])), t2(getBaseType(e[2]));
01106       if (e[0].getType() != boolType())
01107         throw TypecheckException
01108           ("The conditional in IF-THEN-ELSE must be BOOLEAN, but is:\n\n"
01109            +e[0].getType().toString()
01110            +"\n\nIn the expression:\n\n  "
01111            +e.toString());
01112       if(t1 != t2) {
01113         throw TypecheckException
01114           ("The types of the IF-THEN-ELSE branches do not match.\n"
01115            "THEN branch has the type:\n\n  "
01116            +e[1].getType().toString()
01117            +"\n\nELSE branch has the type:\n\n  "
01118            +e[2].getType().toString()
01119            +"\n\nIn expression:\n\n  "+e.toString());
01120       }
01121       Type res(e[1].getType());
01122       // If the precise types match in both branches, use it as the
01123       // result type.
01124       if(res == e[2].getType()) {
01125         IF_DEBUG(if(res != t1) // Trace ITEs with strict subtypes
01126                  TRACE("ite", "ITE: setting type "+res.toString()
01127                        +" to:\n\n  ", e, ""));
01128         e.setType(res);
01129       }
01130       else
01131         // Note: setting the base type, since e[1] and e[2] have
01132         // different exact types, and the base type is a conservative
01133         // approximation we can easily compute.
01134         e.setType(t1);
01135     }
01136       break;
01137     case EQ: {
01138       Type t0(getBaseType(e[0])), t1(getBaseType(e[1]));
01139       if (t0.isBool() || t1.isBool()) {
01140         throw TypecheckException
01141           ("Cannot use EQ ('=') for BOOLEAN type; use IFF ('<=>') instead.\n"
01142            "Error in the following expression:\n"+e.toString());
01143       }
01144       if (t0 != t1) {
01145         throw TypecheckException
01146           ("Type mismatch in equality:\n\n LHS type:\n"+t0.toString()
01147            +"\n\n RHS type: \n"+t1.toString()
01148            +"\n\n in expression: \n"+e.toString());
01149       }
01150       e.setType(boolType());
01151     }
01152       break;
01153     case NOT:
01154     case AND:
01155     case OR:
01156     case XOR:
01157     case IFF:
01158     case IMPLIES:
01159 
01160     case AND_R:
01161     case IFF_R:
01162     case ITE_R:
01163     
01164       for (int k = 0; k < e.arity(); ++k) {
01165         if (e[k].getType() != boolType()) {
01166           throw TypecheckException(e.toString());
01167         }
01168       }
01169       e.setType(boolType());
01170       break;
01171     case CONSTDEF: 
01172     case LETDECL: {
01173       Type varTp(getBaseType(e[0]));
01174       Type valTp(getBaseType(e[1]));
01175       if(valTp != varTp) {
01176         throw TypecheckException("Type mismatch for "+e[0].toString()+":"
01177                                  +"\n  declared: "
01178                                  + varTp.toString()
01179                                  +"\n  derived: "+ valTp.toString());
01180       }
01181       e.setType(e[0].getType());
01182     }
01183       break;
01184     default:
01185       DebugAssert(false,"TheoryCore::computeType(" + e.toString()
01186                   + "):\nNot implemented");
01187       break;
01188   }
01189 }
01190 
01191 
01192 Type
01193 TheoryCore::computeBaseType(const Type& tp) {
01194   const Expr& e = tp.getExpr();
01195   Type res;
01196   switch(e.getKind()) {
01197   case SUBTYPE: {
01198     DebugAssert(e.arity() == 1, "Expr::computeBaseType(): "+e.toString());
01199     Type lambdaTp = e[0].getType();
01200     Type lambdaBaseTp = getBaseType(lambdaTp);
01201     DebugAssert(lambdaBaseTp.isFunction(), 
01202                 "Expr::computeBaseType(): lambdaBaseTp = "
01203                 +lambdaBaseTp.toString()+" in e = "+e.toString());
01204     res = lambdaBaseTp[0];
01205     break;
01206   }
01207   case BOOLEAN:
01208     res = tp; break;
01209   case TYPEDEF: // Compute the base type of the definition
01210     res = getBaseType(Type(e[1]));
01211     break;
01212   default:
01213     DebugAssert(false, "TheoryCore::computeBaseType("+tp.toString()+")");
01214     res = tp;
01215   }
01216   return res;
01217 }
01218 
01219 
01220 Expr 
01221 TheoryCore::computeTCC(const Expr& e) {
01222   Expr res;
01223   switch (e.getKind()) {
01224   case NOT:
01225     res = getTCC(e[0]);
01226     break;
01227   case AND: {
01228     // ( (tcc(e1) & !e1) \/ ... \/ (tcc(en) & !en) \/ (tcc(e1)&...&tcc(en))
01229     vector<Expr> tccs;
01230     for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
01231       tccs.push_back(getTCC(*i));
01232     vector<Expr> pairs;
01233     pairs.push_back(rewriteAnd(andExpr(tccs)).getRHS());
01234     for(size_t i=0, iend=tccs.size(); i<iend; ++i)
01235       pairs.push_back(rewriteAnd(tccs[i].andExpr(e[i].negate())).getRHS());
01236     res = rewriteOr(orExpr(pairs)).getRHS();
01237     break;
01238   }
01239   case OR: {
01240     // ( (tcc(e1) & e1) \/ ... \/ (tcc(en) & en) \/ (tcc(e1)&...&tcc(en))
01241     vector<Expr> tccs;
01242     for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
01243       tccs.push_back(getTCC(*i));
01244     vector<Expr> pairs;
01245     pairs.push_back(rewriteAnd(andExpr(tccs)).getRHS());
01246     for(size_t i=0, iend=tccs.size(); i<iend; ++i)
01247       pairs.push_back(rewriteAnd(tccs[i].andExpr(e[i])).getRHS());
01248     res = rewriteOr(orExpr(pairs)).getRHS();
01249     break;
01250   }
01251   case ITE: {
01252     Expr tcc1(getTCC(e[1])), tcc2(getTCC(e[2]));
01253     // Optimize: if TCCs on both branches are the same, skip the ITE
01254     Expr tccITE((tcc1 == tcc2)? tcc1 : e[0].iteExpr(tcc1, tcc2));
01255     res = rewriteAnd(getTCC(e[0]).andExpr(tccITE)).getRHS();
01256     break;
01257   }
01258   case IMPLIES:
01259     res = getTCC(e[0].negate().orExpr(e[1]));
01260     break;
01261   case APPLY: {
01262     Theory* i = theoryOf(e);
01263     if (i != this) return i->computeTCC(e);
01264     // fall through
01265   }
01266   default: // All the other operators are strict
01267     res = Theory::computeTCC(e);
01268     break;
01269   }
01270   return res;
01271 }
01272 
01273 ///////////////////////////////////////////////////////////////////////////////
01274 // Pretty-printing                                                           //
01275 ///////////////////////////////////////////////////////////////////////////////
01276 
01277 ExprStream&
01278 TheoryCore::print(ExprStream& os, const Expr& e)   
01279 {
01280   switch(os.lang()) {
01281   case PRESENTATION_LANG:
01282     switch(e.getKind()) {
01283     case TRUE:
01284     case FALSE:
01285     case UCONST:
01286     case BOOLEAN:
01287     case STRING_EXPR:
01288       e.print(os); break;
01289     case TYPE:
01290       if(e.arity() == 0) os << "TYPE";
01291       else if(e.arity() == 1)
01292         os << e[0] << ": TYPE;";
01293       else if(e.arity() == 2)
01294         os << e[0] << ":" << push << " TYPE = " << e[1] << push << ";";
01295       else e.printAST(os);
01296       break;
01297     case ID:
01298       if(e.arity() == 1 && e[0].isString()) os << e[0].getString();
01299       else e.printAST(os);
01300       break;
01301     case CONST:
01302       if(e.arity() == 2) {
01303         if(e[0].getKind() == RAW_LIST) {
01304           bool first(true);
01305           for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) {
01306             if(first) first = false;
01307             else os << push << "," << pop << space;
01308             os << (*i);
01309           }
01310         }
01311         else
01312           os << e[0];
01313         os << ":" << push << space << e[1] << push << ";";
01314       } else if(e.arity() == 3)
01315         os << e[0] << ":" << push << space << e[1]
01316            << space << "=" << space << push << e[2] << push << ";";
01317       else
01318         e.printAST(os);
01319       break;
01320     case SUBTYPE:
01321       os << "SUBTYPE(" << push << e[0] << push << ")";
01322       break;
01323     case TYPEDEF: {
01324       // This is used when dumping declarations to file.  Print just
01325       // the name of the type, unless it's a messed-up expression.
01326       if(e.arity() != 2) e.printAST(os);
01327       else if(e[0].isString()) os << e[0].getString();
01328       else e[0].print(os);
01329       break;
01330     }
01331     case EQ:
01332       // When a separator starts with a space (like " = "), add the
01333       // leading space with 'space' modifier.  If this separator goes
01334       // to the next line, the leading spaces must be eaten up to get
01335       // the indentation right; 'space' will tell the indentation
01336       // engine that it is a space that can be eaten.  A space in a
01337       // string (like " ") will never be eaten.
01338       os << "(" << push << e[0] << space << "= " << e[1] << push << ")";
01339       break;
01340     case NOT: os << "NOT " << e[0]; break;
01341     case AND: {
01342       int i=0, iend=e.arity();
01343       os << "(" << push;
01344       if(i!=iend) { os << e[i]; ++i; }
01345       for(; i!=iend; ++i) os << space << "AND " << e[i];
01346       os << push << ")";
01347     }
01348       break;
01349     case OR: {
01350       int i=0, iend=e.arity();
01351       os << "(" << push;
01352       if(i!=iend) { os << e[i]; ++i; }
01353       for(; i!=iend; ++i) os << space << "OR " << e[i];
01354       os << push << ")";
01355     }
01356       break;
01357     case ITE:
01358       os << push << "IF " << push << e[0] << popSave
01359          << space << "THEN " << pushRestore << e[1] << popSave
01360          << space << "ELSE " << pushRestore << e[2] << pop
01361          << space << "ENDIF";
01362       break;
01363     case IFF:
01364       if(e.arity() == 2)
01365         os << "(" << push << e[0] << space << "<=> " << e[1] << push << ")";
01366       else
01367         e.printAST(os);
01368       break;
01369     case IMPLIES:
01370       os << "(" << push << e[0] << space << "=> " << e[1] << push << ")";
01371       break;
01372       // Commands
01373     case ASSERT:
01374       os << "ASSERT " << push << e[0] << push << ";";
01375       break;
01376     case TRANSFORM:
01377       os << "TRANSFORM " << push << e[0] << push << ";";
01378       break;
01379     case QUERY:
01380       os << "QUERY " << push << e[0] << push << ";";
01381       break;
01382     case WHERE:
01383       os << "WHERE;";
01384       break;
01385     case ASSERTIONS:
01386       os << "ASSERTIONS;";
01387       break;
01388     case ASSUMPTIONS:
01389       os << "ASSUMPTIONS;";
01390       break;
01391     case COUNTEREXAMPLE:
01392       os << "COUNTEREXAMPLE;";
01393       break;
01394     case COUNTERMODEL:
01395       os << "COUNTERMODEL;";
01396       break;
01397     case PUSH:
01398       if(e.arity()==0)
01399         os << "PUSH;";
01400       else
01401         os << "PUSH" << space << e[0] << push << ";";
01402       break;
01403     case POP:
01404       if(e.arity()==0)
01405         os << "POP;";
01406       else
01407         os << "POP" << space << e[0] << push << ";";
01408       break;
01409     case POPTO:
01410       os << "POPTO" << space << e[0] << push << ";"; break;
01411     case PUSH_SCOPE:
01412       if(e.arity()==0)
01413         os << "PUSH_SCOPE;";
01414       else
01415         os << "PUSH_SCOPE" << space << e[0] << push << ";";
01416       break;
01417     case POP_SCOPE:
01418       if(e.arity()==0)
01419         os << "POP_SCOPE;";
01420       else
01421         os << "POP_SCOPE" << space << e[0] << push << ";";
01422       break;
01423     case POPTO_SCOPE:
01424       os << "POPTO_SCOPE" << space << e[0] << push << ";"; break;
01425     case CONSTDEF:
01426     case LETDECL:
01427       if(e.arity() == 2) os << e[1];
01428       else e.printAST(os);
01429       break;
01430     case LET: {
01431       // (LET (LETDECLS (LETDECL var [ type ] val) .... ) body)
01432       bool first(true);
01433       os << "(" << push << "LET" << space << push;
01434       for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) {
01435         if(!first) os << push << "," << pop << endl;
01436         else first = false;
01437         if(i->arity() == 3) {
01438           os << (*i)[0] << ":" << space << push << (*i)[1]
01439              << space << "= " << push << nodag << (*i)[2] << pop << pop;
01440         } else {
01441           os << (*i)[0];
01442           Type tp((*i)[0].lookupType());
01443           if(!tp.isNull()) os << ":" << space << push << tp.getExpr();
01444           else os << push;
01445           os << space << "= " << push << nodag << (*i)[1] << pop << pop;
01446         }
01447       }
01448       os << pop << endl << "IN" << space << push << e[1] << push << ")";
01449       break;
01450     }
01451     case BOUND_VAR:
01452       os << e.getName()+"_"+e.getUid();
01453       break;
01454     case SKOLEM_VAR:
01455       os << "SKOLEM_" + int2string(e.getIndex());
01456       break;
01457     case PF_APPLY: // FIXME: this will eventually go to the "symsim" theory
01458       DebugAssert(e.arity() > 0, "TheoryCore::print(): "
01459                   "Proof rule application must have at "
01460                   "least one argument (rule name):\n "+e.toString());
01461       os << e[0];
01462       if(e.arity() > 1) { // Print the arguments
01463         os << push << "(" << push;
01464         bool first(true);
01465         for(int i=1; i<e.arity(); i++) {
01466           if(first) first=false;
01467           else os << push << "," << pop << space;
01468           os << e[i];
01469         }
01470         os << push << ")";
01471       }
01472       break;
01473     case RAW_LIST: {
01474       os << "[" << push;
01475       bool firstTime(true);
01476       for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
01477         if(firstTime) firstTime = false;
01478         else os << push << "," << pop << space;
01479         os << *i;
01480       }
01481       os << push << "]";
01482       break;
01483     }
01484     case PF_HOLE: // FIXME: implement this (now fall through to default)
01485     default:
01486       // Print the top node in the default LISP format, continue with
01487       // pretty-printing for children.
01488       e.printAST(os);
01489     }
01490     break; // end of case PRESENTATION_LANG
01491   case SMTLIB_LANG:
01492     switch(e.getKind()) {
01493     case TRUE: os << "true"; break;
01494     case FALSE: os << "false"; break;
01495     case UCONST: e.print(os); break;
01496     case BOOLEAN: e.printAST(os); break;
01497     case STRING_EXPR: e.print(os); break;
01498     case TYPE:
01499       if (e.arity() == 1) {
01500         os << "  :extrasorts (";
01501         for (int i=0; i < e[0].arity(); ++i) {
01502           if (i != 0) os << push << space;
01503           os << push << e[0][i];
01504         }
01505         os << push << ")";
01506       }
01507       else if (e.arity() == 2) {
01508         break;
01509       }
01510       else {
01511         throw SmtlibException("TheoryCore::print: SMTLIB: Unexpected TYPE expression");
01512       }
01513       break;
01514     case ID: // FIXME: when lisp becomes case-insensitive, fix printing of IDs
01515       if(e.arity() == 1 && e[0].isString()) os << e[0].getString();
01516       else e.printAST(os);
01517       break;
01518     case CONST:
01519       if(e.arity() == 2) {
01520         if (e[1].getKind() == BOOLEAN) {
01521           os << "  :extrapreds ((" << push << e[0]
01522              << push << "))";
01523         }
01524         else if (e[1].getKind() == ARROW && e[1][e[1].arity()-1].getKind() == BOOLEAN) {
01525           os << "  :extrapreds ((" << push << e[0]
01526              << space << e[1] << push << "))";
01527         }
01528         else {
01529           os << "  :extrafuns ((" << push << e[0]
01530              << space << e[1] << push << "))";
01531         }
01532       }
01533       else if (e.arity() == 0) e.printAST(os);
01534       else {
01535         throw SmtlibException("TheoryCore::print: SMTLIB: CONST not implemented");
01536       }
01537       break;
01538     case SUBTYPE:
01539       throw SmtlibException("TheoryCore::print: SMTLIB: SUBTYPE not implemented");
01540       break;
01541     case TYPEDEF: {
01542       throw SmtlibException("TheoryCore::print: SMTLIB: TYPEDEF not implemented");
01543       break;
01544     }
01545     case EQ:
01546       os << "(" << push << "=" << space << e[0]
01547          << space << e[1] << push << ")";
01548       break;
01549     case NOT:
01550       os << "(" << push << "not" << space << e[0] << push << ")";
01551       break;
01552     case AND: {
01553       int i=0, iend=e.arity();
01554       os << "(" << push << "and";
01555       for(; i!=iend; ++i) os << space << e[i];
01556       os << push << ")";
01557     }
01558       break;
01559     case OR: {
01560       int i=0, iend=e.arity();
01561       os << "(" << push << "or";
01562       for(; i!=iend; ++i) os << space << e[i] << space;
01563       os << push << ")";
01564       break;
01565     }
01566     case XOR: {
01567       int i=0, iend=e.arity();
01568       os << "(" << push << "xor";
01569       for(; i!=iend; ++i) os << space << e[i] << space;
01570       os << push << ")";
01571       break;
01572     }
01573     case ITE:
01574       os << "(" << push;
01575       if (e.getType().isBool()) os << "if_then_else";
01576       else os << "ite";
01577       os << space << e[0]
01578          << space << e[1] << space << e[2] << push << ")";
01579       break;
01580     case IFF:
01581       os << "(" << push << "iff" << space
01582          << e[0] << space << e[1] << push << ")";
01583       break;
01584     case IMPLIES:
01585       os << "(" << push << "implies" << space
01586          << e[0] << space << e[1] << push << ")";
01587       break;
01588       // Commands
01589     case ASSERT:
01590       //      throw SmtlibException("TheoryCore::print: SMTLIB: ASSERT not implemented");
01591       os << "(" << push << "ASSERT" << space << e[0] << push << ")";
01592       break;
01593     case TRANSFORM:
01594       throw SmtlibException("TheoryCore::print: SMTLIB: TRANSFORM not implemented");
01595       os << "(" << push << "TRANSFORM" << space << e[0] << push << ")";
01596       break;
01597     case QUERY:
01598       throw SmtlibException("TheoryCore::print: SMTLIB: QUERY not implemented");
01599       os << "(" << push << "QUERY" << space << e[0] << push << ")";
01600       break;
01601     case CONSTDEF:
01602     case LETDECL:
01603       //      throw SmtlibException("TheoryCore::print: SMTLIB: CONSTDEF, LETDECL not implemented");
01604       if(e.arity() == 2) os << e[1];
01605       else e.printAST(os);
01606       break;
01607     case LET: {
01608       // (LET ((var [ type ] val) .... ) body)
01609       for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) {
01610         os << "(" << push;
01611         Type tp(i->arity() == 3 ? (*i)[2].getType() : (*i)[1].getType());
01612         DebugAssert(!tp.isNull(), "Unexpected Null type");
01613         if (tp.getExpr().getKind() == BOOLEAN) {
01614           os << "flet" << space << "(" << push;
01615         }
01616         else {
01617           os << "let" << space << "(" << push;
01618         }
01619         if(i->arity() == 3) {
01620           os << (*i)[0] << space << nodag << (*i)[2];
01621         } else {
01622           os << (*i)[0] << space << nodag << (*i)[1];
01623         }
01624         os << push << ")" << pop << pop << space;
01625       }
01626       os << e[1] << push;
01627       for (int j = 0; j < e[0].arity(); ++j)
01628         os << ")";
01629       break;
01630     }
01631     case BOUND_VAR:
01632       os << e.getName()+"_"+e.getUid();
01633       break;
01634     case SKOLEM_VAR:
01635       os << "SKOLEM_" + int2string(e.getIndex());
01636       break;
01637     case PF_APPLY: {// FIXME: this will eventually go to the "symsim" theory
01638       throw SmtlibException("TheoryCore::print: SMTLIB: PF_APPLY not implemented");
01639       break;
01640     }
01641     case RAW_LIST: {
01642       os << "(" << push;
01643       bool firstTime(true);
01644       for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
01645         if(firstTime) firstTime = false;
01646         else os << space;
01647         os << *i;
01648       }
01649       os << push << ")";
01650       break;
01651     }
01652     case PUSH:
01653     case POP:
01654     case POPTO:
01655     case PUSH_SCOPE:
01656     case POP_SCOPE:
01657     case POPTO_SCOPE:
01658       throw SmtlibException("TheoryCore::print: SMTLIB: Stack operations not implemented");
01659       break;
01660     case PF_HOLE: // FIXME: implement this (now fall through to default)
01661     default:
01662       throw SmtlibException("TheoryCore::print: SMTLIB_LANG: Unexpected expression: "
01663                             +getEM()->getKindName(e.getKind()));
01664     }
01665     break; // end of case SMTLIB_LANG
01666   case LISP_LANG:
01667     switch(e.getKind()) {
01668     case TRUE:
01669     case FALSE:
01670     case UCONST:
01671       e.print(os); break;
01672     case TYPE:
01673       if(e.arity() == 0) os << "TYPE";
01674       else if(e.arity() == 1)
01675         os << "(" << push << "TYPE" << space << e[0] << push << ")";
01676       else if(e.arity() == 2)
01677         os << "(" << push << "TYPE" << space << e[0]
01678            << space << e[1] << push << ")";
01679       else e.printAST(os);
01680       break;
01681     case ID: // FIXME: when lisp becomes case-insensitive, fix printing of IDs
01682       if(e.arity() == 1 && e[0].isString()) os << e[0].getString();
01683       else e.printAST(os);
01684       break;
01685     case CONST:
01686       if(e.arity() == 2)
01687         os << "(" << push << "CONST" << space << e[0]
01688            << space << e[1] << push << ")";
01689       else
01690         e.printAST(os);
01691       break;
01692     case SUBTYPE:
01693       os << "SUBTYPE(" << push << e[0] << push << ")";
01694       break;
01695     case TYPEDEF: {
01696       // This is used when dumping declarations to file.  Print just
01697       // the name of the type, unless it's a messed-up expression.
01698       if(e.arity() != 2) e.printAST(os);
01699       else if(e[0].isString()) os << e[0].getString();
01700       else e[0].print(os);
01701       break;
01702     }
01703     case EQ:
01704       // When a separator starts with a space (like " = "), add the
01705       // leading space with 'space' modifier.  If this separator goes
01706       // to the next line, the leading spaces must be eaten up to get
01707       // the indentation right; 'space' will tell the indentation
01708       // engine that it is a space that can be eaten.  A space in a
01709       // string (like " ") will never be eaten.
01710       os << "(" << push << "=" << space << e[0]
01711          << space << e[1] << push << ")";
01712       break;
01713     case NOT:
01714       os << "(" << push << "NOT" << space << e[0] << push << ")";
01715       break;
01716     case AND: {
01717       int i=0, iend=e.arity();
01718       os << "(" << push << "AND";
01719       for(; i!=iend; ++i) os << space << e[i];
01720       os << push << ")";
01721     }
01722       break;
01723     case OR: {
01724       int i=0, iend=e.arity();
01725       os << "(" << push << "OR";
01726       for(; i!=iend; ++i) os << space << e[i] << space;
01727       os << push << ")";
01728     }
01729       break;
01730     case ITE:
01731       os << "(" << push << "IF" << space << e[0]
01732          << space << e[1] << space << e[2] << push << ")";
01733       break;
01734     case IFF:
01735       os << "(" << push << "<=>" << space
01736          << e[0] << space << e[1] << push << ")";
01737       break;
01738     case IMPLIES:
01739       os << "(" << push << "=>" << space
01740          << e[0] << space << e[1] << push << ")";
01741       break;
01742       // Commands
01743     case ASSERT:
01744       os << "(" << push << "ASSERT" << space << e[0] << push << ")";
01745       break;
01746     case TRANSFORM:
01747       os << "(" << push << "TRANSFORM" << space << e[0] << push << ")";
01748       break;
01749     case QUERY:
01750       os << "(" << push << "QUERY" << space << e[0] << push << ")";
01751       break;
01752     case PUSH:
01753       os << "(PUSH)"; break;
01754     case POP:
01755       os << "(POP)"; break;
01756     case POPTO:
01757       os << "(" << push << "POPTO" << space << e[0] << push << ")"; break;
01758     case CONSTDEF:
01759     case LETDECL:
01760       if(e.arity() == 2) os << e[1];
01761       else if(e.arity()==3) // It's a declaration of a named Expr
01762         os << e[0] << push << ":" << space << push << e[1] << push << " ="
01763            << pop << pop << space << e[2];
01764       else e.printAST(os);
01765       break;
01766     case LET: {
01767       // (LET ((var [ type ] val) .... ) body)
01768       bool first(true);
01769       os << "(" << push << "LET" << space << "(" << push;
01770       for(Expr::iterator i=e[0].begin(), iend=e[0].end(); i!=iend; ++i) {
01771         if(!first) os << space;
01772         else first = false;
01773         os << "(" << push;
01774         if(i->arity() == 3) {
01775           os << (*i)[0] << space << (*i)[1]
01776              << space << nodag << (*i)[2];
01777         } else {
01778           os << (*i)[0];
01779           Type tp((*i)[0].lookupType());
01780           if(!tp.isNull()) os << space << tp.getExpr();
01781           os << space << nodag << (*i)[1];
01782         }
01783         os << push << ")" << pop << pop;
01784       }
01785       os << push << ")" << pop << pop << space << e[1] << push << ")";
01786       break;
01787     }
01788     case BOUND_VAR:
01789       os << e.getName()+"_"+e.getUid();
01790       break;
01791     case SKOLEM_VAR:
01792       os << "SKOLEM_" + int2string(e.getIndex());
01793       break;
01794     case PF_APPLY: {// FIXME: this will eventually go to the "symsim" theory
01795       DebugAssert(e.arity() > 0, "TheoryCore::print(): "
01796                   "Proof rule application must have at "
01797                   "least one argument (rule name):\n "+e.toString());
01798       os << push << "(" << push;
01799       bool first(true);
01800       for(int i=0; i<e.arity(); i++) {
01801         if(first) first=false;
01802         else os << space;
01803         os << e[i];
01804       }
01805       os << push << ")";
01806       break;
01807     }
01808     case RAW_LIST: {
01809       os << "(" << push;
01810       bool firstTime(true);
01811       for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
01812         if(firstTime) firstTime = false;
01813         else os << space;
01814         os << *i;
01815       }
01816       os << push << ")";
01817       break;
01818     }
01819     case PF_HOLE: // FIXME: implement this (now fall through to default)
01820     default:
01821       // Print the top node in the default LISP format, continue with
01822       // pretty-printing for children.
01823       e.printAST(os);
01824     }
01825     break; // end of case LISP_LANGUAGE
01826   default:
01827     // Print the top node in the default LISP format, continue with
01828     // pretty-printing for children.
01829     e.printAST(os);
01830   }
01831   return os;
01832 }
01833 
01834 ///////////////////////////////////////////////////////////////////////////////
01835 //parseExpr:
01836 //translates intermediate representation to internal language for use in VCCmd
01837 ///////////////////////////////////////////////////////////////////////////////
01838 Expr TheoryCore::parseExpr(const Expr& e) {
01839   TRACE("parseExpr", "parseExpr(", e, ") {");
01840   // Remember the current size of the bound variable stack
01841   size_t boundVarSize = d_boundVarStack.size();
01842   TRACE("parseExpr", "#bound vars = ", d_boundVarStack.size(), "");
01843 
01844   // Compute the kind to determine what to do with the expression
01845   int kind = NULL_KIND;
01846 
01847   switch(e.getKind()) {
01848   case ID: {
01849     TRACE("parser verbose", "resolving variable/operator(", e[0], ")");
01850     const Expr c1 = e[0];
01851     kind = getEM()->getKind(c1.getString());
01852     if(kind == NULL_KIND) { // It's an identifier; try to resolve it
01853       Expr res = resolveID(e[0].getString());
01854       if(res.isNull())
01855         throw ParserException("cannot resolve an identifier: "
01856                               +e[0].toString());
01857       else {
01858         TRACE("parseExpr", "#bound vars = ", d_boundVarStack.size(), "");
01859         TRACE("parseExpr", "parseExpr => ", res, " }");
01860         DebugAssert(!e.isApply(), "Unexpected apply function");
01861         return res;
01862       }
01863     }
01864     // Otherwise exit the switch and use DP-specific parsing
01865     break;
01866   }
01867   case RAW_LIST: {
01868     TRACE("parser verbose", "constructing Expr from list(", e, ")");
01869     if(e.arity() == 0)
01870       throw ParserException("Empty list is not an expression!");
01871     const Expr& op = e[0];
01872     // First, resolve the operator
01873     switch(op.getKind()) {
01874     case ID: { // The operator in the list is ID: is it keyword or variable?
01875       kind = getEM()->getKind(op[0].getString());
01876       if(kind == NULL_KIND) {
01877         // It's a named function application.  Resolve the ID.
01878         Expr res = resolveID(op[0].getString());
01879         if(res.isNull())
01880           throw ParserException("cannot resolve an identifier: "
01881                                 +op[0].toString());
01882         if(e.arity() < 2)
01883           throw ParserException("Bad function application: "+e.toString());
01884         Expr::iterator i=e.begin(), iend=e.end();
01885         ++i;
01886         vector<Expr> args;
01887         for(; i!=iend; ++i) args.push_back(parseExpr(*i));
01888         return Expr(res.mkOp(), args);
01889       }
01890       // Proceed to DP-specific parsing
01891       break;
01892     }
01893     case RAW_LIST: 
01894       // This can only be a lambda expression application.
01895       kind = LAMBDA;
01896       break;
01897     default:
01898       throw ParserException("Bad operator in "+e.toString());
01899     }
01900     break; // Exit the top-level switch, proceed to DP-specific parsing
01901   }
01902   default: // Can only be a string or a number.
01903     TRACE("parseExpr", "parseExpr => ", e, " }");
01904     return e;
01905   }
01906 
01907   // DP-specific parsing
01908   if(hasTheory(kind)) {
01909     TRACE("parseExpr", "parseExprOp["+theoryOf(kind)->getName()+"](",
01910           e, ") {");
01911     Expr res = theoryOf(kind)->parseExprOp(e);
01912     TRACE("parseExpr",
01913           "parseExprOp["+theoryOf(kind)->getName()+"] => ", res, " }");
01914     TRACE("parseExpr", "#bound vars = ", d_boundVarStack.size(), "");
01915     // Restore the bound variable stack
01916     while(d_boundVarStack.size() > boundVarSize) {
01917       TRACE("parseExpr", "Pop bound var "+d_boundVarStack.back().first+": ",
01918             d_boundVarStack.back().second, "");
01919       d_boundVarStack.pop_back();
01920     }
01921     TRACE("parseExpr", "#bound vars = ", d_boundVarStack.size(), "");
01922     TRACE("parseExpr", "parseExpr => ", res, " }");
01923     return res;
01924   }
01925   else {
01926     TRACE("parseExpr", "parseExpr => ", e, " }");
01927     return e;
01928   }
01929 }
01930 
01931 //! An auxiliary recursive function to process COND expressions into ITE
01932 Expr TheoryCore::processCond(const Expr& e, int i) {
01933   DebugAssert(i < e.arity()-1, "e = "+e.toString()+", i = "+int2string(i));
01934   if(i == e.arity()-2) {
01935     if(e[i].getKind() == RAW_LIST && e[i].arity() == 2
01936        && e[i+1].getKind() == RAW_LIST  && e[i+1].arity() == 2
01937        && e[i+1][0].getKind() == ID && e[i+1][0][0].getString() == "ELSE") {
01938       Expr c(parseExpr(e[i][0]));
01939       Expr e1(parseExpr(e[i][1]));
01940       Expr e2(parseExpr(e[i+1][1]));
01941       return c.iteExpr(e1,e2);
01942     }
01943   } else {
01944     if(e[i].getKind() == RAW_LIST && e[i].arity() == 2
01945        && e[i+1].getKind() == RAW_LIST  && e[i+1].arity() == 2) {
01946       Expr c(parseExpr(e[i][0]));
01947       Expr e1(parseExpr(e[i][1]));
01948       Expr e2(processCond(e, i+1));
01949       return c.iteExpr(e1,e2);
01950     }
01951   }
01952   throw ParserException("Parse Error: bad COND expression: "+e.toString());
01953 }
01954 
01955 ///////////////////////////////////////////////////////////////////////////////
01956 //parseExprOp:
01957 //Recursive call of parseExpr defined in theory_ libaries based on kind of expr 
01958 //being built
01959 ///////////////////////////////////////////////////////////////////////////////
01960 Expr
01961 TheoryCore::parseExprOp(const Expr& e) {
01962   TRACE("parser", "TheoryCore::parseExprOp(", e, ")");
01963   // If the expression is not a list, it must have been already
01964   // parsed, so just return it as is.
01965   switch(e.getKind()) {
01966   case ID: {
01967     int kind = getEM()->getKind(e[0].getString());
01968     switch(kind) {
01969     case NULL_KIND: return e; // nothing to do
01970     case TRUE:
01971     case FALSE:
01972     case TYPE:
01973     case BOOLEAN: return getEM()->newLeafExpr(kind);
01974     default:
01975       DebugAssert(false, "Bad use of bare keyword: "+e.toString());
01976       return e;
01977     }
01978   }
01979   case RAW_LIST: break; // break out of switch, do the work
01980   default:
01981     return e;
01982   }
01983   DebugAssert(e.getKind()==RAW_LIST && e.arity() > 0 && e[0].getKind()==ID,
01984               "TheoryCore::parseExprOp:\n e = "+e.toString());
01985   /* The first element of the list (e[0] is an ID of the operator. 
01986      ID string values are the dirst element of the expression */              
01987   const Expr& c1 = e[0][0];
01988   int kind = getEM()->getKind(c1.getString());
01989   TRACE("parser verbose", "building kind(", kind, ")");
01990   switch(kind) {
01991   case VARDECLS: 
01992   case LETDECLS:
01993   case HELP: 
01994   case DUMP_PROOF:
01995   case DUMP_ASSUMPTIONS:
01996   case DUMP_SIG:
01997   case DUMP_TCC:
01998   case DUMP_TCC_ASSUMPTIONS:
01999   case DUMP_TCC_PROOF:
02000   case DUMP_CLOSURE:
02001   case DUMP_CLOSURE_PROOF:
02002   case WHERE:
02003   case ASSERTIONS:
02004   case ASSUMPTIONS:
02005   case COUNTEREXAMPLE:
02006   case COUNTERMODEL:
02007   case ASSERT:
02008   case PRINT:
02009   case QUERY:
02010   case CHECKSAT:
02011   case CONTINUE:
02012   case RESTART:
02013   case TRACE:
02014   case ECHO:
02015   case UNTRACE:
02016   case VARLIST:
02017   case SUBTYPE: 
02018   case FORGET: 
02019   case GET_TYPE: 
02020   case IFF: 
02021   case IMPLIES: 
02022   case TYPEDEF: 
02023   case OPTION:
02024   case AND:
02025   case OR:
02026   case XOR:
02027   case NOT:
02028   case EQ: 
02029   case CALL: 
02030   case TRANSFORM: 
02031   case CHECK_TYPE: 
02032   case VARDECL: 
02033   case GET_CHILD: 
02034   case SUBSTITUTE: 
02035   case SEQ:
02036   case CONSTDEF: 
02037   case DBG: 
02038   case PUSH:
02039   case POP:
02040   case POPTO:
02041   case PUSH_SCOPE:
02042   case POP_SCOPE:
02043   case POPTO_SCOPE:
02044   case LETDECL:
02045   case ELSE:
02046   case CONTEXT:{
02047     vector<Expr> k;
02048     Expr::iterator i = e.begin(), iend=e.end();
02049     // Skip first element of the vector of kids in 'e'.
02050     // The first element is the operator.
02051     ++i; 
02052     // Parse the kids of e and push them into the vector 'k'
02053     for(; i!=iend; ++i) 
02054       k.push_back(parseExpr(*i));
02055     return Expr(kind, k, e.getEM());
02056   }
02057   case NEQ:
02058     if(e.arity()==3)
02059       return !(parseExpr(e[1]).eqExpr(parseExpr(e[2])));
02060     else
02061       throw ParserException("Disequality requires exactly two arguments: "
02062                             +e.toString());
02063     break;
02064   case CONST: {
02065     if(e.arity()==3) {
02066       vector<Expr> names;
02067       const Expr& vars = e[1];
02068       if(vars.getKind() == RAW_LIST) {
02069         for(Expr::iterator i=vars.begin(), iend=vars.end(); i!=iend; ++i)
02070           names.push_back(*i);
02071       } else if(vars.getKind() == ID)
02072         names.push_back(vars);
02073       return Expr(CONST, Expr(RAW_LIST, names, getEM()),
02074                   parseExpr(e[2]));
02075     }
02076     else if(e.arity() == 4 && e[1].getKind() == ID)
02077       return Expr(CONSTDEF, e[1],
02078                   parseExpr(e[2]), parseExpr(e[3]));
02079     throw ParserException("Bad CONST declaration: "+e.toString());
02080     break;
02081   }
02082   case TYPE: {
02083     if(e.arity()==2) {
02084       const Expr& types = e[1];
02085       if(types.getKind() == RAW_LIST) {
02086         vector<Expr> names;
02087         for(Expr::iterator i=types.begin(), iend=types.end(); i!=iend; ++i)
02088           names.push_back(*i);
02089         return Expr(TYPEDECL, names, getEM());
02090       }
02091     }
02092     else if(e.arity() == 3 && e[1].getKind() == ID)
02093       return Expr(TYPEDEF, e[1], parseExpr(e[2]));
02094     throw ParserException("Bad TYPE declaration: "+e.toString());
02095     break;
02096   }
02097   case IF: 
02098     if(e.arity() == 4) {
02099       Expr c(parseExpr(e[1]));
02100       Expr e1(parseExpr(e[2]));
02101       Expr e2(parseExpr(e[3]));
02102       return c.iteExpr(e1, e2);
02103     } else
02104       throw ParserException("Bad IF-THEN-ELSE expression: "
02105                       +e.toString());
02106   case COND: {
02107     if(e.arity() >= 3)
02108       return processCond(e, 1);
02109     else
02110       throw ParserException("Bad COND expression: "+e.toString());
02111     break;
02112   }
02113   case LET: { // (LET ((v1 [ type1 ] e1) ... ) body)
02114     if(!(e.arity() == 3 && e[1].getKind() == RAW_LIST && e[1].arity() > 0))
02115       throw ParserException("Bad LET expression: "+e.toString());
02116 
02117     // Iterate through the bound variables
02118     for(Expr::iterator i=e[1].begin(), iend=e[1].end(); i!=iend; ++i) {
02119       const Expr& decl = *i;
02120       if(decl.getKind() != RAW_LIST
02121          || !(decl.arity() == 2 || decl.arity() == 3))
02122         throw ParserException("Bad variable declaration block in LET "
02123                               "expression: "+decl.toString()+
02124                               "\n e = "+e.toString());
02125       if(decl[0].getKind() != ID)
02126         throw ParserException("Variable must be an identifier in LET "
02127                               "expression: "+decl[0].toString()+
02128                               "\n e = "+e.toString());
02129       Type type;
02130       Expr def;
02131       if(decl.arity()==3) {
02132         type = Type(parseExpr(decl[1]));
02133         def = parseExpr(decl[2]);
02134       } else 
02135         def = parseExpr(decl[1]);
02136       addBoundVar(decl[0][0].getString(), type, def);
02137     }
02138     // Parse the body recursively and return it (nuke the LET)
02139     return parseExpr(e[2]);
02140   }
02141 //     {
02142 //     vector<Expr> letDecls, lvars;
02143 //     Expr letDeclsExpr;
02144 //     for(Expr::iterator i = e[1].begin(), iend=e[1].end(); i!=iend; ++i) {
02145 //       lvars = i->getKids();
02146 //       lvars.insert(lvars.begin(), Expr(e.getEM(), ID, Expr(e.getEM(), STRING_EXPR, "LETDECL")));
02147 //       letDecls.push_back(Expr(e.getEM(), RAW_LIST, lvars));
02148 //       }
02149 //     letDecls.insert(letDecls.begin(), Expr(e.getEM(), ID, Expr(e.getEM(), STRING_EXPR, "LETDECLS")));
02150 //     letDeclsExpr = Expr(e.getEM(), RAW_LIST, letDecls);
02151 //     return Expr(e.getEM(), kind, parseExpr(letDeclsExpr), parseExpr(e[2]));
02152 //   }
02153   case TRUE:    { return e.getEM()->trueExpr(); }
02154   case FALSE:   { return e.getEM()->falseExpr();}
02155   case BOOLEAN: { return e.getEM()->boolExpr(); }
02156     break;
02157   default:
02158     DebugAssert(false,
02159                 "TheoryCore::parseExprOp: invalid command or expression: "
02160                 + e.toString());
02161     break;
02162   }
02163   return e;
02164 }
02165 
02166 ///////////////////////////////////////////////////////////////////////////////
02167 // Theory-cooperation framework helper functions                             //
02168 ///////////////////////////////////////////////////////////////////////////////
02169 
02170 
02171 void TheoryCore::processFactQueue() {
02172   Theorem thm;
02173   int i;
02174   do {
02175     while (!d_queue.empty() && !d_inconsistent) {
02176       thm = d_queue.front();
02177       d_queue.pop();
02178       assertFactCore(thm);
02179     }
02180     if (d_inconsistent) {
02181       while(d_queue.size()) d_queue.pop();
02182       d_queueSE.clear();
02183       TRACE_MSG("facts addFact", "addFact[top level] => (inconsistent) }");
02184       return;
02185     }
02186     IF_DEBUG(debugger.counter("DP checkSAT calls")++);
02187     for(i=0; i<getNumTheories() && !d_inconsistent && d_queue.empty(); ++i) {
02188       TRACE("facts checkSat", "checkSat[", d_theories[i]->getName(), "]() {");
02189       d_theories[i]->checkSat(false);
02190       TRACE("facts checkSat", "checkSat[", d_theories[i]->getName(), "]() => }");
02191     }
02192     // Flush search engine queue inside the main loop; search engine
02193     // may add new facts to d_queue in the process.
02194     if(d_queue.empty()) {
02195       TRACE_MSG("facts addFact",
02196                 "TheoryCore::processFactQueue(): flushing queueSE");
02197       // The queue may be emptied in the process due to
02198       // setInconsistent() call from the SearchEngine.  Monitor it at
02199       // every iteration.
02200       while(!d_queueSE.empty()) {
02201         // Copy a Theorem by value, to guarantee valid reference down
02202         // the call chain
02203         Theorem thm(d_queueSE.back());
02204         d_queueSE.pop_back();
02205         d_coreSatAPI->addLemma(thm);
02206       }
02207     }
02208   } while (!d_queue.empty());
02209 }
02210 
02211 
02212 #ifdef DEBUG
02213 static void checkRewriteType(TheoryCore* core, const Theorem& thm) {
02214   Type t1(core->getBaseType(thm.getLHS()));
02215   Type t2(core->getBaseType(thm.getRHS()));
02216   DebugAssert(t1 == t2, "TheoryCore::rewriteCore: type-unsafe rewrite:\n"
02217               "type1 = "+t1.toString()+"\ntype2 = "+t2.toString()+"\n\n"
02218               +thm.toString());
02219 }
02220 #endif
02221 
02222 
02223 ///////////////////////////////////////////////////////////////////////////////
02224 // Theory-cooperation framework code implementation                          //
02225 ///////////////////////////////////////////////////////////////////////////////
02226 
02227 
02228 void TheoryCore::setInconsistent(const Theorem& e) {
02229   TRACE("setInconsistent", "setInconsistent(", e, ") {");
02230   d_inconsistent = true; d_incThm = e;
02231   d_queueSE.clear();
02232   // Theory 0 is TheoryCore, skip it
02233   for(int i=1; i<getNumTheories(); ++i) {
02234     TRACE("facts notifyInconsistent", "notifyInconsistent[", d_theories[i]->getName(), "]() {");
02235     d_theories[i]->notifyInconsistent(e);
02236     TRACE("facts notifyInconsistent", "notifyInconsistent[", d_theories[i]->getName(), "]() => }");
02237   }
02238   TRACE_MSG("setInconsistent", "setInconsistent => }");
02239 }
02240 
02241 
02242 void TheoryCore::enqueueFact(const Theorem& e) {
02243   TRACE("enqueueFact", "enqueueFact[Core](", e.getExpr(), ")");
02244   // The theorem scope shouldn't be higher than current
02245   DebugAssert(e.getScope() <= d_cm->scopeLevel(),
02246               "\n e.getScope()="+int2string(e.getScope())
02247               +"\n scopeLevel="+int2string(d_cm->scopeLevel())
02248               +"\n e = "+e.getExpr().toString());
02249   DebugAssert(d_inAddFact || d_inCheckSATCore || d_inRegisterAtom,
02250               "enqueueFact() is called outside of addFact()"
02251               " or checkSATCore() or registerAtom()");
02252   // No need to enqueue when already inconsistent
02253   if(inconsistent()) return;
02254              
02255   IF_DEBUG(if(*d_dumpTrace != "")
02256            dumpTrace(e.getExpr(), "enqueueFact"));
02257   // The theorem scope shouldn't be higher than current
02258   DebugAssert(e.getScope() <= d_cm->scopeLevel(),
02259               "\n e.getScope()="+int2string(e.getScope())
02260               +"\n scopeLevel="+int2string(d_cm->scopeLevel())
02261               +"\n e = "+e.getExpr().toString());
02262   if(!e.isRewrite() && e.getExpr().isFalse()) {
02263     IF_DEBUG(debugger.counter("conflicts enqueued from DPs")++);
02264     setInconsistent(e);
02265   } else if(getResource()) {
02266     d_queue.push(e);
02267   } else {
02268     // No more resources: ignore all the remaining facts and fail
02269     // gracefully
02270     setIncomplete("Exhausted user-specified resource");
02271   }
02272 }
02273 
02274 
02275 void TheoryCore::addFact(const Theorem& e)
02276 {
02277   TRACE("facts addFact", "addFact[top level](", e, ") {");
02278   DebugAssert(!d_inAddFact, "Recursive call to addFact() is not allowed");
02279   DebugAssert(d_queue.empty(), "addFact[start]: Expected empty queue");
02280   DebugAssert(d_queueSE.empty(), "addFact[start]: Expected empty queue");
02281   DebugAssert(d_update_thms.empty() && d_update_data.empty(),
02282               "adFact[start]: Expected empty update list");
02283   IF_DEBUG(ScopeWatcher sw(&d_inAddFact));
02284   IF_DEBUG(if(*d_dumpTrace != "") dumpTrace(e.getExpr(), "addFact"));
02285 
02286   if(!d_inconsistent) enqueueFact(e);
02287 
02288   processFactQueue();
02289 
02290   DebugAssert(d_queue.empty(), "addFact[end]: Expected empty queue");
02291   DebugAssert(d_queueSE.empty(), "addFact[end]: Expected empty queue");
02292 
02293   TRACE_MSG("facts addFact", "addFact[top level] => }");
02294 }
02295 
02296 
02297 void TheoryCore::assertFactCore(const Theorem& e)
02298 {
02299   TRACE("facts assertFact", "assertFactCore(", e, ") {");
02300   const Expr& e2 = e.getExpr();
02301   Theorem equiv = simplify(e2);
02302 
02303   Theorem estarThm(iffMP(e, equiv));
02304   Expr estar = estarThm.getExpr();
02305 
02306   if(estar.isExists()) {
02307     Theorem sk(d_commonRules->skolemize(estarThm));
02308     enqueueFact(sk);
02309     TRACE("skolem", "assertFactCore: created Skolemized assumption:\n ",
02310           sk.getExpr(), "");
02311   }
02312 
02313   // Make sure originally asserted atomic formulas have a find pointer
02314   if(e2 != estar && !e2.isTrue() && e2.isAbsLiteral())
02315     setFindLiteral(e, true);
02316   
02317   if(estar.isAnd()) {
02318     for(int i=0,iend=estar.arity(); i<iend; ++i)
02319       assertFactCore(d_commonRules->andElim(estarThm, i));
02320     TRACE_MSG("facts assertFact", "assertFactCore[AND] => }");
02321     return;
02322   }
02323 
02324   if (estar.isAbsLiteral()) {
02325     if (estar.isEq()) {
02326       // Notify the search engine
02327       enqueueSE(estarThm);
02328       Theorem solvedThm(solve(estarThm));
02329       // Search engine doesn't have to know about estar at this point
02330       if(estar != solvedThm.getExpr()) setFindLiteral(estarThm, false);
02331       assertEqualities(solvedThm);
02332     }
02333     else if (estar.isFalse()) {
02334       IF_DEBUG(debugger.counter("conflicts from simplifier")++);
02335       setInconsistent(estarThm);
02336     }
02337     else if (!estar.isTrue()) {
02338       assertFormula(estarThm);
02339       processUpdates();
02340     }
02341   } else {
02342     // Notify the search engine
02343     enqueueSE(estarThm);
02344   }
02345 
02346   DebugAssert(!e2.isAbsLiteral() || e2.hasFind()
02347               || (e2.isNot() && e2[0].hasFind()),
02348               "assertFactCore: e2 = "+e2.toString());
02349   DebugAssert(!estar.isAbsLiteral() || estar.hasFind()
02350               || (estar.isNot() && estar[0].hasFind()),
02351               "assertFactCore: estar = "+estar.toString());
02352   TRACE_MSG("facts assertFact", "assertFactCore => }");
02353 }
02354 
02355 
02356 /*!
02357  * Invariants: 
02358  * - The input theorem e is either an equality or a conjunction of
02359  *   equalities;
02360  * - In each equality e1=e2, the RHS e2 i-leaf-simplified;
02361  * - At the time of calling update(), all equalities in the queue are
02362  *   processed by assertFormula() and the equivalence classes are merged
02363  *   in the union-find database.
02364  *
02365  * In other words, the entire equality queue is processed "in parallel".
02366  */
02367 
02368 void TheoryCore::assertEqualities(const Theorem& e)
02369 {
02370   TRACE("facts eq", "assertEqualities(", e, ") {");
02371   DebugAssert(d_equalityQueue.empty(), "TheoryCore::assertEqualities()");
02372   enqueueEquality(e);
02373 
02374   while(!d_equalityQueue.empty()) {
02375     // We need to be careful: first copy the queue to a separate map
02376     // (to eliminate duplicates) and empty the "official" queue, so
02377     // that DPs can safely enqueue new equalities.
02378 
02379     ExprMap<Theorem> q;
02380     for(vector<Theorem>::iterator i=d_equalityQueue.begin(),
02381           iend=d_equalityQueue.end(); i!=iend; ++i) {
02382       if(processEquality(*i, q)) {
02383         // Derived inconsistency
02384         TRACE_MSG("facts eq", "assertEqualities[FALSE] => }");
02385         d_equalityQueue.clear();
02386         return;
02387       }
02388     }
02389     d_equalityQueue.clear();
02390 
02391     // Check invariants and assert the equations to the DPs
02392     for(ExprMap<Theorem>::iterator i=q.begin(), iend=q.end(); i!=iend; ++i) {
02393       const Theorem& e = i->second;
02394       DebugAssert(e.isRewrite(), "");
02395       DebugAssert(e.getLHS().isTerm(), "term expected");
02396 
02397       assertFormula(e);
02398     }
02399 
02400     // Merge the equivalence classes
02401     for(ExprMap<Theorem>::iterator i=q.begin(), iend=q.end(); i!=iend; ++i) {
02402       const Theorem& e = i->second;
02403       DebugAssert(find(e.getLHS()).getRHS() == e.getLHS(),
02404                   "find error: e = "+e.getExpr().toString()
02405                   +"\n\n  find(e.getLHS()) = "
02406                   +find(e.getLHS()).getRHS().toString());
02407       DebugAssert(find(e.getRHS()).getRHS() == e.getRHS(),
02408                   "find error: e = "+e.getExpr().toString()
02409                   +"\n\n  find(e.getRHS()) = "
02410                   +find(e.getRHS()).getRHS().toString());
02411 //       DebugAssert(leavesAreSimp(e.getRHS()), "assertEqualities("
02412 //                +e.toString()+")");
02413       
02414       e.getLHS().setFind(e);
02415     }
02416 
02417     d_em->invalidateSimpCache();
02418   
02419     // Call the update() functions (process NotifyLists).  
02420 
02421     for(ExprMap<Theorem>::iterator i=q.begin(), iend=q.end(); i!=iend; ++i) {
02422       const Theorem& e = i->second;
02423       NotifyList *L = e.getLHS().getNotify();
02424       if (L) processNotify(e, L);
02425     }
02426   }
02427   processUpdates();
02428   TRACE_MSG("facts eq", "assertEqualities => }");
02429 }
02430 
02431 
02432 void TheoryCore::assertFormula(const Theorem& thm)
02433 {
02434   TRACE("facts assertFact", "assertFormula(", thm, ") {");
02435   const Expr& e = thm.getExpr();
02436   if (e.isAbsLiteral()) {
02437     Theory* i = theoryOf(e);
02438     // (Dis)equalities should also be asserted to the theories of
02439     // their types for concrete model generation 
02440     Theory* i2(NULL);
02441     // Treat disequality as a separate theory, so that terms are
02442     // reported as shared
02443     if(e.isNot() && e[0].isEq())
02444       setupTerm(e, this);
02445     else
02446       setupTerm(e,i);
02447 
02448     // Use find to force af to rewrite to TRUE and NOT af to rewrite to FALSE,
02449     // where af is an atomic formula.  If af is an equality, make sure its lhs
02450     // is greater than its rhs so the simplifier will be able to use the find.
02451     enqueueSE(thm);
02452     Theorem findThm;
02453     NotifyList* L;
02454     if (e.isNot()) {
02455       DebugAssert(!e[0].hasFind(), "already has find");
02456       if (e[0].isEq()) {
02457         // Save the disequality for later processing
02458         d_diseq.push_back(thm);
02459         // For concrete model generation
02460         i2 = theoryOf(getBaseType(e[0][0]).getExpr()); 
02461 
02462         if(e[0][0] < e[0][1]) {
02463           Expr e2 = e[0][1].eqExpr(e[0][0]);
02464           DebugAssert(!e2.hasFind(), "already has find");
02465           findThm = transitivityRule(d_commonRules->rewriteUsingSymmetry(e2),
02466                                      d_commonRules->notToIff(thm));
02467           e2.setFind(findThm);
02468           d_em->invalidateSimpCache();
02469           L = e2.getNotify();
02470           if (L) processNotify(findThm, L);
02471         }
02472       }
02473       findThm = d_commonRules->notToIff(thm);
02474       e[0].setFind(findThm);
02475       d_em->invalidateSimpCache();
02476       L = e[0].getNotify();
02477       if (L) processNotify(findThm, L);
02478     }
02479     else {
02480       // If we are called from assertEqualities(), we may get e1=e2
02481       // for which there is a known fact e1/=e2 or e2/=e1.  In this
02482       // case, we should derive a contradiction.
02483       // Note, that this is not necessarily detected by the DPs.
02484       if(e.hasFind()) {
02485         // Why would find(e) be always false?  Not if we set find to
02486         // all atomic formulas...
02487 //      DebugAssert(find(e).getRHS().isFalse(), "e = "+e.toString()
02488 //                  +"\nfind(e) = "+find(e).getRHS().toString());
02489         findThm = find(e);
02490         if(findThm.getExpr().isFalse()) {
02491           IF_DEBUG(debugger.counter("conflicts from find pointers")++);
02492           setInconsistent(d_commonRules->contradictionRule(thm,
02493                             d_commonRules->iffFalseElim(find(e))));
02494           TRACE_MSG("facts assertFact", "assertFormula[contradiction] => }");
02495           return;
02496         }
02497       }
02498       else {
02499         findThm = d_commonRules->iffTrue(thm);
02500         e.setFind(findThm);
02501         d_em->invalidateSimpCache();
02502         L = e.getNotify();
02503         if (L) processNotify(findThm, L);
02504       }
02505 
02506       if(e.isEq()) {
02507         if(e[0] < e[1]) {
02508           Expr e2 = e[1].eqExpr(e[0]);
02509           if(e2.hasFind()) {
02510 //          DebugAssert(find(e2).getRHS().isFalse(), "e2 = "+e2.toString()
02511 //                      +"\nfind(e2) = "+find(e2).getRHS().toString());
02512             findThm = find(e2);
02513             if(findThm.getExpr().isFalse()) {
02514               IF_DEBUG(debugger.counter("conflicts from find pointers")++);
02515               setInconsistent(d_commonRules->contradictionRule(
02516                                 symmetryRule(thm),
02517                                 d_commonRules->iffFalseElim(find(e2))));
02518               TRACE_MSG("facts assertFact", "assertFormula[e[1]/=e[0]] => }");
02519               return;
02520             }
02521           } else {
02522             findThm = transitivityRule(d_commonRules->rewriteUsingSymmetry(e2),
02523                                        d_commonRules->iffTrue(thm));
02524             e2.setFind(findThm);
02525             d_em->invalidateSimpCache();
02526             L = e2.getNotify();
02527             if (L) processNotify(findThm, L);
02528           }
02529         }
02530       }
02531     }
02532     d_em->invalidateSimpCache();
02533     // Do not send existential quantifiers to DPs; skolemize them and
02534     // notify the Search Engine about it.
02535     if(thm.getExpr().isExists())
02536       enqueueFact(d_commonRules->skolemize(thm));
02537     else {
02538       TRACE("facts assertFact", ("assertFact[->" + i->getName() + "]("), thm, ") {");
02539       i->assertFact(thm);
02540       TRACE("facts assertFact", "assertFact[->", i->getName(),"] => }");
02541       if(i2 != NULL && i != i2) {
02542         TRACE("facts assertFact", ("assertFact[->" + i2->getName() + "]("), thm, ") {");
02543         IF_DEBUG(debugger.counter("assertFact(diseq) by type")++);
02544         i2->assertFact(thm);
02545         TRACE("facts assertFact", "assertFact[->", i2->getName(),"] => }");
02546       }
02547     }
02548   }
02549   else {
02550     DebugAssert(false,"assertFormula: nonliteral asserted:\n  "
02551                 +thm.toString());
02552   }
02553   TRACE_MSG("facts assertFact", "assertFormula => }");
02554 }
02555 
02556 
02557 void TheoryCore::setupTerm(const Expr& t, Theory* i)
02558 {
02559   TRACE("facts setup", "setupTerm(", t, ", i="+i->getName()+") {");
02560 
02561   // Even if t is already setup, it may become shared with another theory
02562   Theory* j = theoryOf(t);
02563   if(i != j && t.isTerm()) {
02564     TRACE("facts setup", "addSharedTerm[->"+j->getName()+"](", t, ") {");
02565     j->addSharedTerm(t);
02566     TRACE_MSG("facts setup", "addSharedTerm[->"+j->getName()+"] => }");
02567     TRACE("facts setup", "addSharedTerm[->"+i->getName()+"](", t, ") {");
02568     i->addSharedTerm(t);
02569     TRACE_MSG("facts setup", "addSharedTerm[->"+i->getName()+"] => }");
02570     d_sharedTerms.insert(t, j);
02571   }
02572   
02573   int k;
02574 
02575   // Atomic formulas (non-terms) may have find pointers without the
02576   // subterms being setup.  Recurse down to the terms before checking
02577   // for find pointers.
02578   if (!t.isTerm()) {
02579     if(t.isAbsLiteral()) {
02580       for (k = 0; k < t.arity(); ++k) {
02581         setupTerm(t[k], i);
02582       }
02583       TRACE("facts setup", "setup[->"+j->getName()+"](", t, ") {");
02584       j->setup(t);
02585       TRACE("facts setup", "setup[->",j->getName(),"] => }");
02586     }
02587     TRACE_MSG("facts setup", "setupTerm[not term] => }");
02588     return;
02589   }
02590 
02591   // If already setup, nothing else to do
02592   if (t.hasFind()) {
02593     TRACE_MSG("facts setup", "setupTerm[has find] => }");
02594     return;
02595   }
02596 
02597   // Proceed with the setup
02598 
02599   // Add the term into the set of all terms
02600   d_terms.push_back(t);
02601 
02602   for (k = 0; k < t.arity(); ++k) {
02603     setupTerm(t[k],theoryOf(t));
02604   }
02605   Theorem thm = d_commonRules->reflexivityRule(t);
02606   t.setFind(thm);
02607   TRACE("facts setup", "setup[->"+j->getName()+"](", t, ") {");
02608   j->setup(t);
02609   TRACE("facts setup", "setup[->",j->getName(),"] => }");
02610 
02611   // Assert the subtyping predicate AFTER the setup is complete
02612   Theorem pred = d_rules->typePred(t);
02613   // pred = d_commonRules->iffMP(pred, simplify(pred.getExpr()));
02614   const Expr& predExpr = pred.getExpr();
02615   // TRACE("tccs", "setupTerm: subtype predicate:\n", predExpr, "");
02616   if(predExpr.isFalse()) {
02617     IF_DEBUG(debugger.counter("conflicts from type preficate")++);
02618     setInconsistent(pred); 
02619   }
02620   else if(!predExpr.isTrue()) {
02621     Theory* k = theoryOf(t.getType().getExpr());
02622     TRACE("facts setup", "assertTypePred[->"+k->getName()+"]("
02623           +t.toString()+", ", pred, ") {");
02624     k->assertTypePred(t, pred);
02625     TRACE_MSG("facts setup", "assertTypePred[->"+k->getName()+"] => }");
02626   }
02627 
02628   d_typePredAsserted[t] = true;
02629   TRACE_MSG("facts setup", "setupTerm => }");
02630 }
02631 
02632 
02633 Theorem TheoryCore::rewriteCore(const Expr& e)
02634 {
02635   TRACE("rewrite", "rewriteCore(", e, ") {");
02636   if (e.hasFind()) {
02637     TRACE("rewrite", "rewriteCore[hasFind] => ", find(e), " }");
02638     IF_DEBUG(checkRewriteType(this, find(e)));
02639     return find(e);
02640   }
02641   if (e.isRewriteNormal()) {
02642     IF_DEBUG(
02643       // Check that the RewriteNormal flag is set properly.  Note that we
02644       // assume theory-specific rewrites are idempotent
02645       e.clearRewriteNormal();
02646       Expr rewritten(rewriteCore(e).getRHS());
02647       e.setRewriteNormal(); // Restore the flag
02648       DebugAssert(rewritten == e, 
02649                   "Expected no change: e = " + e.toString()
02650                   +"\n rewriteCore(e) = "+rewritten.toString());
02651     )
02652     TRACE("rewrite", "rewriteCore[isRewriteNormal] => ", reflexivityRule(e), " }");
02653     return reflexivityRule(e);
02654   }
02655   Theorem thm;
02656   if (e.isNot() || e.isEq()) {
02657     TRACE("rewrite", "rewriteLitCore(", e, ") {");
02658     thm = rewriteLitCore(e);
02659     IF_DEBUG(checkRewriteType(this, thm));
02660     TRACE("rewrite", "rewriteLitCore => ", thm, "}");
02661     if(e != thm.getRHS()) {
02662       thm = rewriteCore(thm);
02663       TRACE("rewrite", "rewriteCore => ", thm, " }");
02664       return thm;
02665     }
02666   }
02667   TRACE("rewrite", ("rewrite["+theoryOf(e)->getName()+"]("), e, ") {");
02668   thm = theoryOf(e)->rewrite(e);
02669   TRACE("rewrite", ("rewrite["+theoryOf(e)->getName()+"] => "), thm, "}");
02670   IF_DEBUG(checkRewriteType(this, thm));
02671 
02672   const Expr& e2 = thm.getRHS();
02673 
02674   // Theory-specific rewrites for equality should ensure that lhs >= rhs, or
02675   // there is danger of an infinite loop.
02676   DebugAssert(!e2.isEq() || e2[0] >= e2[1],
02677               "theory-specific rewrites for equality should ensure lhs >= rhs");
02678 
02679   if (e != e2) {
02680     thm = rewriteCore(thm);
02681     TRACE("rewrite", "rewriteCore => ", thm, " }");
02682     return thm;
02683   }
02684 
02685   TRACE("rewrite", "rewriteCore[refl] => ", thm, " }");
02686   return thm;
02687 }
02688 
02689 
02690 bool TheoryCore::checkSATCore() {
02691   TRACE_MSG("facts checkSat", "checkSATCore() {");
02692   DebugAssert(d_queue.empty(), "checkSATCore[start]: Expected empty queue");
02693   DebugAssert(d_queueSE.empty(), "checkSATCore[start]: Expected empty queue");
02694   DebugAssert(!d_inCheckSATCore, "Recursive call to checkSATCore is not allowed!");
02695   IF_DEBUG(ScopeWatcher sw(&d_inCheckSATCore));
02696   IF_DEBUG(debugger.counter("DP checkSAT(fullEffort) calls")++);
02697   for(int i=0; i<getNumTheories() && !d_inconsistent && d_queue.empty(); ++i) {
02698     TRACE("facts checkSat", "checkSAT (full effort) [",
02699           d_theories[i]->getName(), "]() {");
02700     d_theories[i]->checkSat(true);
02701     TRACE("facts checkSat", "checkSAT (full effort) [",
02702           d_theories[i]->getName(), "]() }");
02703   }
02704 
02705   if(d_queue.empty()) {
02706     DebugAssert(d_queueSE.empty(),
02707                 "checkSATCore[start]: Expected empty queue");
02708     TRACE_MSG("facts checkSat", "checkSATCore[queue empty] => true }");
02709     return true;
02710   } 
02711 
02712   // Process enqueued facts
02713   processFactQueue();
02714  
02715   TRACE("facts checkSat", "checkSATCore => ",
02716         d_inconsistent? "true" : "false", " }");
02717 
02718   DebugAssert(d_queue.empty(), "checkSATCore[start]: Expected empty queue");
02719   DebugAssert(d_queueSE.empty(), "checkSATCore[start]: Expected empty queue");
02720 
02721   return(d_inconsistent); 
02722 }
02723 
02724 
02725 void TheoryCore::addToVarDB(const Expr&  e)
02726 {
02727   TRACE("model", "TheoryCore::addToVarDB(", e, ")");
02728   d_vars.push_back(e);
02729 }
02730 
02731 
02732 void TheoryCore::refineCounterExample()
02733 {
02734   // Theory 0 is TheoryCore, skip it
02735   for(int i = 1; i<getNumTheories(); i++) {
02736     if(d_theories[i] != this)
02737       d_theories[i]->refineCounterExample();
02738     if(inconsistent()) {
02739       vector<Expr> assump;
02740       inconsistentThm().getLeafAssumptions(assump);
02741       Expr a = Expr(RAW_LIST, assump, d_em);
02742       throw EvalException("Theory["+d_theories[i]->getName()
02743                       +"]: Model Creation failed due "
02744                       "to the following assumptions:\n\n"
02745                       +a.toString()
02746                       +"\n\nYou might be using an incomplete logical fragment.");
02747     }
02748   }
02749 }
02750 
02751 
02752 void TheoryCore::computeModelBasic(const vector<Expr>& v) {
02753   for(vector<Expr>::const_iterator i=v.begin(), iend=v.end(); i!=iend; ++i) {
02754     TRACE("model", "Model var "+i->toString()+" = ", find(*i).getRHS(), "");
02755     DebugAssert((*i).getType().isBool(), "TheoryCore::computeModel: *i = "
02756                 +(*i).toString());
02757     Expr val = find(*i).getRHS();
02758     if(!val.isBoolConst()) val = d_em->trueExpr();
02759     assignValue(*i, val);
02760   }
02761 }
02762 
02763 
02764 void TheoryCore::collectBasicVars() {
02765   TRACE_MSG("model", "collectBasicVars() {");
02766   // Clear caches
02767   d_varModelMap.clear();
02768   d_varAssignments.clear();
02769   // Current stack of variables to process
02770   vector<Expr> stack(d_vars.begin(), d_vars.end());
02771   size_t lastSize(0);
02772   while(stack.size() > 0) {
02773     Expr var(stack.back());
02774     stack.pop_back();
02775     if(d_varModelMap.count(var) > 0) continue; // Already processed
02776     Theorem findThm(find(var));
02777     if(findThm.getRHS()!=var) { // Replace var with its find
02778       d_simplifiedModelVars[var] = findThm;
02779       stack.push_back(findThm.getRHS());
02780       TRACE("model", "collectBasicVars: simplified var: ", findThm.getExpr(), "");
02781       continue; // Recycle to the beginning of the loop
02782     }
02783     lastSize = stack.size();
02784     TRACE("model", "getModelTerm(", var, ") {");
02785     getModelTerm(var, stack);
02786     TRACE("model", "getModelTerm => ",
02787           Expr(RAW_LIST, stack, getEM()), " }");
02788     if(stack.size() == lastSize) {
02789       // Add a primitive variable
02790       TRACE("model", "collectBasicVars: adding primitive var: ", var, "");
02791       d_basicModelVars.push_back(var);
02792       if(var.isTerm()) {
02793         Theory* t1 = theoryOf(var);
02794         Theory* t2 = theoryOf(getBaseType(var).getExpr().getKind());
02795         if(t1 != t2) {
02796           TRACE("model", "collectBasicVars: adding shared var: ", var, "");
02797           d_sharedTerms.insert(var, t1);
02798           t1->addSharedTerm(var);
02799           t2->addSharedTerm(var);
02800         }
02801       }
02802     } else { // Record the descendants of var
02803       vector<Expr>& kids = d_varModelMap[var];
02804       for(size_t i=lastSize; i<stack.size(); ++i) {
02805         DebugAssert(stack[i] != var, "Primitive var was pushed on "
02806                     "the stack in computeModelTerm(): "+var.toString());
02807         kids.push_back(stack[i]);
02808       }
02809       TRACE("model", "collectBasicVars: var="+var.toString()
02810             +" maps into vars=", Expr(RAW_LIST, kids, getEM()), "");
02811     }
02812   }
02813   TRACE_MSG("model", "collectBasicVars() => }");
02814 }
02815 
02816 
02817 void TheoryCore::buildModel(ExprMap<Expr>& m) {
02818   TRACE_MSG("model", "buildModel() {");
02819 
02820   size_t numTheories = getNumTheories();
02821   // Use STL set to prune duplicate variables in theories
02822   set<Expr> theoryExprs[numTheories+1];
02823   // Sort out model vars by theories
02824   for(size_t j = 0 ; j<d_basicModelVars.size() ; j++) {
02825     const Expr& var = d_basicModelVars[j];
02826     Theorem findThm(find(var));
02827     if(findThm.getRHS()!=var) { // Replace var with its find and skip it
02828       TRACE("model", "buildModel: replace var="+var.toString(),
02829             " with find(var)=", findThm.getRHS());
02830       d_simplifiedModelVars[var] = findThm;
02831       continue;
02832     }
02833 
02834     Theory *th = theoryOf(getBaseType(var).getExpr().getKind());
02835     size_t i=0;
02836     for(; i<numTheories && d_theories[i] != th; ++i);
02837     DebugAssert(i<numTheories && d_theories[i] == th,
02838                 "TheoryCore::buildModel: cannot find the theory ["
02839                 +th->getName()+"] for the variable: "
02840                 +var.toString());
02841     theoryExprs[i].insert(var);
02842     TRACE("model", "buildModel: adding ", var,
02843           " to theory "+d_theories[i]->getName());
02844   }
02845   // Build a model for the basic-type variables
02846   for(int i=0; i<getNumTheories(); i++) {
02847     if(theoryExprs[i].size() > 0) {
02848       TRACE("model", "computeModelBasic[", d_theories[i]->getName(), "] {");
02849       // Copy the corresponding variables into a vector
02850       vector<Expr> vars;
02851       vars.insert(vars.end(), theoryExprs[i].begin(), theoryExprs[i].end());
02852       d_theories[i]->computeModelBasic(vars);
02853       TRACE("model", "computeModelBasic[", d_theories[i]->getName(), "] => }");
02854       if(inconsistent()) {
02855         vector<Expr> assump;
02856         inconsistentThm().getLeafAssumptions(assump);
02857         Expr a = Expr(RAW_LIST, assump, d_em);
02858         throw EvalException
02859           ("Model Creation failed in Theory["
02860            +d_theories[i]->getName()
02861            +"] due to the following assumptions:\n\n"
02862            +a.toString()
02863            +"\n\nYou might be using an incomplete logical fragment.");
02864       }
02865     }
02866   }
02867   // Recombine the values for the compound-type variables
02868   ExprHashMap<Theorem>::iterator k, kend=d_simplifiedModelVars.end();
02869   for(CDList<Expr>::const_iterator i=d_vars.begin(), iend=d_vars.end(); i!=iend; ++i) {
02870     Expr var(*i);
02871     TRACE("model", "buildModel: recombining var=", var, "");
02872     k=d_simplifiedModelVars.find(var);
02873     Theorem simp; // Null by default
02874     if(k!=kend) { // This var is simplified
02875       simp = k->second;
02876       TRACE("model", "buildModel: simplified var="+var.toString()+" to ",
02877             simp.getRHS(), "");
02878       var = simp.getRHS();
02879     }
02880     collectModelValues(var, m);
02881     if(d_varAssignments.count(var) > 0) {
02882       if(!simp.isNull()) {
02883         Theorem thm(transitivityRule(simp, d_varAssignments[var]));
02884         assignValue(thm);
02885         DebugAssert(thm.getLHS() == *i, "");
02886         m[*i] = thm.getRHS();
02887       } else
02888         m[*i] = d_varAssignments[var].getRHS();
02889     }
02890 //     else if(simp.isNull())
02891 //       m[*i] = *i;
02892 //     else
02893 //       m[*i] = simp.getRHS();
02894   }
02895   TRACE_MSG("model", "buildModel => }");
02896 }
02897 
02898 
02899 // Recursively build a compound-type variable assignment for e
02900 /*! Not all theories may implement aggregation of compound values.  If
02901  *  a compound variable is not assigned by a theory, add the more
02902  *  primitive variable assignments to 'm'.
02903  *
02904  * Some variables may simplify to something else (simplifiedVars map).
02905  * INVARIANT: e is always simplified (it's not in simplifiedVars map).
02906  * Also, if v simplifies to e, and e is assigned, then v must be assigned.
02907  */
02908 void TheoryCore::collectModelValues(const Expr& e, ExprMap<Expr>& m) {
02909   TRACE("model", "collectModelValues(", e, ") {");
02910   if(d_varAssignments.count(e) > 0) {
02911     TRACE("model", "collectModelValues[cached] => ",
02912           d_varAssignments[e].getRHS(), " }");
02913     return; // Got it already
02914   }
02915   ExprHashMap<Theorem>::iterator k, kend=d_simplifiedModelVars.end();
02916   k=d_simplifiedModelVars.find(e);
02917   if(k!=kend) {
02918     const Theorem& findThm = k->second;
02919     const Expr& ee = findThm.getRHS();
02920     collectModelValues(ee, m);
02921     if(d_varAssignments.count(ee) > 0) {
02922       Theorem thm = transitivityRule(findThm, d_varAssignments[ee]);
02923       assignValue(thm);
02924     }
02925     TRACE("model", "collectModelValues[simplified] => ",
02926           d_varAssignments[e].getRHS(), " }");
02927     return;
02928   }
02929   if(d_varModelMap.count(e) == 0) { // Consider it a value of itself
02930     assignValue(reflexivityRule(e));
02931     TRACE("model", "collectModelValues[e=e] => ", e, " }");
02932     return; // Got it already
02933   }
02934   // Get the vector of more primitive vars
02935   const vector<Expr>& vars = d_varModelMap[e];
02936   // Recurse
02937   bool gotAll(true);  // Whether we got all the values
02938   for(vector<Expr>::const_iterator i=vars.begin(), iend=vars.end(); i!=iend; ++i) {
02939     Expr var(*i);
02940 //     k=d_simplifiedModelVars.find(var);
02941 //     Theorem simp; // Null by default
02942 //     if(k!=kend) { // This var is simplified
02943 //       simp = k->second;
02944 //       var = simp.getRHS();
02945 //     }
02946     collectModelValues(var, m);
02947     if(d_varAssignments.count(var) == 0) {
02948       gotAll = false;
02949     }
02950 //     else if(!simp.isNull()) {
02951 //       Theorem thm(transitivityRule(simp, d_varAssignments[var]));
02952 //       DebugAssert(thm.getLHS() == *i, "");
02953 //       assignValue(thm);
02954 //     }
02955   }
02956   IF_DEBUG(vector<Expr> res);
02957   if(gotAll) {
02958     vector<Expr> assigned; // What DP actually assigns
02959     Theory* th = theoryOf(getBaseType(e).getExpr());
02960     TRACE("model", "computeModel["+th->getName()+"](", e, ") {");
02961     th->computeModel(e, assigned);
02962     TRACE("model", "computeModel["+th->getName()+"] => ",
02963           Expr(RAW_LIST, assigned, getEM()), " }");
02964     // Check if the assigned vars are different from e
02965     if(!(assigned.size()==1 && assigned[0]==e)) {
02966       //    if(d_varAssignments.count(e) == 0) {
02967       for(vector<Expr>::iterator i=assigned.begin(), iend=assigned.end();
02968           i!=iend; ++i) {
02969         if(*i == e) continue; // Skip the original var
02970         m[*i] = getModelValue(*i).getRHS();
02971         IF_DEBUG(res.push_back(getModelValue(*i).getExpr()));
02972       }
02973     } else {
02974       IF_DEBUG(res.push_back(getModelValue(e).getExpr()));
02975     }
02976   }
02977   TRACE("model", "collectModelValues => ",
02978         Expr(RAW_LIST, res, getEM()), " }");
02979 }
02980 
02981 
02982 void TheoryCore::enqueueEquality(const Theorem& e) {
02983   TRACE("enqueueEquality", "enqueueEquality["+getName()+"](",
02984         e.getExpr(), ")");
02985   IF_DEBUG(if(*d_dumpTrace != "")
02986            dumpTrace(e.getExpr(), "enqueueEquality"));
02987   IF_DEBUG(const Expr& expr = e.getExpr());
02988   IF_DEBUG(int kind = expr.getKind());
02989   DebugAssert(kind == EQ || kind == AND || kind == EXISTS || kind == FALSE,
02990               "enqueueEnquality: bad input: "+expr.toString());
02991   // The theorem scope shouldn't be higher than current
02992   DebugAssert(e.getScope() <= d_cm->scopeLevel(),
02993               "\n e.getScope()="+int2string(e.getScope())
02994               +"\n scopeLevel="+int2string(d_cm->scopeLevel())
02995               +"\n e = "+expr.toString());
02996 //   DebugAssert(kind != EQ || !expr[0].subExprOf(expr[1]),
02997 //            "enqueueEquality("+expr.toString()+")");
02998   d_equalityQueue.push_back(e);
02999 }
03000 
03001 
03002 /*!
03003  * Fill in the copy of the equality queue with single equalities by
03004  * processing the input 'eq', which can be an equality, a conjunction
03005  * of equalities, or an existential quantifier of the above.
03006  */
03007 bool TheoryCore::processEquality(const Theorem& thm, ExprMap<Theorem>& q) {
03008   const Expr& e = thm.getExpr();
03009   TRACE("facts eq", "processEquality(", e, ") {");
03010   bool res(false);
03011 
03012   switch(e.getKind()) {
03013   case FALSE:
03014     IF_DEBUG(debugger.counter("conflicts from solver")++);
03015     setInconsistent(thm);
03016     res = true;
03017     break;
03018   case EXISTS:
03019     // Skolemize the quantifier and expect an equality or a
03020     // conjunction of equalities inside
03021     res = processEquality(d_commonRules->skolemize(thm), q);
03022     break;
03023   case AND: 
03024     for(int i=0, iend=e.arity(); i!=iend; ++i)
03025       if(res = processEquality(d_commonRules->andElim(thm, i), q)) break;
03026     break;
03027   case EQ:
03028     // find(e0) != e1 && find(e1) != e0
03029     if(find(e[0]).getRHS() != e[1] && e[0] != find(e[1]).getRHS()) {
03030       DebugAssert(e[0] != e[1], "processEquality: e = "+e.toString());
03031       DebugAssert(!e[1].hasFind() || find(e[1]).getRHS() == e[1],
03032                   "processEquality: e = "+e.toString()
03033                   +"\nfind(e[1]) = "+find(e[1]).getRHS().toString());
03034 //       DebugAssert(!e[0].subExprOf(e[1]), "processEquality: e = "+e.toString());
03035       q[e] = thm;
03036       TRACE("facts eq", "  [new]  ", e, ",\n");
03037     } else if(find(e).getRHS().isFalse()) {
03038       TRACE("facts eq", " [FALSE] ", e,  "]");
03039       IF_DEBUG(debugger.counter("conflicts from find pointers")++);
03040       setInconsistent(d_commonRules->contradictionRule(thm,
03041                         d_commonRules->iffFalseElim(find(e))));
03042       res = true;
03043     } else {
03044       TRACE("facts eq", "         ", e, ",");
03045     }
03046     break;
03047   default:
03048     DebugAssert(false,
03049                 "TheoryCore::processEquality(): bad input:\n "
03050                 +thm.toString());
03051   }
03052   TRACE("facts eq", "processEquality => ", res? "true" : "false", " }");
03053   return res;
03054 }
03055 
03056 
03057 void TheoryCore::processNotify(const Theorem& e, NotifyList *L)
03058 {
03059   DebugAssert(L, "Expected non-NULL notify list");
03060   // L may be changing during update() call; copy it to a local
03061   // vector before calling update()
03062   //  vector<pair<Theory*, Expr> > l;
03063   //  for (unsigned k = 0, size = L->size(); k < size; ++k) {
03064   //    l.push_back(pair<Theory*,Expr>(L->getTheory(k), L->getExpr(k)));
03065   //  }
03066   for(unsigned k = 0; k < L->size(); ++k) {
03067     TRACE("facts update", "update["+L->getTheory(k)->getName()+"]("
03068           +e.toString()+", ", L->getExpr(k), ") {");
03069     L->getTheory(k)->update(e, L->getExpr(k));
03070     TRACE("facts update", "update[", L->getTheory(k)->getName(), "] => }");
03071   }
03072 }
03073 
03074 
03075 void TheoryCore::setIncomplete(const string& reason) {
03076   d_incomplete.insert(reason, true);
03077 }
03078 
03079 
03080 void
03081 TheoryCore::setResourceLimit(unsigned limit) {
03082   d_resourceLimit = limit;
03083 }
03084 
03085 
03086 IF_DEBUG(static ExprMap<bool> simpStack);
03087 
03088 Theorem TheoryCore::simplify(const Expr& e, bool forceRebuild)
03089 {
03090   TRACE("simplify", "simplify(", e, ") {");
03091   IF_DEBUG(ScopeWatcher sw(&d_inSimplify));
03092   Theorem (TheoryCore::*oldSimplifier)(const Expr&) = d_currentRecursiveSimplifier;
03093 
03094   if (*d_simplifyInPlace) {
03095     if (!forceRebuild) {
03096       d_currentRecursiveSimplifier = &CVCL::TheoryCore::simplifyInPlaceRec;
03097       Theorem res(simplifyRec(e));
03098       d_currentRecursiveSimplifier = oldSimplifier;
03099       TRACE("simplify", "simplify[in place] => ", res.getRHS(), " }");
03100       return res;
03101     }
03102     else {
03103       d_currentRecursiveSimplifier = &CVCL::TheoryCore::simplifyFullRec;
03104       d_em->invalidateSimpCache();
03105       Theorem thm = simplifyRec(e);
03106       d_em->invalidateSimpCache();
03107       if (!e.isAbsLiteral() && e != thm.getRHS()) {
03108         e.setFind(thm);
03109       }
03110       d_currentRecursiveSimplifier = oldSimplifier;
03111       TRACE("simplify", "simplify[rebuild] => ", thm.getRHS(), " }");
03112       return thm;
03113     }
03114   }
03115   d_currentRecursiveSimplifier = &CVCL::TheoryCore::simplifyFullRec;
03116   Theorem res(simplifyRec(e));
03117   d_currentRecursiveSimplifier = oldSimplifier;
03118   TRACE("simplify", "simplify => ", res.getRHS(), " }");
03119   return res;
03120 }
03121 
03122 
03123 Theorem TheoryCore::simplifyRec(const Expr& e)
03124 {
03125   DebugAssert(d_currentRecursiveSimplifier, "unexpected call to simplifyRec");
03126   return (this->*d_currentRecursiveSimplifier)(e);
03127 }
03128 
03129 
03130 Theorem TheoryCore::simplifyFullRec(const Expr& e)
03131 {
03132   TRACE("simplifyRec", "simplifyRec(", e, ") {");
03133   DebugAssert(simpStack.count(e) == 0, "TheoryCore::simplifyRec: loop detected over e =\n"
03134               +e.toString());
03135   TRACE("simplify stack", "simpStack.size = ", simpStack.size(), "");
03136   DebugAssert(simpStack.size() < 10000,
03137               "TheoryCore::simplify: too deep recursion depth");
03138   IF_DEBUG(simpStack[e] = true);
03139   Theorem thm;
03140   if(e.hasFind()) {
03141     thm = find(e);
03142     const Expr& e2 = thm.getRHS();
03143     if (e2.hasFind()) {
03144       DebugAssert(e2.isTrue() || e2.isFalse() || e2.isTerm(),
03145                   "Unexpected find pointer");
03146       TRACE_MSG("simplifyRec", "Using find");
03147       TRACE("simplifyRec", "simplify => ", thm, "}\n");
03148       IF_DEBUG(simpStack.erase(e));
03149       return thm;
03150     }
03151     else {
03152       DebugAssert(!e.isAbsLiteral(), "Expected non-literal: e = "+e.toString()
03153                   +"\n e2 = "+e2.toString());
03154       DebugAssert(*d_simplifyInPlace, "Expected in-place flag: e = "
03155                   +e.toString()+"\n e2 = "+e2.toString());
03156       Theorem thm2 = simplifyRec(e2);
03157       if (thm2.getLHS() != thm2.getRHS()) {
03158         e.setFind(transitivityRule(thm,thm2));
03159         TRACE_MSG("simplifyRec", "Using find 2");
03160         TRACE("simplifyRec", "simplify => ", e.getFind(), "}\n");
03161         IF_DEBUG(simpStack.erase(e));
03162         return e.getFind();
03163       }
03164       TRACE_MSG("simplifyRec", "Using find 3");
03165       TRACE("simplifyRec", "simplify => ", thm, "}\n");
03166       IF_DEBUG(simpStack.erase(e));
03167       return thm;
03168     }
03169  }
03170 
03171   if(e.validSimpCache()) {
03172     TRACE_MSG("simplifyRec", "Using cached result");
03173     TRACE("simplifyRec", "simplify => ", e.getSimpCache(), "}\n");
03174     IF_DEBUG(simpStack.erase(e));
03175     return e.getSimpCache();
03176   }
03177 
03178   // Optimization: check both sides of = or <=> for syntactic equality
03179   switch(e.getKind()) {
03180   case EQ:
03181   case IFF:
03182     if(e[0]==e[1]) {
03183       thm = d_commonRules->iffTrue(reflexivityRule(e[0]));
03184       IF_DEBUG(debugger.counter("simplified x=x")++);
03185       break; // Break out of switch()
03186     }
03187     // Otherwise fall through
03188   default: // Make a recursive call
03189     TRACE("simplifyRec", "simplifyOp["+theoryOf(e)->getName()+"](",
03190           e, ") {");
03191     thm = theoryOf(e)->simplifyOp(e);
03192     TRACE("simplifyRec", "simplifyOp["+theoryOf(e)->getName()+"] => ",
03193           thm.getRHS(), " }");
03194     thm = rewriteCore(thm);
03195   }
03196 
03197   const Expr& e2 = thm.getRHS();
03198 #ifdef DEBUG
03199   // The "ite-lift-unary" option will break this check (experimental)
03200   if(!getFlags()["ite-lift-unary"].getBool()) {
03201     if (!e2.isTerm() || !e2.hasFind()) {
03202       // The rewriter should guarantee that all of its children are simplified.
03203       for (int k=0; k<e2.arity(); ++k) {
03204         Expr simplified(simplifyRec(e2[k]).getRHS());
03205         DebugAssert(e2[k]==simplified,"Simplify Error 1:\n e2[k="+int2string(k)
03206                     +"] = "
03207                     +e2[k].toString() + "\nSimplified = "
03208                     +simplified.toString()
03209                     +"\ne2 = "+e2.toString());
03210 //      Expr rewritten(rewriteCore(e2[k]).getRHS());
03211 //      DebugAssert(e2[k]==rewritten,"Simplify Error 2: e2[k] = \n"
03212 //                  +e2[k].toString() + "\nSimplified rewritten = \n"
03213 //                  +rewritten.toString());
03214       }
03215     }
03216     Expr rewritten(rewriteCore(e2).getRHS());
03217     DebugAssert(e2==rewritten,"Simplify Error 2: e2 = \n"
03218                 +e2.toString() + "\nSimplified rewritten = \n"
03219                 +rewritten.toString());
03220   }
03221 #endif
03222   e.setSimpCache(thm);
03223   if (e != e2) {
03224     e2.setSimpCache(reflexivityRule(e2));
03225   }
03226   TRACE("simplifyRec", "simplify => ", thm, "}\n");
03227   IF_DEBUG(simpStack.erase(e));
03228   return thm;
03229 }
03230 
03231 
03232 // This needs to be reviewed -- I'm not sure it's working properly
03233 Theorem TheoryCore::simplifyInPlaceRec(const Expr& e)
03234 {
03235   TRACE("simplifyRec", "simplifyInPlaceRec(", e, ") {");
03236   Theorem thm;
03237   if (e.hasFind()) {
03238     thm = find(e);
03239     const Expr& e2 = thm.getRHS();
03240     if (e2.hasFind()) {
03241       DebugAssert(e2.isTrue() || e2.isFalse() || e2.isTerm(),
03242                   "Unexpected find pointer");
03243       TRACE_MSG("simplifyRec", "Using find");
03244       TRACE("simplifyRec", "simplifyInPlaceRec => ", thm, "}\n");
03245       return thm;
03246     }
03247     else {
03248       DebugAssert(!e.isAbsLiteral(), "huh?");
03249       Theorem thm2 = simplifyInPlaceRec(e2);
03250       if (thm2.getLHS() != thm2.getRHS()) {
03251         e.setFind(transitivityRule(thm,thm2));
03252         TRACE_MSG("simplifyRec", "Using find 2");
03253         TRACE("simplifyRec", "simplifyInPlaceRec => ", e.getFind(), "}\n");
03254         return e.getFind();
03255       }
03256       TRACE_MSG("simplifyRec", "Using find 3");
03257       TRACE("simplifyRec", "simplifyInPlaceRec => ", thm, "}\n");
03258       return thm;
03259     }
03260   }
03261 
03262   if (e.validSimpCache()) {
03263     TRACE_MSG("simplifyRec", "Using cached result");
03264     TRACE("simplifyRec", "simplifyInPlaceRec => ", e.getSimpCache(), "}\n");
03265     return e.getSimpCache();
03266   }
03267 
03268   int k, ar = e.arity();
03269   if (ar > 0) {
03270     vector<Theorem> newChildrenThm;
03271     vector<unsigned> changed;
03272     const vector<Expr>& kids = e.getKids();
03273     for(k = 0; k < ar; ++k) {
03274       thm = simplifyRec(kids[k]);
03275       if (thm.getLHS() != thm.getRHS()) {
03276         if ((e.getKind() == OR && thm.getRHS().isTrue()) ||
03277             (e.getKind() == AND && thm.getRHS().isFalse())) {
03278           newChildrenThm.clear();
03279           changed.clear();
03280           newChildrenThm.push_back(thm);
03281           changed.push_back(k);
03282           break;
03283         }
03284         else if (k == 0 && e.getKind() == ITE && (thm.getRHS().isBoolConst())) {
03285           newChildrenThm.push_back(thm);
03286           changed.push_back(k);
03287           if (thm.getRHS().isTrue()) k += 1;
03288           else k += 2;
03289           thm = simplifyRec(kids[k]);
03290           newChildrenThm.push_back(thm);
03291           changed.push_back(k);          
03292           break;
03293         }
03294         else {
03295           newChildrenThm.push_back(thm);
03296           changed.push_back(k);
03297         }
03298       }
03299     }
03300     if (changed.size() == 0) thm = rewriteCore(e);
03301     else {
03302       thm = substitutivityRule(e, changed, newChildrenThm);
03303       Theorem thm2 = rewriteCore(thm.getRHS());
03304       const Expr& e2 = thm2.getLHS();
03305       if (e2 == thm2.getRHS()) {
03306         if (!e.isAbsLiteral() && !e2.isAtomic() && !e2.isAbsLiteral()) {
03307           e.setFind(thm);
03308           thm = reflexivityRule(e);
03309         }
03310       }
03311       else thm = transitivityRule(thm, thm2);
03312     }
03313   } else {
03314     thm = rewriteCore(e);
03315   }
03316   e.setSimpCache(thm);
03317   const Expr& e2 = thm.getRHS();
03318   if (e != e2) {
03319     e2.setSimpCache(reflexivityRule(e2));
03320   }
03321   TRACE("simplifyRec", "simplifyInPlaceRec => ", thm, "}\n");
03322   return thm;
03323 }
03324 
03325 
03326 bool TheoryCore::incomplete(vector<string>& reasons) {
03327   if(d_incomplete.size() > 0) {
03328     for(CDMap<string,bool>::iterator i=d_incomplete.begin(),
03329           iend=d_incomplete.end(); i!=iend; ++i)
03330       reasons.push_back((*i).first);
03331     return true;
03332   }
03333   else
03334     return false;
03335 }
03336 
03337 
03338 Theorem TheoryCore::rewriteCore(const Theorem& e) {
03339   DebugAssert(e.isRewrite(),
03340               "rewriteCore(thm): not equality or iff:\n  " + e.toString());
03341   return transitivityRule(e, rewriteCore(e.getRHS()));
03342 }
03343 
03344 
03345 Theorem TheoryCore::rewriteLiteral(const Expr& e) {
03346   DebugAssert(e.isAbsLiteral(), "rewriteLiteral("+e.toString()
03347               +")\nExpected a literal.");
03348   Theorem res;
03349   //Theory* i = theoryOf(getBaseType(e).getExpr());
03350   bool neg(e.isNot());
03351   const Expr a = neg? e[0] : e;
03352   Theory * i;
03353   if(a.isEq())
03354     i = theoryOf(getBaseType(a[0]).getExpr());  
03355   else if (a.arity() > 1)
03356     i = theoryOf(getBaseType(a[0]).getExpr());
03357   else
03358     i = theoryOf(a);
03359   TRACE("rewrite", ("rewriteAtomic["+i->getName()+"]("), e, ") {");
03360   res = i->rewriteAtomic(a);
03361   TRACE("rewrite", ("rewriteAtomic["+i->getName()+"] => "), res, "}");
03362   if(neg) res = d_commonRules->iffContrapositive(res);
03363   return res;
03364 }
03365 
03366 /*****************************************************************************/
03367 /*!
03368  * Function: TheoryCore::solve
03369  *
03370  * Author: Clark Barrett
03371  *
03372  * Created: Wed Feb 26 16:17:54 2003
03373  *
03374  * This is a generalization of what's in my thesis.  The goal is to rewrite e
03375  * into an equisatisfiable conjunction of equations such that the left-hand
03376  * side of each equation is a variable which does not appear as an i-leaf of
03377  * the rhs, where i is the theory of the primary solver.  Any solution which
03378  * satisfies this is fine.  "Solvers" from other theories can do whatever they
03379  * want as long as we eventually reach this form.
03380  */
03381 /*****************************************************************************/
03382 Theorem TheoryCore::solve(const Theorem& eThm)
03383 {
03384   const Expr& e = eThm.getExpr();
03385   TRACE("facts solve", "solve[Core](", e, ") {");
03386   Theorem thm;
03387   Expr e2;
03388   if (d_solver) {
03389     TRACE("facts solve", "solve["+d_solver->getName()+"](", e,") {");
03390     thm = d_solver->solve(eThm);
03391     TRACE("facts solve", "solve["+d_solver->getName()+"] => ", thm.getExpr(), " }");
03392     e2 = thm.getExpr();
03393     // FIXME: this stops other solvers from being run when arithmetic
03394     // solves into a system of equations.  This results in
03395     // INCOMPLETENESS.  In my opinion (Sergey), the correct fix is to
03396     // allow multiple independent solvers, just like rewriters.
03397     if (!e2.isEq() || theoryOf(e2) == d_solver) {
03398       TRACE("facts solve", "solve[Core](non-eq) => ", thm, " }");
03399       // setIncomplete("Not all solvers have been run (this is a bug)");
03400       return thm;
03401     }
03402   }
03403   else {
03404     thm = eThm;
03405     e2 = e;
03406   }
03407   Theory* i = theoryOf(e2);
03408   TRACE("facts solve", "solve["+i->getName()+"](", e2,") {");
03409   Theorem thm2 = i->solve(thm);
03410   TRACE("facts solve", "solve["+i->getName()+"] => ", thm2.getExpr(), " }");
03411   IF_DEBUG(
03412     // Check that the result is in solved form according to the primary solver
03413     if (d_solver) {
03414       e2 = thm2.getExpr();
03415       if(e2.isEq()) {
03416         Expr solved(d_solver->solve(thm2).getExpr());
03417         DebugAssert(solved == e2, "e2 = "+e2.toString()
03418                     +"\nsolved = "+solved.toString());
03419       }
03420       // FIXME: how do we check it for AND and EXISTS?
03421     }
03422     );
03423   TRACE("facts solve", "solve[Core] => ", thm2, " }");
03424   return thm2;
03425 }
03426 
03427 
03428 Theorem TheoryCore::typePred(const Expr& e) {
03429   return d_rules->typePred(e);
03430 }
03431 
03432 
03433 Theorem TheoryCore::subtypePredicate(const Expr& e) {
03434   TRACE("tccs", "subtypePredicate(", e, ") {");
03435   Theorem pred(e.lookupSubtypePred());
03436   if(pred.isNull()) {
03437     vector<Theorem> thms;
03438     thms.push_back(d_rules->typePred(e));
03439     TRACE("tccs", "subtypePredicate: typePred(e) = ", thms[0].getExpr(), "");
03440     for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
03441       thms.push_back(subtypePredicate(*i));
03442     pred = d_commonRules->andIntro(thms);
03443     pred = d_commonRules->rewriteAnd(pred);
03444     e.setSubtypePred(pred);
03445   }
03446   TRACE("tccs", "subtypePredicate => ", pred.getExpr(), " }");
03447   return pred;
03448 }
03449 
03450 
03451 IF_DEBUG(
03452 void TheoryCore::dumpTrace(const Expr& e, const string& title) {
03453   vector<StrPair> fields;
03454   fields.push_back(strPair("op", d_em->getKindName(e.getKind())));
03455   fields.push_back(strPair("theory", theoryOf(e)->getName()));
03456   debugger.dumpTrace(title, fields);
03457 }
03458 )
03459 
03460 
03461 void TheoryCore::setFindLiteral(const Theorem& thm, bool notifySAT) {
03462   const Expr& e = thm.getExpr();
03463   if (e.isNot()) {
03464     if (!e[0].hasFind()) {
03465       if(notifySAT) enqueueSE(thm);
03466       e[0].setFind(d_commonRules->notToIff(thm));
03467       d_em->invalidateSimpCache();
03468     }
03469   }
03470   else if (!e.hasFind()) {
03471     e.setFind(d_commonRules->iffTrue(thm));
03472     if(notifySAT) enqueueSE(thm);
03473     d_em->invalidateSimpCache();
03474   }
03475 }
03476 
03477 
03478 Theorem TheoryCore::rewriteIte(const Expr& e) {
03479   if (e[0].isTrue())
03480     return d_rules->rewriteIteTrue(e);
03481   if (e[0].isFalse())
03482     return d_rules->rewriteIteFalse(e);
03483   if (e[1] == e[2])
03484     return d_rules->rewriteIteSame(e);
03485   // This results in exponential blowup
03486 //   if(!isTerm(e1) && !isTerm(e2))
03487 //     return d_commonRules->rewriteIteBool(c, e1, e2);
03488   // Default case: no rewrite
03489   return reflexivityRule(e);
03490 }
03491 
03492 
03493 /* Recurse through s looking for atomic formulas (or terms in the case of
03494  * then/else branches of ite's) and use the notifylist mechanism to indicate
03495  * that the atomic formula e depends on these atomic formulas and terms.  Used
03496  * by registerAtom. */
03497 void TheoryCore::setupSubFormulas(const Expr& s, const Expr& e)
03498 {
03499   if (s.isAtomic()) {
03500     setupTerm(s, theoryOf(s));
03501     s.addToNotify(this, e);
03502     processFactQueue();
03503   }
03504   else if (s.isAbsAtomicFormula()) {
03505     setupTerm(s, theoryOf(s));
03506     for (int i = 0; i < s.arity(); ++i) {
03507       s[i].addToNotify(this, e);
03508     }
03509     s.addToNotify(this, e);
03510     processFactQueue();
03511   }
03512   else {
03513     for (int i = 0; i < s.arity(); ++i) {
03514       setupSubFormulas(s[i], e);
03515     }
03516   }
03517 }
03518 
03519 
03520 void TheoryCore::registerAtom(const Expr& e)
03521 {
03522   // TODO: don't change state by calling this function
03523   DebugAssert(e.isAbsAtomicFormula(), "Expected atomic formula");
03524   IF_DEBUG(ScopeWatcher sw(&d_inRegisterAtom));
03525   Theorem thm = simplify(e);
03526   if (thm.getRHS().isTrue()) {
03527     if (e.isImpliedLiteral()) return;
03528     e.setImpliedLiteral();
03529     d_impliedLiterals.push_back(d_commonRules->iffTrueElim(thm));
03530   }
03531   else if (thm.getRHS().isFalse()) {
03532     Expr not_e = !e;
03533     if (not_e.isImpliedLiteral()) return;
03534     not_e.setImpliedLiteral();
03535     d_impliedLiterals.push_back(d_commonRules->iffFalseElim(thm));
03536   }
03537   else {
03538     setupSubFormulas(thm.getRHS(), e);
03539   }
03540 }
03541 
03542 
03543 Theorem TheoryCore::getImpliedLiteral(void)
03544 {
03545   Theorem res;
03546   if (d_impliedLiteralsIdx < d_impliedLiterals.size()) {
03547     res = d_impliedLiterals[d_impliedLiteralsIdx];
03548     d_impliedLiteralsIdx = d_impliedLiteralsIdx + 1;
03549   }
03550   return res;
03551 }
03552 
03553 
03554 Theorem TheoryCore::getImpliedLiteralByIndex(unsigned index)
03555 {
03556   DebugAssert(index < d_impliedLiterals.size(), "index out of bounds");
03557   return d_impliedLiterals[index];
03558 }
03559 
03560 
03561 void TheoryCore::assignValue(const Expr& t, const Expr& val) {
03562   DebugAssert(d_varAssignments.count(t) == 0
03563               || d_varAssignments[t].getRHS() == val,
03564               "TheoryCore::assignValue("+t.toString()+" := "+val.toString()
03565               +")\n variable already has a different value");
03566   // Check if the assignment theorem can be derived from the find of t
03567   Theorem thm(find(t));
03568   const Expr& t2 = thm.getRHS();
03569 
03570   if(t2!=val) {
03571     bool isBool(t2.getType().isBool());
03572     Expr assump = (isBool)? t2.iffExpr(val) : t2.eqExpr(val);
03573     Theorem assertThm = d_coreSatAPI->addAssumption(assump);
03574     addFact(assertThm);
03575     thm = transitivityRule(thm, assertThm);
03576   }
03577   d_varAssignments[t] = thm;
03578 }
03579 
03580 
03581 void TheoryCore::assignValue(const Theorem& thm) {
03582   DebugAssert(thm.isRewrite(), "TheoryCore::assignValue("+thm.toString()+")");
03583   const Expr& t = thm.getLHS();
03584   const Expr& val = thm.getRHS();
03585   DebugAssert(d_varAssignments.count(t) == 0
03586               || d_varAssignments[t].getRHS() == val,
03587               "TheoryCore::assignValue("+thm.getExpr().toString()
03588               +")\n variable already has a different value:\n "
03589               +d_varAssignments[t].getExpr().toString());
03590   d_varAssignments[t] = thm;
03591   // Check if the assignment theorem can be derived from the find of t
03592   Theorem findThm(find(t));
03593   const Expr& t2 = findThm.getRHS();
03594 
03595   if(t2!=val) {
03596     Theorem thm2 = transitivityRule(symmetryRule(findThm), thm);
03597     addFact(thm2);
03598   }
03599 }
03600 
03601 
03602 bool TheoryCore::getResource() {
03603   // Unlimited resource
03604   if(d_resourceLimit == 0) return true;
03605   // Resource is limited: check and consume it
03606   if(d_resourceLimit > 1) {
03607     d_resourceLimit--;
03608     return true;
03609   }
03610   else
03611     return false;
03612 }
03613 
03614 
03615 Theorem3 TheoryCore::queryTCC(const Theorem& phi, const Theorem& D_phi)
03616 {
03617   return d_rules->queryTCC(phi, D_phi);
03618 }
03619 
03620 
03621 Theorem3 TheoryCore::implIntro3(const Theorem3& phi,
03622                                 const std::vector<Expr>& assump,
03623                                 const std::vector<Theorem>& tccs)
03624 {
03625   return d_rules->implIntro3(phi, assump, tccs);
03626 }

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