vcl.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file vcl.cpp
00004  * 
00005  * Author: Clark Barrett
00006  * 
00007  * Created: Tue Dec 31 18:27:11 2002
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 <fstream>
00031 #include <iostream>
00032 #include "vcl.h"
00033 #include "context.h"
00034 #include "parser.h"
00035 #include "vc_cmd.h"
00036 #include "search.h"
00037 #include "search_simple.h"
00038 #include "search_fast.h"
00039 #include "theorem_manager.h"
00040 #include "variable.h"
00041 #include "theory_core.h"
00042 #include "theory_uf.h"
00043 #include "theory_arith.h"
00044 #include "theory_bitvector.h"
00045 #include "theory_array.h"
00046 #include "theory_quant.h"
00047 #include "theory_records.h"
00048 #include "theory_simulate.h"
00049 #include "theory_datatype.h"
00050 #include "command_line_flags.h"
00051 #include "typecheck_exception.h"
00052 #include "eval_exception.h"
00053 #include "debug.h"
00054 
00055 using namespace std;
00056 using namespace CVCL;
00057 
00058 ValidityChecker* ValidityChecker::create(const CLFlags& flags)
00059 {
00060   return new VCL(flags);
00061 }
00062 
00063 
00064 CLFlags ValidityChecker::createFlags() {
00065   CLFlags flags;
00066   // We expect the user to type cvcl -h to get help, which will set
00067   // the "help" flag to false; that's why it's initially true.
00068 
00069   // Overall system control flags
00070   flags.addFlag("timeout", CLFlag(0, "Kill cvcl process after given number of seconds (0==no limit)"));
00071   flags.addFlag("resource", CLFlag(0, "Set finite resource limit (0==no limit)"));
00072   flags.addFlag("mm", CLFlag("chunks", "Memory manager (chunks, malloc)"));
00073   // Information printing flags
00074   flags.addFlag("help",CLFlag(true, "print usage information and exit"));
00075   flags.addFlag("version",CLFlag(true, "print version information and exit"));
00076   flags.addFlag("quiet", CLFlag(true, "Be as quiet as possible"));
00077   flags.addFlag("interactive", CLFlag(false, "Interactive mode"));
00078   flags.addFlag("stats", CLFlag(false, "Print run-time statistics"));
00079   flags.addFlag("reorder", CLFlag(false, "Permute and get reordered "
00080                                   "CVC benchmark (ite should be on)"));
00081   flags.addFlag("seed", CLFlag(1, "Set the seed for random sequence"));
00082   flags.addFlag("pq", CLFlag(false, "Print query"));
00083   flags.addFlag("dump-log", CLFlag("", "Dump API call log in CVCL input "
00084                                    "format to given file "
00085                                    "(off when file name is \"\")"));
00086   flags.addFlag("translate", CLFlag(false, "Produce a complete translation from "
00087                                            "the input language to output language.  "
00088                                            "Requires dump-log."));
00089   flags.addFlag("real2int", CLFlag(false, "When translating, convert reals to integers."));
00090 
00091   // Parser related flags
00092   flags.addFlag("old-func-syntax",CLFlag(false, "Enable parsing of old-style function syntax"));
00093 
00094   // Pretty-printing related flags
00095   flags.addFlag("dagify-exprs",
00096                 CLFlag(true, "Print expressions with sharing as DAGs"));
00097   flags.addFlag("lang", CLFlag("pres", "Input language "
00098                                "(presentation, smtlib, internal)"));
00099   flags.addFlag("output-lang", CLFlag("", "Output language "
00100                                       "(presentation, smtlib, internal, lisp)"));
00101   flags.addFlag("indent", CLFlag(true, "Print expressions with indentation"));
00102   flags.addFlag("width", CLFlag(80, "Suggested line width for printing"));
00103   flags.addFlag("print-depth", CLFlag(-1, "Max. depth to print expressions "));
00104   flags.addFlag("print-assump", CLFlag(false, "Print assumptions in Theorems "));
00105 
00106   // Search Engine (SAT) related flags
00107   flags.addFlag("sat",CLFlag("fast", "choose a SAT solver to use "
00108                              "(fast, simple)"));
00109   flags.addFlag("de",CLFlag("dfs", "choose a decision engine to use "
00110                             "(dfs, caching, mbtf)"));
00111   flags.addFlag("dfs", CLFlag(false, "Use simple DFS splitter heuristic"));
00112   flags.addFlag("clauses", CLFlag(true, "Build conflict clauses"));
00113   flags.addFlag("max-clauses",
00114                 CLFlag(100000, "Max. number of conflict clauses (for +sat)"));
00115   flags.addFlag("berkmin", CLFlag(false, "Use BerkMin splitter heuristic"));
00116   flags.addFlag("track-literals", CLFlag(false, "Keep a list of literals asserted internally since last user assertion"));
00117 
00118   // Proofs and Assumptions
00119   flags.addFlag("proofs", CLFlag(false, "Produce proofs (also sets +assump)"));
00120   flags.addFlag("check-proofs",
00121                 CLFlag(IF_DEBUG(true ||) false, "Check proofs on-the-fly"));
00122   flags.addFlag("assump", CLFlag(true, "Track assumptions"));
00123 
00124   // Core framework switches
00125   flags.addFlag("tcc", CLFlag(true, "Check TCCs for each ASSERT and QUERY"));
00126   flags.addFlag("cnf", CLFlag(false, "Convert top-level Boolean formulas to CNF"));
00127   flags.addFlag("ignore-cnf-vars", CLFlag(false, "Do not split on aux. CNF vars (with +cnf)"));
00128   flags.addFlag("orig-formula", CLFlag(false, "Preserve the original formula with +cnf (for splitter heuristics)"));
00129   flags.addFlag("iflift", CLFlag(false, "Translate if-then-else terms to CNF (with +cnf)"));
00130   flags.addFlag("circuit", CLFlag(false, "With +cnf, use circuit propagation"));
00131   flags.addFlag("un-ite-ify", CLFlag(false, "Unconvert ITE expressions"));
00132   flags.addFlag("ip", CLFlag(false, "Simplify \"in place\""));
00133   flags.addFlag("ite", CLFlag(false,
00134                               "Convert to ITE expression in preprocess"));
00135   flags.addFlag("pp", CLFlag(false, "Use ITE-simplifier in "
00136                              "preprocess (with +ite)"));
00137   flags.addFlag("diseq", CLFlag(false, "Exploit structural similarity "
00138                                 "in disequalities"));
00139   // Concrete model generation (counterexamples) flags
00140   flags.addFlag("applications", CLFlag(true, "Add relevant function applications and array accesses to the concrete counterexample"));
00141   // Debugging flags (only for the debug build)
00142   // #ifdef DEBUG
00143   vector<pair<string,bool> > sv;
00144   flags.addFlag("trace", CLFlag(sv, "Tracing.  Multiple flags add up."));
00145   flags.addFlag("dump-trace", CLFlag("", "Dump debugging trace to "
00146                                    "given file (off when file name is \"\")"));
00147   // #endif
00148   // DP-specific flags
00149 
00150   // Arithmetic
00151   flags.addFlag("var-order",
00152                 CLFlag(false, "Use simple variable order in arith"));
00153   flags.addFlag("ineq-delay", CLFlag(10, "Accumulate this many inequalities "
00154                                      "before processing"));
00155 
00156   // Quantifiers
00157   flags.addFlag("max-quant-inst", CLFlag(100, "The maximum number of"
00158                                 " quantifier instantiations processed"));
00159 
00160   //Bitvectors
00161   flags.addFlag("bv-simplify",
00162                 CLFlag(false, "Simplify bitvector facts"));
00163   flags.addFlag("boolean-rewrite",
00164                 CLFlag(true, "Rewrite booleans on the fly"));
00165   flags.addFlag("use-boolextract-cache",
00166                 CLFlag(false, "Use cache to construct boolextract exprs"));
00167   flags.addFlag("bv-rewrite",
00168                 CLFlag(true, "Rewrite bitvector expressions"));
00169   flags.addFlag("bv-concatnormal-rewrite",
00170                 CLFlag(true, "Concat Normal Form rewrites"));
00171   flags.addFlag("bv-plusnormal-rewrite",
00172                 CLFlag(true, "Bvplus Normal Form rewrites"));
00173   flags.addFlag("bv-rw-bitblast",
00174                 CLFlag(false, "Rewrite while bit-blasting"));
00175   flags.addFlag("bv-cnf-bitblast", 
00176                 CLFlag(true,"Bitblast equalities in CNFconverter with +cnf"));
00177   flags.addFlag("bv-update",
00178                 CLFlag(true,"Update bitvectors on find pointer changes"));
00179   flags.addFlag("bv-setup",
00180                 CLFlag(true,"Setup bitvectors for single bit changes"));
00181   flags.addFlag("bv-shared-setup",
00182                 CLFlag(true,"Setup only subterms of shared terms"));
00183   flags.addFlag("bv-assert",
00184                 CLFlag(true,"Assert bits corresponding to BOOL_EXTRACT(t,i)"));
00185   flags.addFlag("bv-delay-eq",
00186                 CLFlag(true, "Queue up equalities"));
00187   flags.addFlag("bv-bit-eq",
00188                 CLFlag(false, "Expand equalities into 1-bit equalities"));
00189   flags.addFlag("bv-delay-diseq",
00190                 CLFlag(true, "Queue up disequalities"));
00191   flags.addFlag("bv-delay-typepred",
00192                 CLFlag(true,"Delay bitvector type predicates"));
00193   flags.addFlag("bv-nl-remove1",
00194                 CLFlag(true,"BV DP: Remove updated canonical rep from NotifyList"));
00195   flags.addFlag("bv-nl-remove2",
00196                 CLFlag(true,"BV DP: Remove updated bit expansion from NotifyList"));
00197   flags.addFlag("bv-lhs-minus-rhs", 
00198                 CLFlag(false,"Do lhs-rhs=0 if both lhs/rhs are BVPLUS"));
00199 
00200   
00201 
00202   // Uninterpreted Functions
00203   flags.addFlag("trans-closure",
00204                 CLFlag(false,"enables transitive closure of binary relations"));
00205   return flags;
00206 }
00207 
00208 
00209 ValidityChecker* ValidityChecker::create()
00210 {
00211   return new VCL(createFlags());
00212 }
00213 
00214 
00215 size_t VCL::UserAssertion::s_nextIdx = 0;
00216 
00217 
00218 //! Recursive assumption graph traversal to find user assumptions
00219 /*!
00220  *  If an assumption has a TCC, traverse the proof of TCC and add its
00221  *  assumptions to the set recursively.
00222  */
00223 void VCL::getAssumptionsRec(const Theorem& thm,
00224                             set<UserAssertion>& assumptions,
00225                             bool addTCCs) {
00226   if(thm.isFlagged()) return;
00227   thm.setFlag();
00228   if(thm.isAxiom()) {
00229     if(d_userAssertions->count(thm.getExpr())>0) {
00230       const UserAssertion& a = (*d_userAssertions)[thm.getExpr()];
00231       assumptions.insert(a);
00232       if(addTCCs) {
00233         DebugAssert(!a.tcc().isNull(), "getAssumptionsRec(a="
00234                     +a.thm().toString()+", thm = "+thm.toString()+")");
00235         getAssumptionsRec(a.tcc(), assumptions, true);
00236       }
00237     } else { // it's a splitter
00238       UserAssertion a(thm, Theorem());
00239       assumptions.insert(a);
00240     }
00241   }
00242   else {
00243     Assumptions a(thm.getAssumptions());
00244     for(Assumptions::iterator i=a.begin(), iend=a.end(); i!=iend; ++i)
00245       getAssumptionsRec(*i, assumptions, addTCCs);
00246   }
00247 }
00248 
00249 
00250 void VCL::getAssumptions(const Assumptions& a, vector<Expr>& assumptions)
00251 {
00252   set<UserAssertion> assumpSet;
00253   if(a.isNull()) return;
00254   Assumptions::iterator i=a.begin(), iend=a.end();
00255   if(i!=iend) i->clearAllFlags();
00256   for(; i!=iend; ++i)
00257     getAssumptionsRec(*i, assumpSet, getFlags()["tcc"].getBool());
00258   // Order assumptions by their creation time
00259   for(set<UserAssertion>::iterator i=assumpSet.begin(), iend=assumpSet.end();
00260       i!=iend; ++i)
00261     assumptions.push_back(i->thm().getExpr());
00262 }
00263 
00264 
00265 Theorem3 VCL::deriveClosure(const Theorem3& thm) {
00266   vector<Expr> assump;
00267   set<UserAssertion> assumpSet;
00268   // Compute the vector of assumptions for thm, and iteratively move
00269   // the assumptions to the RHS until done.  Each closure step may
00270   // introduce new assumptions from the proofs of TCCs, so those need
00271   // to be dealt with in the same way, until no assumptions remain.
00272   Theorem3 res = thm;
00273   Assumptions a(res.getAssumptions());
00274   while(!a.empty()) {
00275     assump.clear();
00276     assumpSet.clear();
00277     Assumptions::iterator i=a.begin(), iend=a.end();
00278     if(i!=iend) i->clearAllFlags();
00279     // Collect the assumptions of 'res' *without* TCCs
00280     for(; i!=iend; ++i)
00281       getAssumptionsRec(*i, assumpSet, false);
00282 
00283     // Build the vectors of assumptions and TCCs
00284     vector<Theorem> tccs;
00285     if(getFlags()["tcc"].getBool()) {
00286       for(set<UserAssertion>::iterator i=assumpSet.begin(),
00287             iend=assumpSet.end(); i!=iend; ++i) {
00288         assump.push_back(i->thm().getExpr());
00289         tccs.push_back(i->tcc());
00290       }
00291     }
00292     // Derive the closure
00293     res = d_theoryCore->implIntro3(res, assump, tccs);
00294     a = res.getAssumptions();
00295   }
00296   return res;
00297 }
00298 
00299 
00300 static string fileToSMTLIBIdentifier(const string& filename)
00301 {
00302   string tmpName;
00303   string::size_type pos = filename.rfind("/");
00304   if (pos == string::npos) {
00305     tmpName = filename;
00306   }
00307   else {
00308     tmpName = filename.substr(pos+1);
00309   }
00310   char c = tmpName[0];
00311   string res;
00312   if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) {
00313     res = "B_";
00314   }
00315   for (unsigned i = 0; i < tmpName.length(); ++i) {
00316     c = tmpName[i];
00317     if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') &&
00318         (c < '0' || c > '9') && (c != '.' && c != '_')) {
00319       c = '_';
00320     }
00321     res += c;
00322   }
00323   return res;
00324 }
00325 
00326 
00327 VCL::VCL(const CLFlags& flags): d_flags(new CLFlags(flags)) // , d_cnf(NULL)
00328 {
00329   // Set the dependent flags so that they are consistent
00330 
00331   // If proofs are enabled, then enable assumptions too
00332   if((*d_flags)["proofs"].getBool()) d_flags->setFlag("assump", true);
00333   // The default SAT solver must always be run with assump enabled
00334   if((*d_flags)["sat"].getString() != "simple")
00335     d_flags->setFlag("assump", true);
00336 
00337   d_cm = new ContextManager();
00338   // Initialize the database of user assertions.  It has to be
00339   // initialized after d_cm.
00340   d_userAssertions = new CDMap<Expr,UserAssertion>(getCurrentContext());
00341 
00342   d_tm = new TheoremManager(this, (*d_flags)["proofs"].getBool(),
00343                             (*d_flags)["assump"].getBool());
00344 
00345   // ExprManager uses Theorem class, so it has to be created after
00346   // TheoremManager is ready, and deleted before.
00347   d_em = new ExprManager(d_cm, *d_flags);
00348 
00349   // Initialize TheoremManager
00350   d_tm->init();
00351 
00352   d_theoryCore = new TheoryCore(this);
00353   d_theories.push_back(d_theoryCore);
00354 
00355   // Fast rewriting of literals is done by setting their find to true or false.
00356   falseExpr().setFind(d_theoryCore->reflexivityRule(falseExpr()));
00357   trueExpr().setFind(d_theoryCore->reflexivityRule(trueExpr()));
00358 
00359   // Must be created after TheoryCore, since it needs it.
00360   // When we have more than one search engine, select one to create
00361   // based on flags
00362   if ((*d_flags)["sat"].getString() == "simple")
00363     d_se = new SearchSimple(this); 
00364 //   else if ((*d_flags)["sat"].getString() == "default")
00365 //     d_se = new SearchEngineDefault(this);
00366   else if ((*d_flags)["sat"].getString() == "fast")
00367     d_se = new SearchEngineFast(this);
00368   else
00369     ASSERT_FATAL(false, "Unrecognized SAT solver name: "
00370                  +(*d_flags)["sat"].getString());
00371 
00372   d_theories.push_back(d_theoryUF = new TheoryUF(this));
00373   d_theories.push_back(d_theoryArith = new TheoryArith(this));
00374   d_theories.push_back(d_theoryArray = new TheoryArray(this));
00375   d_theories.push_back(d_theoryQuant = new TheoryQuant(this));
00376   d_theories.push_back(d_theoryRecords = new TheoryRecords(this));
00377   d_theories.push_back(d_theorySimulate = new TheorySimulate(this));
00378   d_theories.push_back(d_theoryBitvector = new TheoryBitvector(this));
00379   d_theories.push_back(d_theoryDatatype = new TheoryDatatype(this));
00380 
00381   // Initial scope level should be 1
00382   d_cm->push();
00383   d_translate = (*d_flags)["translate"].getBool();
00384   const string& dumpFile = (*d_flags)["dump-log"].getString();
00385   if (dumpFile == "") {
00386     DebugAssert(!d_translate,"Cannot translate without dump file");
00387     d_translate = false;
00388   }
00389   else {
00390     if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
00391       d_osdump.open(".cvcl__smtlib_temporary_file");
00392       if(!d_osdump)
00393         cerr << "*** Warning: cannot open temporary file .cvcl__smtlib_temporary_file"
00394              << dumpFile << endl;
00395       d_osdumpTranslate.open(dumpFile.c_str());
00396       if(!d_osdumpTranslate)
00397         cerr << "*** Warning: cannot open a log file: " << dumpFile << endl;
00398       d_osdumpTranslate <<
00399         "(benchmark " << fileToSMTLIBIdentifier(dumpFile) << endl <<
00400         "  :source {" << endl;
00401       string tmpName;
00402       string::size_type pos = dumpFile.rfind("/");
00403       if (pos == string::npos) {
00404         tmpName = "README";
00405       }
00406       else {
00407         tmpName = dumpFile.substr(0,pos+1) + "README";
00408       }
00409       d_tmpFile.open(tmpName.c_str());
00410       char c;
00411       if (d_tmpFile.is_open()) {
00412         d_tmpFile.get(c);
00413         while (!d_tmpFile.eof()) {
00414           if (c == '{' || c == '}') d_osdumpTranslate << '\\';
00415           d_osdumpTranslate << c;
00416           d_tmpFile.get(c);
00417         }
00418         d_tmpFile.close();
00419       }
00420       else {
00421         d_osdumpTranslate << "Source unknown";
00422       }
00423       d_osdumpTranslate << endl <<
00424         "This benchmark was automatically translated into SMT-LIB format from" << endl <<
00425         "CVC format using CVC Lite" << endl << "}" << endl;
00426     }
00427     else {
00428       d_osdump.open(dumpFile.c_str());
00429       if(!d_osdump)
00430         cerr << "*** Warning: cannot open a log file: " << dumpFile << endl;
00431     }
00432   }
00433 
00434   setResourceLimit((*d_flags)["resource"].getInt());
00435 
00436 //   if ((*d_flags)["cnf"].getBool())
00437 //     d_cnf = new CNF(this);
00438 }
00439 
00440 
00441 VCL::~VCL()
00442 {
00443 //   delete d_cnf;
00444   if (d_osdump) {
00445     if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
00446       d_osdumpTranslate << "  :logic ";
00447       if (d_theoryRecords->theoryUsed() ||
00448           d_theorySimulate->theoryUsed() ||
00449           d_theoryBitvector->theoryUsed() ||
00450           d_theoryDatatype->theoryUsed()) {
00451         d_osdumpTranslate << "unknown";
00452       }
00453       else {
00454         if (d_theoryArith->theoryUsed() &&
00455             (d_theoryArith->getLangUsed() == NONLINEAR ||
00456             (d_theoryArith->realUsed() &&
00457              d_theoryArith->intUsed()))) {
00458           d_osdumpTranslate << "unknown";
00459         }
00460         else {
00461           if (!d_theoryQuant->theoryUsed()) {
00462             d_osdumpTranslate << "QF_";
00463           }
00464           if (d_theoryArray->theoryUsed()) {
00465             if (d_theoryArith->theoryUsed()) {
00466               if (d_theoryArith->realUsed()) {
00467                 d_osdumpTranslate << "AUFLRA";
00468               }
00469               else {
00470                 d_osdumpTranslate << "AUFLIA";
00471               }
00472             }
00473             else {
00474               d_osdumpTranslate << "AUFLIA";
00475             }
00476           }
00477           else if (d_theoryUF->theoryUsed()) {
00478             if (d_theoryArith->theoryUsed()) {
00479               if (d_theoryArith->realUsed()) {
00480                 if (d_theoryArith->getLangUsed() <= DIFF_ONLY) {
00481                   d_osdumpTranslate << "UFRDL";
00482                 }
00483                 else {
00484                   d_osdumpTranslate << "UFLRA";
00485                 }
00486               }                  
00487               else {
00488                 if (d_theoryArith->getLangUsed() <= DIFF_ONLY) {
00489                   d_osdumpTranslate << "UFIDL";
00490                 }
00491                 else {
00492                   d_osdumpTranslate << "UFLIA";
00493                 }
00494               }
00495             }
00496             else {
00497               d_osdumpTranslate << "UF";
00498             }
00499           }
00500           else if (d_theoryArith->theoryUsed()) {
00501             if (d_theoryArith->realUsed()) {
00502               if (d_theoryArith->getLangUsed() == DIFF_ONLY) {
00503                 d_osdumpTranslate << "RDL";
00504               }
00505               else {
00506                 d_osdumpTranslate << "LRA";
00507               }
00508             }
00509             else {
00510               if (d_theoryArith->getLangUsed() == DIFF_ONLY) {
00511                 d_osdumpTranslate << "IDL";
00512               }
00513               else {
00514                 d_osdumpTranslate << "LIA";
00515               }
00516             }
00517           }
00518           else {
00519             d_osdumpTranslate << "UF";
00520           }
00521         }
00522       }
00523       d_osdumpTranslate << endl;
00524       d_osdump.close();
00525       d_tmpFile.clear();
00526       d_tmpFile.open(".cvcl__smtlib_temporary_file");
00527       if (d_tmpFile.is_open()) {
00528         char c;
00529         d_tmpFile.get(c);
00530         while (!d_tmpFile.eof()) {
00531           d_osdumpTranslate << c;
00532           d_tmpFile.get(c);
00533         }
00534         d_tmpFile.close();
00535       }
00536       d_osdumpTranslate << ")" << endl;
00537     }
00538     d_osdumpTranslate.close();
00539   }
00540 
00541   for(size_t i=0; i<d_theories.size(); ++i) {
00542     string name(d_theories[i]->getName());
00543     TRACE("delete", "Deleting Theory[", name, "] {");
00544     delete d_theories[i];
00545     TRACE("delete", "Finished deleting Theory[", name, "] }");
00546   }
00547   TRACE_MSG("delete", "Deleting SearchEngine {");
00548   delete d_se;
00549   TRACE_MSG("delete", "Finished deleting SearchEngine }");
00550   // This map contains expressions and theorems; delete it before
00551   // d_em, d_tm, and d_cm.
00552   TRACE_MSG("delete", "Deleting d_userAssertions {");
00553   delete d_userAssertions;
00554   TRACE_MSG("delete", "Finished deleting d_userAssertions }");
00555   // and set these to null so their destructors don't blow up
00556   d_lastQuery = Theorem3();
00557   d_lastQueryTCC = Theorem();
00558   d_lastClosure = Theorem3();
00559   TRACE_MSG("delete", "Deleting d_vars {");
00560   d_vars.clear();
00561   TRACE_MSG("delete", "Finished deleting d_vars }");
00562   // Delete ExprManager BEFORE TheoremManager, since Exprs use Theorems
00563   TRACE_MSG("delete", "Clearing d_em {");
00564   d_em->clear();
00565   d_tm->clear();
00566   TRACE_MSG("delete", "Finished clearing d_em }");
00567   TRACE_MSG("delete", "Deleting d_cm {");
00568   delete d_cm;
00569   TRACE_MSG("delete", "Finished deleting d_cm }");
00570   TRACE_MSG("delete", "Deleting d_em {");
00571   delete d_em;
00572   TRACE_MSG("delete", "Finished deleting d_em }");
00573   // TheoremManager does not call ~Theorem() destructors, and only
00574   // releases memory.  At worst, we'll lose some Assumptions.
00575   TRACE_MSG("delete", "Deleting d_tm {");
00576   delete d_tm;
00577   TRACE_MSG("delete", "Finished deleting d_tm }");
00578   TRACE_MSG("delete", "Deleting d_flags [end of ~VCL()]");
00579   delete d_flags;
00580   // No more TRACE-ing after this point (it needs d_flags)
00581 }
00582 
00583 
00584 Type VCL::boolType(){
00585   return d_theoryCore->boolType();
00586 }
00587 
00588 
00589 Type VCL::realType()
00590 {
00591   return d_theoryArith->realType();
00592 }
00593 
00594 
00595 Type VCL::intType() {
00596   return d_theoryArith->intType();
00597 }
00598 
00599 
00600 Type VCL::subrangeType(const Expr& l, const Expr& r) {
00601   return d_theoryArith->subrangeType(l, r);
00602 }
00603 
00604 Type VCL::subtypeType(const Expr& pred) {
00605   Type predTp(getType(pred));
00606   if(!predTp.isFunction())
00607     throw TypecheckException
00608       ("Non-function type in the predicate subtype:\n\n  "
00609        +predTp.toString()
00610        +"\n\nThe predicate is:\n\n  "
00611        +pred.toString());
00612   if(!predTp[1].isBool())
00613     throw TypecheckException
00614       ("Range is not BOOLEAN in the predicate subtype:\n\n  "
00615        +predTp.toString()
00616        +"\n\nThe predicate is:\n\n  "
00617        +pred.toString());
00618   // Eliminate CONSTDEF, if the predicate is a user-defined symbol
00619   Expr p(simplify(pred));
00620   // Make sure that the supplied predicate is total: construct 
00621   // 
00622   //    FORALL (x: domType): getTCC(pred(x))
00623   //
00624   // This only needs to be done for LAMBDA-expressions, since
00625   // uninterpreted predicates are defined for all the arguments
00626   // of correct (exact) types.
00627   if(p.isLambda()) {
00628     Expr quant(forallExpr(p.getVars(), d_theoryCore->getTCC(p.getBody())));
00629       int scope = scopeLevel();
00630       d_cm->push();
00631       if(!query(quant, true)) {
00632         throw TypecheckException
00633           ("Subtype predicate is not total in the following type:\n\n  "
00634            +newExpr(getEM(), SUBTYPE, p).toString()
00635            +"\n\nThe failed TCC is:\n\n  "
00636            +quant.toString());
00637       }
00638       d_cm->popto(scope);
00639   }
00640   return Type(newExpr(getEM(), SUBTYPE, p));
00641 }
00642 
00643 
00644 Type VCL::tupleType(const Type& type0, const Type& type1)
00645 {
00646   vector<Type> types;
00647   types.push_back(type0);
00648   types.push_back(type1);
00649   return d_theoryRecords->tupleType(types);
00650 }
00651 
00652 
00653 Type VCL::tupleType(const Type& type0, const Type& type1, const Type& type2)
00654 {
00655   vector<Type> types;
00656   types.push_back(type0);
00657   types.push_back(type1);
00658   types.push_back(type2);
00659   return d_theoryRecords->tupleType(types);
00660 }
00661 
00662 
00663 Type VCL::tupleType(const vector<Type>& types)
00664 {
00665   return d_theoryRecords->tupleType(types);
00666 }
00667 
00668 
00669 //! Comparison of string/Expr pairs for sorting
00670 template<class T>
00671 class StrPairLess {
00672 public:
00673   bool operator()(const pair<string,T>& p1,
00674                   const pair<string,T>& p2) const {
00675     return p1.first < p2.first;
00676   }
00677 };
00678 
00679 template<class T>
00680 static pair<string,T> strPair(const string& f, const T& t) {
00681   return pair<string,T>(f, t);
00682 }
00683 
00684 //! Sort two vectors based on the first vector
00685 template<class T>
00686 static void sort2(vector<string>& keys, vector<T>& vals) {
00687   DebugAssert(keys.size()==vals.size(), "VCL::sort2()");
00688   // Create vector of pairs
00689   vector<pair<string,T> > pairs;
00690   for(size_t i=0, iend=keys.size(); i<iend; ++i)
00691     pairs.push_back(strPair(keys[i], vals[i]));
00692   // Sort pairs
00693   StrPairLess<T> comp;
00694   sort(pairs.begin(), pairs.end(), comp);
00695   DebugAssert(pairs.size() == keys.size(), "VCL::sort2()");
00696   // Split the pairs back into the original vectors
00697   for(size_t i=0, iend=pairs.size(); i<iend; ++i) {
00698     keys[i] = pairs[i].first;
00699     vals[i] = pairs[i].second;
00700   }
00701 }
00702 
00703 Type VCL::recordType(const string& field, const Type& type)
00704 {
00705   vector<string> fields;
00706   vector<Type> kids;
00707   fields.push_back(field);
00708   kids.push_back(type);
00709   return Type(d_theoryRecords->recordType(fields, kids));
00710 }
00711 
00712 
00713 Type VCL::recordType(const string& field0, const Type& type0,
00714                      const string& field1, const Type& type1) {
00715   vector<string> fields;
00716   vector<Type> kids;
00717   fields.push_back(field0);
00718   fields.push_back(field1);
00719   kids.push_back(type0);
00720   kids.push_back(type1);
00721   sort2(fields, kids);
00722   return Type(d_theoryRecords->recordType(fields, kids));
00723 }
00724 
00725 
00726 Type VCL::recordType(const string& field0, const Type& type0,
00727                      const string& field1, const Type& type1,
00728                      const string& field2, const Type& type2)
00729 {
00730   vector<string> fields;
00731   vector<Type> kids;
00732   fields.push_back(field0);
00733   fields.push_back(field1);
00734   fields.push_back(field2);
00735   kids.push_back(type0);
00736   kids.push_back(type1);
00737   kids.push_back(type2);
00738   sort2(fields, kids);
00739   return Type(d_theoryRecords->recordType(fields, kids));
00740 }
00741 
00742 Type VCL::recordType(const vector<string>& fields,
00743                      const vector<Type>& types)
00744 {
00745   DebugAssert(fields.size() == types.size(),
00746               "VCL::recordType: number of fields is different \n"
00747               "from the number of types");
00748   // Create copies of the vectors to sort them
00749   vector<string> fs(fields);
00750   vector<Type> ts(types);
00751   sort2(fs, ts);
00752   return Type(d_theoryRecords->recordType(fs, ts));
00753 }
00754 
00755 
00756 Type VCL::dataType(const string& constructor,
00757                    const vector<string>& selectors, const vector<Type>& types)
00758 {
00759   vector<string> constructors;
00760   constructors.push_back(constructor);
00761 
00762   vector<vector<string> > selectorsVec;
00763   selectorsVec.push_back(selectors);
00764 
00765   vector<vector<Type> > typesVec;
00766   typesVec.push_back(types);
00767 
00768   return dataType(constructors, selectorsVec, typesVec);
00769 }
00770 
00771 
00772 Type VCL::dataType(const vector<string>& constructors,
00773                    const vector<vector<string> >& selectors,
00774                    const vector<vector<Type> >& types)
00775 {
00776   return d_theoryDatatype->dataType(constructors, selectors, types);
00777 }
00778 
00779 
00780 Type VCL::arrayType(const Type& typeIndex, const Type& typeData)
00781 {
00782   return ::arrayType(typeIndex, typeData);
00783 }
00784 
00785 
00786 Type VCL::funType(const Type& typeDom, const Type& typeRan)
00787 {
00788   return typeDom.funType(typeRan);
00789 }
00790 
00791 
00792 Type VCL::funType(const std::vector<Type>& typeDom, const Type& typeRan) {
00793   DebugAssert(typeDom.size() >= 1, "VCL::funType: missing domain types");
00794   return ::funType(typeDom, typeRan);
00795 }
00796 
00797 
00798 Type VCL::createType(const string& typeName)
00799 {
00800   if(d_osdump) {
00801     d_osdump << newExpr(d_em, TYPE, listExpr(idExpr(typeName))) << endl;
00802   }
00803   return d_theoryCore->newTypeExpr(typeName);
00804 }
00805 
00806 
00807 Type VCL::createType(const std::string& typeName, const Type& def)
00808 {
00809   if(d_osdump && !d_translate) {
00810     d_osdump << newExpr(d_em, TYPE, idExpr(typeName), def.getExpr())
00811              << endl;
00812   }
00813   return d_theoryCore->newTypeExpr(typeName, def);
00814 }
00815 
00816 
00817 Type VCL::lookupType(const std::string& typeName)
00818 {
00819   // TODO: check if it already exists
00820   return d_theoryCore->newTypeExpr(typeName);
00821 }
00822 
00823 
00824 Expr VCL::varExpr(const string& name, const Type& type)
00825 {
00826   // Check if the ofstream is open (as opposed to the command line flag)
00827   if(d_osdump) {
00828     d_osdump << newExpr(d_em, CONST, idExpr(name), type.getExpr())
00829              << endl;
00830   }
00831   return d_theoryCore->newVar(name, type);
00832 }
00833 
00834 
00835 Expr VCL::varExpr(const string& name, const Type& type, const Expr& def)
00836 {
00837   // Check if the ofstream is open (as opposed to the command line flag)
00838   if(d_osdump && !d_translate) {
00839     d_osdump << newExpr(d_em, CONST, idExpr(name), type.getExpr(), def)
00840              << endl;
00841   }
00842   // Prove the TCCs of the definition
00843   if(getFlags()["tcc"].getBool()) {
00844     Type tpDef(getType(def)), tpVar(type);
00845     // Make sure that tpDef is a subtype of tpVar; that is, prove
00846     // FORALL (x: tpDef): typePred(tpVar)(x)
00847     if(tpDef != tpVar) {
00848       // Typecheck the base types
00849       if(getBaseType(tpDef) != getBaseType(type)) {
00850         throw TypecheckException("Type mismatch in constant definition:\n"
00851                                  "Constant "+name+
00852                                  " is declared with type:\n  "
00853                                  +type.toString()
00854                                  +"\nBut the type of definition is\n  "
00855                                  +tpDef.toString());
00856       }
00857       TRACE("tccs", "CONSTDEF: "+name+" : "+tpVar.toString()
00858             +" := <value> : ", tpDef, ";");
00859       vector<Expr> boundVars;
00860       boundVars.push_back(boundVarExpr(name, "tcc", tpDef));
00861       Expr body(getTypePred(tpVar, boundVars[0]));
00862       Expr quant(forallExpr(boundVars, body));
00863       // Query the subtyping formula
00864       push();
00865       if(!query(quant, true)) {
00866         throw TypecheckException
00867           ("Type mismatch in constant definition:\n"
00868            "Constant "+name+
00869            " is declared with type:\n  "
00870            +type.toString()
00871            +"\nBut the type of definition is\n  "
00872            +getType(def).toString()
00873            +"\n\n which is not a subtype of the constant");
00874       }
00875       pop();
00876     }
00877   }
00878   return d_theoryCore->newVar(name, type, def);
00879 }
00880 
00881 
00882 Expr VCL::boundVarExpr(const string& name, const string& uid, 
00883                        const Type& type) {
00884   return d_theoryCore->newBoundVar(name, uid, type);
00885 }
00886 
00887 
00888 Expr VCL::lookupVar(const string& name, Type* type)
00889 {
00890   return d_theoryCore->lookupVar(name, type);
00891 }
00892 
00893 
00894 Type VCL::getType(const Expr& e)
00895 {
00896   return d_theoryCore->getType(e);
00897 }
00898 
00899 Expr VCL::getTypePred(const Type&t, const Expr& e)
00900 {
00901   return d_theoryCore->getTypePred(t, e);
00902 }
00903 
00904 
00905 Type VCL::getBaseType(const Expr& e)
00906 {
00907   return d_theoryCore->getBaseType(e);
00908 }
00909 
00910 
00911 Type VCL::getBaseType(const Type& t)
00912 {
00913   return d_theoryCore->getBaseType(t);
00914 }
00915 
00916 
00917 Expr VCL::importExpr(const Expr& e)
00918 {
00919   return d_em->rebuildExpr(e);
00920 }
00921 
00922 
00923 Type VCL::importType(const Type& t)
00924 {
00925   return Type(d_em->rebuildExpr(t.getExpr()));
00926 }
00927 
00928 
00929 Expr VCL::eqExpr(const Expr& child0, const Expr& child1)
00930 {
00931   return child0.eqExpr(child1);
00932 }
00933 
00934 
00935 Expr VCL::trueExpr()
00936 {
00937   return d_em->trueExpr();
00938 }
00939 
00940 
00941 Expr VCL::falseExpr()
00942 {
00943   return d_em->falseExpr();
00944 }
00945 
00946 
00947 Expr VCL::notExpr(const Expr& child)
00948 {
00949   return !child;
00950 }
00951 
00952 
00953 Expr VCL::andExpr(const Expr& left, const Expr& right)
00954 {
00955   return left && right;
00956 }
00957 
00958 
00959 Expr VCL::andExpr(const vector<Expr>& children)
00960 {
00961   DebugAssert(children.size() > 0, "VCL::andExpr()");
00962   return Expr(getEM(), AND, children);
00963 }
00964 
00965 
00966 Expr VCL::orExpr(const Expr& left, const Expr& right)
00967 {
00968   return left || right;
00969 }
00970 
00971 
00972 Expr VCL::orExpr(const vector<Expr>& children)
00973 {
00974   DebugAssert(children.size() > 0, "VCL::orExpr()");
00975   return Expr(getEM(), OR, children);
00976 }
00977 
00978 
00979 Expr VCL::impliesExpr(const Expr& hyp, const Expr& conc)
00980 {
00981   return hyp.impExpr(conc);
00982 }
00983 
00984 
00985 Expr VCL::iffExpr(const Expr& left, const Expr& right)
00986 {
00987   return left.iffExpr(right);
00988 }
00989 
00990 
00991 Expr VCL::iteExpr(const Expr& ifpart, const Expr& thenpart, const Expr& elsepart)
00992 {
00993   return ifpart.iteExpr(thenpart, elsepart);
00994 }
00995 
00996 
00997 Expr VCL::ratExpr(int n, int d)
00998 {
00999   DebugAssert(d != 0,"denominator cannot be 0");
01000   return newRatExpr(d_em, Rational(n,d));
01001 }
01002 
01003 
01004 Expr VCL::ratExpr(const string& n, const string& d, int base)
01005 {
01006   return newRatExpr(d_em, Rational(n.c_str(), d.c_str(), base));
01007 }
01008 
01009 Expr VCL::ratExpr(const string& n, int base)
01010 {
01011   return newRatExpr(d_em, Rational(n.c_str(), base));
01012 }
01013 
01014 
01015 Expr VCL::uminusExpr(const Expr& child)
01016 {
01017   return -child;
01018 }
01019 
01020 
01021 Expr VCL::plusExpr(const Expr& left, const Expr& right)
01022 {
01023   return left + right;
01024 }
01025 
01026 
01027 Expr VCL::minusExpr(const Expr& left, const Expr& right)
01028 {
01029   return left - right;
01030 }
01031 
01032 
01033 Expr VCL::multExpr(const Expr& left, const Expr& right)
01034 {
01035   return left * right;
01036 }
01037 
01038 
01039 Expr VCL::powExpr(const Expr& x, const Expr& n)
01040 {
01041   return ::powExpr(n, x);
01042 }
01043 
01044 Expr VCL::divideExpr(const Expr& num, const Expr& denom)
01045 {
01046   return ::divideExpr(num,denom);
01047 }
01048 
01049 
01050 Expr VCL::ltExpr(const Expr& left, const Expr& right)
01051 {
01052   return ::ltExpr(left, right);
01053 }
01054 
01055 
01056 Expr VCL::leExpr(const Expr& left, const Expr& right)
01057 {
01058   return ::leExpr(left, right);
01059 }
01060 
01061 
01062 Expr VCL::gtExpr(const Expr& left, const Expr& right)
01063 {
01064   return ::gtExpr(left, right);
01065 }
01066 
01067 
01068 Expr VCL::geExpr(const Expr& left, const Expr& right)
01069 {
01070   return ::geExpr(left, right);
01071 }
01072 
01073 
01074 Expr VCL::recordExpr(const string& field, const Expr& expr)
01075 {
01076   vector<string> fields;
01077   vector<Expr> kids;
01078   kids.push_back(expr);
01079   fields.push_back(field);
01080   return d_theoryRecords->recordExpr(fields, kids);
01081 }
01082 
01083 
01084 Expr VCL::recordExpr(const string& field0, const Expr& expr0,
01085                      const string& field1, const Expr& expr1)
01086 {
01087   vector<string> fields;
01088   vector<Expr> kids;
01089   fields.push_back(field0);
01090   fields.push_back(field1);
01091   kids.push_back(expr0);
01092   kids.push_back(expr1);
01093   sort2(fields, kids);
01094   return d_theoryRecords->recordExpr(fields, kids);
01095 }
01096 
01097 
01098 Expr VCL::recordExpr(const string& field0, const Expr& expr0,
01099                      const string& field1, const Expr& expr1,
01100                      const string& field2, const Expr& expr2)
01101 {
01102   vector<string> fields;
01103   vector<Expr> kids;
01104   fields.push_back(field0);
01105   fields.push_back(field1);
01106   fields.push_back(field2);
01107   kids.push_back(expr0);
01108   kids.push_back(expr1);
01109   kids.push_back(expr2);
01110   sort2(fields, kids);
01111   return d_theoryRecords->recordExpr(fields, kids);
01112 }
01113 
01114 
01115 Expr VCL::recordExpr(const vector<string>& fields,
01116                      const vector<Expr>& exprs)
01117 {
01118   DebugAssert(fields.size() > 0, "VCL::recordExpr()");
01119   DebugAssert(fields.size() == exprs.size(),"VCL::recordExpr()");
01120   // Create copies of the vectors to sort them
01121   vector<string> fs(fields);
01122   vector<Expr> es(exprs);
01123   sort2(fs, es);
01124   return d_theoryRecords->recordExpr(fs, es);
01125 }
01126 
01127 
01128 Expr VCL::recSelectExpr(const Expr& record, const string& field)
01129 {
01130   return d_theoryRecords->recordSelect(record, field);
01131 }
01132 
01133 
01134 Expr VCL::recUpdateExpr(const Expr& record, const string& field,
01135                         const Expr& newValue)
01136 {
01137   return d_theoryRecords->recordUpdate(record, field, newValue);
01138 }
01139 
01140 
01141 Expr VCL::readExpr(const Expr& array, const Expr& index)
01142 {
01143   return read(array, index);
01144 }
01145 
01146 
01147 Expr VCL::writeExpr(const Expr& array, const Expr& index, const Expr& newValue)
01148 {
01149   return write(array, index, newValue);
01150 }
01151 
01152 
01153 Expr VCL::tupleExpr(const std::vector<Expr>& exprs) {
01154   DebugAssert(exprs.size() > 0, "VCL::tupleExpr()");
01155   return d_theoryRecords->tupleExpr(exprs);
01156 }
01157 
01158 
01159 Expr VCL::tupleSelectExpr(const Expr& tuple, int index)
01160 {
01161   return d_theoryRecords->tupleSelect(tuple, index);
01162 }
01163 
01164 
01165 Expr VCL::tupleUpdateExpr(const Expr& tuple, int index, const Expr& newValue)
01166 {
01167   return d_theoryRecords->tupleUpdate(tuple, index, newValue);
01168 }
01169 
01170 
01171 Expr VCL::datatypeConsExpr(const string& constructor, const vector<Expr>& args)
01172 {
01173   return d_theoryDatatype->datatypeConsExpr(constructor, args);
01174 }
01175 
01176 
01177 Expr VCL::datatypeSelExpr(const string& selector, const Expr& arg)
01178 {
01179   return d_theoryDatatype->datatypeSelExpr(selector, arg);
01180 }
01181 
01182 
01183 Expr VCL::forallExpr(const std::vector<Expr>& vars, const Expr& body) {
01184   DebugAssert(vars.size() > 0, "VCL::andExpr()");
01185   return newClosureExpr(d_em, FORALL, vars, body);
01186 }
01187 
01188 
01189 Expr VCL::existsExpr(const std::vector<Expr>& vars, const Expr& body) {
01190   return newClosureExpr(d_em, EXISTS, vars, body);
01191 }
01192 
01193 
01194 Expr VCL::lambdaExpr(const std::vector<Expr>& vars, const Expr& body) {
01195   return newClosureExpr(d_em, LAMBDA, vars, body);
01196 }
01197 
01198 
01199 Expr VCL::simulateExpr(const Expr& f, const Expr& s0,
01200                        const std::vector<Expr>& inputs, const Expr& n) {
01201   vector<Expr> kids;
01202   kids.push_back(f);
01203   kids.push_back(s0);
01204   kids.insert(kids.end(), inputs.begin(), inputs.end());
01205   kids.push_back(n);
01206   return newExpr(getEM(), SIMULATE, kids);
01207 }
01208 
01209 
01210 Op VCL::createOp(const string& name, const Type& type)
01211 {
01212   // Check if the ofstream is open (as opposed to the command line flag)
01213   if(d_osdump) {
01214     d_osdump << newExpr(d_em, CONST, idExpr(name), type.getExpr())
01215              << endl;
01216   }
01217   return d_theoryCore->newFunction(name, type);
01218 }
01219 
01220 
01221 Op VCL::createOp(const string& name, const Type& type, const Expr& def)
01222 {
01223   // Check if the ofstream is open (as opposed to the command line flag)
01224   if(d_osdump) {
01225     d_osdump << newExpr(d_em, CONST, idExpr(name), type.getExpr(), def)
01226              << endl;
01227   }
01228   // Prove the TCCs of the definition
01229   if(getFlags()["tcc"].getBool()) {
01230     Type tpDef(getType(def)), tpVar(type);
01231     // Make sure that tpDef is a subtype of tpVar; that is, prove
01232     // FORALL (x: tpDef): typePred(tpVar)(x)
01233     if(tpDef != tpVar) {
01234       TRACE("tccs", "CONSTDEF: "+name+" : "+tpVar.toString()
01235             +" := <value> : ", tpDef, ";");
01236       bool typesMatch(true);
01237       if(tpDef.isFunction() || tpVar.isFunction())
01238         // For functions, require exact type match
01239         typesMatch=false;
01240       else { // Non-function type: check the TCCs
01241         vector<Expr> boundVars;
01242         boundVars.push_back(boundVarExpr(name, "tcc", tpDef));
01243         Expr body(getTypePred(tpVar, boundVars[0]));
01244         Expr quant(forallExpr(boundVars, body));
01245         // Query the subtyping formula
01246         push();
01247         typesMatch=query(quant, true);
01248       }
01249       if(!typesMatch) {
01250         throw TypecheckException
01251           ("Type mismatch in constant definition:\n"
01252            "Constant "+name+
01253            " is declared with type:\n  "
01254            +type.toString()
01255            +"\nBut the type of definition is\n  "
01256            +getType(def).toString()
01257            +"\n\n which is not a subtype of the constant");
01258       }
01259       pop();
01260     }
01261   }
01262   return d_theoryCore->newFunction(name, type, def);
01263 }
01264 
01265 
01266 Expr VCL::funExpr(const Op& op, const Expr& child)
01267 {
01268   return newExpr(op, child);
01269 }
01270 
01271 
01272 Expr VCL::funExpr(const Op& op, const Expr& left, const Expr& right)
01273 {
01274   return newExpr(op, left, right);
01275 }
01276 
01277 
01278 Expr VCL::funExpr(const Op& op, const Expr& child0, const Expr& child1, const Expr& child2)
01279 {
01280   return newExpr(op, child0, child1, child2);
01281 }
01282 
01283 
01284 Expr VCL::funExpr(const Op& op, const vector<Expr>& children)
01285 {
01286   return newExpr(op, children);
01287 }
01288 
01289 
01290 Expr VCL::stringExpr(const string& str) {
01291   return newStringExpr(getEM(), str);
01292 }
01293 
01294 
01295 Expr VCL::idExpr(const string& name) {
01296   return newExpr(getEM(), ID, stringExpr(name));
01297 }
01298 
01299 Expr VCL::listExpr(const vector<Expr>& kids) {
01300   return newExpr(getEM(), RAW_LIST, kids);
01301 }
01302 
01303 
01304 Expr VCL::listExpr(const Expr& e1) {
01305   return newExpr(getEM(), RAW_LIST, e1);
01306 }
01307 
01308 
01309 Expr VCL::listExpr(const Expr& e1, const Expr& e2) {
01310   return newExpr(getEM(), RAW_LIST, e1, e2);
01311 }
01312 
01313 
01314 Expr VCL::listExpr(const Expr& e1, const Expr& e2, const Expr& e3) {
01315   return newExpr(getEM(), RAW_LIST, e1, e2, e3);
01316 }
01317 
01318 
01319 Expr VCL::listExpr(const std::string& op, const std::vector<Expr>& kids) {
01320   vector<Expr> newKids;
01321   newKids.push_back(idExpr(op));
01322   newKids.insert(newKids.end(), kids.begin(), kids.end());
01323   return listExpr(newKids);
01324 }
01325 
01326 
01327 Expr VCL::listExpr(const std::string& op, const Expr& e1) {
01328   return newExpr(getEM(), RAW_LIST, idExpr(op), e1);
01329 }
01330 
01331 
01332 Expr VCL::listExpr(const std::string& op, const Expr& e1,
01333                    const Expr& e2) {
01334   return newExpr(getEM(), RAW_LIST, idExpr(op), e1, e2);
01335 }
01336 
01337 
01338 Expr VCL::listExpr(const std::string& op, const Expr& e1,
01339                    const Expr& e2, const Expr& e3) {
01340   vector<Expr> kids;
01341   kids.push_back(idExpr(op));
01342   kids.push_back(e1);
01343   kids.push_back(e2);
01344   kids.push_back(e3);
01345   return listExpr(kids);
01346 }
01347 
01348 
01349 void VCL::printExpr(const Expr& e) {
01350   printExpr(e, cout);
01351 }
01352 
01353 
01354 void VCL::printExpr(const Expr& e, ostream& os) {
01355   if(getFlags()["reorder"].getBool()){
01356     Expr e1 = (d_theoryCore->preprocess(e)).getRHS();
01357     srandom(getFlags()["seed"].getInt());
01358     e1 = d_theoryCore->ite_reorder(e1);
01359     os << e1 ;
01360     return;
01361   }
01362   if(getFlags()["pq"].getBool()){
01363     os << e ;
01364     return;
01365   }
01366   os << e << endl;
01367 }
01368 
01369 
01370 
01371 
01372 
01373 Expr VCL::parseExpr(const Expr& e) {
01374   return d_theoryCore->parseExprTop(e);
01375 }
01376 
01377 
01378 Type VCL::parseType(const Expr& e) {
01379   return Type(d_theoryCore->parseExpr(e));
01380 }
01381 
01382 
01383 void VCL::assertFormula(const Expr& e)
01384 {
01385   // Typecheck the user input
01386   if(!getType(e).isBool()) {
01387     throw TypecheckException("Non-BOOLEAN formula in ASSERT:\n  "
01388                              +newExpr(getEM(), ASSERT, e).toString()
01389                              +"\nDerived type of the formula:\n  "
01390                              +getType(e).toString());
01391   }
01392 
01393   // Check if the ofstream is open (as opposed to the command line flag)
01394   if(d_osdump) {
01395     if (d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
01396       d_osdump << "  :assumption" << endl;
01397       d_osdump << e << endl;
01398     }
01399     else {
01400       d_osdump << newExpr(d_em, ASSERT, e) << endl;
01401     }
01402   }
01403   // Expr e = getFlags()["cnf"].getBool() ? d_cnf->cnf(ee) : ee;
01404 
01405   TRACE("facts", "VCL::assertFormula(", e, ") {");
01406   // See if e was already asserted before
01407   if(d_userAssertions->count(e) > 0) {
01408     TRACE_MSG("facts", "VCL::assertFormula[repeated assertion] => }");
01409     return;
01410   }
01411   // Check the validity of the TCC
01412   Theorem tccThm;
01413   if(getFlags()["tcc"].getBool()) {
01414     Expr tcc(d_theoryCore->getTCC(e));
01415     int scope = scopeLevel();
01416     d_cm->push();
01417     tccThm = d_se->checkValidThm(tcc);
01418     if(tccThm.isNull()) {
01419       throw TypecheckException("Failed TCC for the formula in ASSERT:\n\n  "
01420                                +newExpr(getEM(), ASSERT, e).toString()
01421                                +"\n\nThe failed TCC is:\n\n  "
01422                                +tcc.toString()
01423                                +"\n\nWhich simplified to:\n\n  "
01424                                +simplify(tcc).toString()
01425                                +"\n\nAnd the last formula is not valid "
01426                                "in the current context.");
01427     }
01428     else
01429       d_lastQueryTCC = tccThm;
01430     d_cm->popto(scope);
01431   }
01432 
01433   Theorem thm = d_se->newUserAssertion(e);
01434   (*d_userAssertions)[e] = UserAssertion(thm, tccThm);
01435   if (!thm.isNull()) {
01436     d_theoryCore->addFact(d_theoryCore->preprocess(thm));
01437   }
01438   TRACE_MSG("facts", "VCL::assertFormula => }");
01439 }
01440 
01441 
01442 Expr VCL::getImpliedLiteral()
01443 {
01444   return d_se->getImpliedLiteral();
01445 }
01446 
01447 
01448 Expr VCL::simplify(const Expr& e) {
01449   if(getFlags()["tcc"].getBool())
01450     return simplifyThm(e).getRHS();
01451   else
01452     return simplifyThm2(e).getRHS();
01453 }
01454 
01455 
01456 Theorem3 VCL::simplifyThm(const Expr& e)
01457 {
01458   DebugAssert(getFlags()["tcc"].getBool(),
01459               "VCL::simplifyThm() is called without +tcc flag");
01460   // Typecheck the user input (here it only needs to typecheck without errors)
01461   getType(e);
01462   // Assert the type predicates of e
01463   d_theoryCore->addFact(d_theoryCore->subtypePredicate(e));
01464 
01465   // Now check the TCC
01466   Expr tcc(d_theoryCore->getTCC(e));
01467   int scope = scopeLevel();
01468   d_cm->push();
01469   Theorem tccThm = d_se->checkValidThm(tcc);
01470   if(tccThm.isNull()) {
01471     throw TypecheckException
01472       ("Failed TCC for the formula in TRANSFORM:\n\n  "
01473        +newExpr(getEM(), TRANSFORM, e).toString()
01474        +"\n\nThe failed TCC is:\n\n  "
01475        +tcc.toString()
01476        +"\n\nWhich simplified to:\n\n  "
01477        +simplify(tcc).toString()
01478        +"\n\nAnd the last formula is not valid in the current context.");
01479   }
01480   else
01481     d_lastQueryTCC = tccThm;
01482   d_cm->popto(scope);
01483   // Finally, we are ready to simplify the original expression
01484   Theorem res2 = d_theoryCore->preprocess(e);
01485   Theorem simpThm =  d_theoryCore->simplifyThm(res2.getRHS(),
01486                                                true /* force rebuild */);
01487   res2 = d_theoryCore->transitivityRule(res2, simpThm);
01488   Theorem3 res3;
01489   // For soundness, we have to re-prove the TCC for the entire formula e=e'
01490   tcc = d_theoryCore->getTCC(res2.getExpr());
01491   scope = scopeLevel();
01492   d_cm->push();
01493   tccThm = d_se->checkValidThm(tcc);
01494   // We may still fail the TCC if the DPs have some funky total
01495   // interpretation of partial functions, in which case it should be
01496   // considered a bug, for any practical purposes.
01497   DebugAssert(!tccThm.isNull(), "VCL::simplifyThm(): TCC for e=e' failed:"
01498               "\n res2 = "+res2.getExpr().toString()
01499               +"\n tcc = "+tcc.toString());
01500   res3 = d_theoryCore->queryTCC(res2, tccThm);
01501   d_cm->popto(scope);
01502   return res3;
01503 }
01504 
01505 
01506 Theorem VCL::simplifyThm2(const Expr& e)
01507 {
01508   // Typecheck the user input (here it only needs to typecheck without errors)
01509   getType(e);
01510   // Assert the type predicates of e
01511   d_theoryCore->addFact(d_theoryCore->subtypePredicate(e));
01512 
01513   // We are ready to simplify the original expression
01514   Theorem res2 = d_theoryCore->preprocess(e);
01515   Theorem simpThm =  d_theoryCore->simplifyThm(res2.getRHS(),
01516                                                true /* force rebuild */);
01517   res2 = d_theoryCore->transitivityRule(res2, simpThm);
01518   return res2;
01519 }
01520 
01521 void VCL::printV(const Expr& e) {
01522   if(e.getKind() == UCONST || (e.getKind() == APPLY && e.arity() == 0)) {
01523     Str_To_Expr::iterator it = d_vars.find(e.toString());
01524     if(it == d_vars.end()){
01525       cout << e << " : " << getType(e).toString() << ";" << endl;
01526       d_vars[e.toString()] = e;
01527     }
01528     return;
01529   }
01530   if(e.getKind() == APPLY) {
01531     string name = e.getFun().toString();
01532     Str_To_Expr::iterator it = d_vars.find(name);
01533     if(it == d_vars.end()) {
01534       Expr e1 = e.getFun();
01535       cout << name << " : " << getType(e1).toString() << ";" << endl;
01536       d_vars[name] = e1;
01537     }
01538   }
01539   
01540   for(int i=0; i<e.arity(); i++) {
01541     printV(e[i]);
01542   }
01543 }
01544 
01545 /*!
01546  * \param e is the queried formula
01547  *
01548  * \param isTCC is true when quering a TCC.  In this case, the TCC of
01549  * e must be TRUE.
01550  */
01551 bool VCL::query(const Expr& e, bool isTCC)
01552 {
01553   // Expr e = getFlags()["cnf"].getBool() ? d_cnf->cnf(ee.negate()).negate() : ee;
01554 
01555   TRACE("facts", "VCL::query(", e,
01556         string(isTCC? ", isTCC=true" : "")+") {");
01557   // Typecheck the user input
01558   if(!getType(e).isBool()) {
01559     throw TypecheckException("Non-BOOLEAN formula in QUERY:\n  "
01560                              +newExpr(getEM(), QUERY, e).toString()
01561                              +"\nDerived type of the formula:\n  "
01562                              +getType(e).toString());
01563   }
01564 
01565   // Check if the ofstream is open (as opposed to the command line flag)
01566   if(d_osdump) {
01567     if (d_translate) {
01568       d_osdump << "  :formula" << endl;
01569       d_osdump << !e << endl;
01570       // For now, just assume status is unknown.
01571       d_osdumpTranslate << "  :status unknown" << endl;
01572       return false;
01573     }
01574     else {
01575       d_osdump << newExpr(d_em, QUERY, e) << endl;
01576     }
01577   }
01578 
01579   // Check the validity of the TCC
01580   if(!isTCC && getFlags()["tcc"].getBool()) {
01581     Expr tcc(d_theoryCore->getTCC(e));
01582     // FIXME: we have to guarantee that the TCC of 'tcc' is always valid
01583     int scope = scopeLevel();
01584     d_cm->push();
01585     d_lastQueryTCC = d_se->checkValidThm(tcc);
01586     if(d_lastQueryTCC.isNull()) {
01587       throw TypecheckException("Failed TCC for the formula in QUERY:\n\n  "
01588                                +newExpr(getEM(), QUERY, e).toString()
01589                                +"\n\nThe failed TCC is:\n\n  "
01590                                +tcc.toString()
01591                                +"\n\nWhich simplified to:\n\n  "
01592                                +simplify(tcc).toString()
01593                                +"\n\nAnd the last formula is not valid "
01594                                "in the current context.");
01595     }
01596     d_cm->popto(scope);
01597   }
01598   if(getFlags()["reorder"].getBool() || getFlags()["pq"].getBool()){
01599     cout << "%% Print query variables:" << endl;
01600     printV(e);
01601     cout << "QUERY ";
01602     printExpr(e);
01603     cout << ";" << endl;
01604     cout << "%%";
01605     return true;
01606   }
01607   Theorem res = d_se->checkValidThm(e);
01608   // Save the result for subsequent commands like DUMP_PROOF
01609   if(!res.isNull()) {
01610     if(isTCC)
01611       d_lastQueryTCC = res;
01612     else if (getFlags()["tcc"].getBool()) {
01613       d_lastQuery = d_theoryCore->queryTCC(res, d_lastQueryTCC);
01614     }
01615   } else { // Clean up the variables
01616     d_lastQueryTCC = Theorem();
01617     d_lastQuery = Theorem3();
01618     d_lastClosure = Theorem3();
01619   }
01620   TRACE("facts", "VCL::query => ", res.isNull()? "false" : "true", " }");
01621 
01622   if(d_translate && d_em->getOutputLang() == SMTLIB_LANG) {
01623     d_osdumpTranslate << "  :status ";
01624     if (!res.isNull()) d_osdumpTranslate << "unsat" << endl;
01625     else if(incomplete()) {
01626       d_osdumpTranslate << "unknown" << endl;
01627     }
01628     else d_osdumpTranslate << "sat" << endl;
01629   }
01630 
01631   return !res.isNull();
01632 }
01633 
01634 
01635 bool VCL::checkUnsat(const Expr& e)
01636 {
01637   return query(!e);
01638 }
01639 
01640 
01641 bool VCL::checkContinue()
01642 {
01643   if(d_osdump) {
01644     d_osdump << newExpr(d_em, CONTINUE) << endl;
01645   }
01646   vector<Expr> assertions;
01647   d_se->getCounterExample(assertions);
01648   if (assertions.size() == 0) {
01649     d_se->restart(falseExpr());
01650     return true;
01651   }
01652   Expr eAnd = assertions.size() == 1 ? assertions[0] : andExpr(assertions);
01653   return d_se->restart(!eAnd);
01654 }
01655 
01656 
01657 bool VCL::restart(const Expr& e)
01658 {
01659   if (d_osdump) {
01660     d_osdump << newExpr(d_em, RESTART, e) << endl;
01661   }
01662   return d_se->restart(e);
01663 }
01664 
01665 
01666 void VCL::getAssertions(vector<Expr>& assertions)
01667 {
01668   d_se->getAssertions(assertions);
01669 }
01670 
01671 
01672 void VCL::getConcreteModel(ExprMap<Expr> & m)
01673 {
01674   if(d_osdump) {
01675     d_osdump << newExpr(d_em, COUNTEREXAMPLE) << endl;
01676   }
01677   d_se->getConcreteModel(m);
01678 }
01679 
01680 
01681 void VCL::getCounterExample(vector<Expr>& assertions, bool inOrder)
01682 {
01683   d_se->getCounterExample(assertions, inOrder);
01684 }
01685 
01686 bool VCL::inconsistent(vector<Expr>& assumptions)
01687 {
01688   if (d_theoryCore->inconsistent()) {
01689     getAssumptions(d_theoryCore->inconsistentThm().getAssumptionsRef(),
01690                    assumptions);
01691     return true;
01692   }
01693   return false;
01694 }
01695 
01696 
01697 bool VCL::incomplete() {
01698   // Return true only after a failed query
01699   return (d_lastQuery.isNull() && d_theoryCore->incomplete());
01700 }
01701 
01702 
01703 bool VCL::incomplete(vector<string>& reasons) {
01704   // Return true only after a failed query
01705   return (d_lastQuery.isNull() && d_theoryCore->incomplete(reasons));
01706 }
01707 
01708 
01709 void VCL::setResourceLimit(unsigned limit) {
01710   d_theoryCore->setResourceLimit(limit);
01711 }
01712 
01713 
01714 Proof VCL::getProof()
01715 {
01716   if(d_lastQuery.isNull())
01717     throw EvalException
01718       ("Method getProof() (or command DUMP_PROOF)\n"
01719        " must be called only after a Valid QUERY");
01720   return d_se->getProof();
01721 }
01722 
01723 
01724 void VCL::getAssumptions(vector<Expr>& assumptions)
01725 {
01726   if(d_lastQuery.isNull())
01727     throw EvalException
01728       ("Method getAssumptions() (or command DUMP_ASSUMPTIONS)\n"
01729        " must be called only after a Valid QUERY");
01730   getAssumptions(d_lastQuery.getAssumptionsRef(), assumptions);
01731 }
01732 
01733 
01734 void VCL::getAssumptionsTCC(vector<Expr>& assumptions)
01735 {
01736   if(d_lastQuery.isNull())
01737     throw EvalException
01738       ("Method getAssumptionsTCC() (or command DUMP_TCC_ASSUMPTIONS)\n"
01739        " must be called only after a Valid QUERY");
01740   getAssumptions(d_lastQueryTCC.getAssumptionsRef(), assumptions);
01741 }
01742 
01743 
01744 const Expr& VCL::getTCC(){
01745   static Expr null;
01746   if(d_lastQueryTCC.isNull()) return null;
01747   else return d_lastQueryTCC.getExpr();
01748 }
01749 
01750 
01751 const Proof& VCL::getProofTCC() {
01752   static Proof null;
01753   if(d_lastQueryTCC.isNull()) return null;
01754   else return d_lastQueryTCC.getProof();
01755 }
01756 
01757 
01758 const Expr& VCL::getClosure() {
01759   static Expr null;
01760   if(d_lastClosure.isNull() && !d_lastQuery.isNull()) {
01761     // Construct the proof of closure and cache it in d_lastClosure
01762     d_lastClosure = deriveClosure(d_lastQuery);
01763   }
01764   if(d_lastClosure.isNull()) return null;
01765   else return d_lastClosure.getExpr();
01766 }
01767 
01768 
01769 const Proof& VCL::getProofClosure() {
01770   static Proof null;
01771   if(d_lastClosure.isNull() && !d_lastQuery.isNull()) {
01772     // Construct the proof of closure and cache it in d_lastClosure
01773     d_lastClosure = deriveClosure(d_lastQuery);
01774   }
01775   if(d_lastClosure.isNull()) return null;
01776   else return d_lastClosure.getProof();
01777 }
01778 
01779 
01780 int VCL::stackLevel()
01781 {
01782   return d_scopeStack.size();
01783 }
01784 
01785 
01786 void VCL::push()
01787 {
01788   TRACE("vcl", "push(): stack size = ", d_scopeStack.size(), "{ ");
01789   // Check if the ofstream is open (as opposed to the command line flag)
01790   if(d_osdump) {
01791     d_osdump << newExpr(d_em, PUSH) << endl;
01792   }
01793   d_scopeStack.push_back(scopeLevel());
01794   d_cm->push();
01795   TRACE("vcl", "push => stack size ", d_scopeStack.size(), "}");
01796 }
01797 
01798 
01799 void VCL::pop()
01800 {
01801   TRACE("vcl", "pop(): stack size = ", d_scopeStack.size(), "{ ");
01802   // Check if the ofstream is open (as opposed to the command line flag)
01803   if(d_osdump) {
01804     d_osdump << newExpr(d_em, POP) << endl;
01805   }
01806   if(d_scopeStack.size() != 0) {
01807     d_cm->popto(d_scopeStack.back());
01808     d_scopeStack.pop_back();
01809   }
01810   TRACE("vcl", "pop => stack size ", d_scopeStack.size(), "}");
01811 }
01812 
01813 
01814 void VCL::popto(int toLevel)
01815 {
01816   // Check if the ofstream is open (as opposed to the command line flag)
01817   if(d_osdump) {
01818     d_osdump << newExpr(d_em, POPTO, ratExpr(toLevel, 1)) << endl;
01819   }
01820   if (toLevel < 0) toLevel = 0;
01821   while (stackLevel() > toLevel+1) {
01822     d_scopeStack.pop_back();
01823   }
01824   if (stackLevel() > toLevel) {
01825     d_cm->popto(d_scopeStack.back());
01826     d_scopeStack.pop_back();
01827   }
01828 }
01829 
01830 
01831 int VCL::scopeLevel()
01832 {
01833   return d_cm->scopeLevel();
01834 }
01835 
01836 
01837 void VCL::pushScope()
01838 {
01839   d_cm->push();
01840   if(d_osdump) {
01841     d_osdump << newExpr(d_em, PUSH_SCOPE) << endl;
01842   }
01843   IF_DEBUG(if((*d_flags)["dump-trace"].getString() != "")
01844            debugger.dumpTrace(scopeLevel()));
01845 }
01846 
01847 
01848 void VCL::popScope()
01849 {
01850   if(d_osdump) {
01851     d_osdump << newExpr(d_em, POP_SCOPE) << endl;
01852   }
01853   if (scopeLevel() == 1) {
01854     cout << "Cannot POP from scope level 1" << endl;
01855   }
01856   else d_cm->pop();
01857   IF_DEBUG(if((*d_flags)["dump-trace"].getString() != "")
01858            debugger.dumpTrace(scopeLevel()));
01859 }
01860 
01861 
01862 void VCL::poptoScope(int toLevel)
01863 {
01864   if(d_osdump) {
01865     d_osdump << newExpr(d_em, POPTO_SCOPE, ratExpr(toLevel, 1)) << endl;
01866   }
01867   if (toLevel < 1) {
01868     d_cm->popto(0);
01869     d_cm->push();
01870   }
01871   else d_cm->popto(toLevel);
01872   IF_DEBUG(if((*d_flags)["dump-trace"].getString() != "")
01873            debugger.dumpTrace(scopeLevel()));
01874 }
01875 
01876 
01877 Context* VCL::getCurrentContext()
01878 {
01879   return d_cm->getCurrentContext();
01880 }
01881 
01882 
01883 TheoryCore* VCL::theoryCore()
01884 {
01885   return d_theoryCore;
01886 }
01887 
01888 void VCL::loadFile(const std::string& fileName, InputLanguage lang,
01889                    bool interactive) {
01890   Parser parser(this, lang, interactive, fileName);
01891   VCCmd cmd(this, &parser);
01892   cmd.processCommands();
01893 }
01894 
01895 
01896 void VCL::loadFile(std::istream& is, InputLanguage lang,
01897                    bool interactive) {
01898   Parser parser(this, lang, is, interactive);
01899   VCCmd cmd(this, &parser);
01900   cmd.processCommands();
01901 }
01902 
01903 
01904 bool VCL::isLiteral(const Expr& e) {
01905   return d_theoryCore->isLiteral(e);
01906 }
01907 
01908 
01909 Expr CNF::exprVar(const Expr& e)
01910 {
01911   TRACE("mycnf", "CNF::exprVar(", e, ") {");
01912   if (e.arity() == 0 || d_core->isLiteral(e) || d_core->isAtomic(e)) {
01913     TRACE("mycnf", "CNF::exprVar[literal] => ", e, " }");
01914     return e;
01915   }
01916 
01917   if (e.isNot()) {
01918     Expr res(!exprVar(e[0]));
01919     TRACE("mycnf", "CNF::exprVar[NOT] => ", res, " }");
01920     return res;
01921   }
01922 
01923   map<Expr,Expr>::iterator it = d_exprVars.find(e);
01924   if (it != d_exprVars.end()) {
01925     // IF_DEBUG(debugger.counter("Jake CNF cache hits")++);
01926     d_vcl->getStatistics().counter("Jake CNF cache hits")++;
01927     TRACE("mycnf", "CNF::exprVar[cache] => ", it->second, " }");
01928     return it->second;
01929   }
01930   else
01931   {
01932     string name("_e_");
01933     name += int2string(d_nextNum++);
01934     // IF_DEBUG(debugger.counter("Jake new vars") = d_nextNum);
01935     d_vcl->getStatistics().counter("Jake new vars")++;
01936     Expr ev = d_vcl->varExpr(name, d_core->getType(e));
01937     //cerr << name << " : " << d_core->getType(e) << ";" << endl;
01938     d_exprVars[e] = ev;
01939     d_q.push_back(e);
01940     TRACE("mycnf", "CNF::exprVar[new] => ", ev, " }");
01941     return ev;
01942   }
01943 }
01944 
01945 TheoryCore * CNF::theoryCore() { 
01946   return d_vcl->theoryCore();
01947 }
01948 
01949 Expr CNF::cnf(const Expr& e)
01950 {
01951   TRACE("mycnf", "CNF::cnf(", e, ") {");
01952  vector<Expr> clauses;
01953  // clauses.push_back(exprVar(theoryCore()->simplifyThm(e).getRHS()));
01954  clauses.push_back(exprVar(e));
01955 
01956   TRACE("cnf-clauses", "cnf call", e, "");
01957   while (d_q.size() > 0)
01958   {
01959     Expr e = d_q.front();
01960     d_q.pop_front();
01961 
01962     if (e.arity() == 0 || d_core->isLiteral(e) || d_core->isAtomic(e))
01963       continue;
01964 
01965     bool isBool = (d_core->getType(e) == d_vcl->boolType());
01966     for (int i=0; i < e.arity() && isBool; i++)
01967       isBool = (d_core->getType(e[i]) == d_vcl->boolType());
01968 
01969     if (isBool)
01970     {
01971       if (e.isAnd())
01972       {
01973         if (d_vcl->getFlags()["circuit"].getBool() && e.arity() == 2)
01974         {
01975           clauses.push_back(newExpr(d_vcl->getEM(),
01976                                     AND_R,
01977                                     exprVar(e),
01978                                     exprVar(e[0]),
01979                                     exprVar(e[1])));
01980         }
01981 
01982         else
01983         {
01984           //   (e <=> (a AND b AND c)) <=>
01985           //   ((NOT e OR a) AND (NOT e OR b) AND (NOT e OR c) AND
01986           //    (e OR NOT a OR NOT b OR NOT c))
01987 
01988           Expr ev = exprVar(e);
01989           vector<Expr> v;
01990           v.push_back(ev);
01991           for (int i=0; i < e.arity(); i++)
01992           {
01993             Expr evi = exprVar(e[i]);
01994             clauses.push_back(ev.negate() || evi);
01995             v.push_back(evi.negate());
01996           }
01997           clauses.push_back(d_vcl->orExpr(v));
01998         }
01999       }
02000 
02001       else if (e.isOr())
02002       {
02003         if (d_vcl->getFlags()["circuit"].getBool() && e.arity() == 2)
02004         {
02005           clauses.push_back(newExpr(d_vcl->getEM(),
02006                                     AND_R,
02007                                     exprVar(e).negate(),
02008                                     exprVar(e[0]).negate(),
02009                                     exprVar(e[1]).negate()));
02010         }
02011 
02012         else
02013         {
02014           //   (e <=> (a OR b OR c)) <=>
02015           //   ((e OR NOT a) AND (e OR NOT b) AND (e OR NOT c) AND
02016           //    (NOT e OR a OR b OR c))
02017 
02018           Expr ev = exprVar(e);
02019           vector<Expr> v;
02020           v.push_back(ev.negate());
02021           for (int i=0; i < e.arity(); i++)
02022           {
02023             Expr evi = exprVar(e[i]);
02024             clauses.push_back(ev || evi.negate());
02025             v.push_back(evi);
02026           }
02027           clauses.push_back(d_vcl->orExpr(v));
02028         }
02029       }
02030 
02031       else if (e.isITE())
02032       {
02033         Expr ev = exprVar(e);
02034         Expr ev0 = exprVar(e[0]);
02035         Expr ev1 = exprVar(e[1]);
02036         Expr ev2 = exprVar(e[2]);
02037 
02038         if (d_vcl->getFlags()["circuit"].getBool())
02039         {
02040           vector<Expr> v;
02041           v.push_back(ev);
02042           v.push_back(ev0);
02043           v.push_back(ev1);
02044           v.push_back(ev2);
02045           clauses.push_back(newExpr(d_vcl->getEM(), ITE_R, v));
02046         }
02047 
02048         else
02049         {
02050           //   (e <=> IF a THEN b ELSE c ENDIF) <=>
02051           //   ((NOT e OR NOT a OR b) AND
02052           //    (NOT e OR a OR c) AND
02053           //    (e OR NOT a OR NOT b) AND
02054           //    (e OR a OR NOT c))
02055 
02056           clauses.push_back(ev.negate() || ev0.negate() || ev1);
02057           clauses.push_back(ev.negate() || ev0 || ev2);
02058           clauses.push_back(ev || ev0.negate() || ev1.negate());
02059           clauses.push_back(ev || ev0 || ev2.negate());
02060         }
02061       }
02062 
02063       else if (e.isImpl())
02064       {
02065         Expr ev = exprVar(e);
02066         Expr ev0 = exprVar(e[0]);
02067         Expr ev1 = exprVar(e[1]);
02068 
02069         if (d_vcl->getFlags()["circuit"].getBool())
02070         {
02071           clauses.push_back(newExpr(d_vcl->getEM(), AND_R,
02072                                     ev.negate(), ev0, ev1.negate()));
02073         }
02074 
02075         else
02076         {
02077           //   (e <=> (a => b)) <=>
02078           //   ((NOT e OR NOT a OR b) AND (e OR a) AND (e OR NOT b))
02079 
02080           clauses.push_back(ev.negate() || ev0.negate() || ev1);
02081           clauses.push_back(ev || ev0);
02082           clauses.push_back(ev || ev1.negate());
02083         }
02084       }
02085 
02086       else if (e.isIff())
02087       {
02088         Expr ev = exprVar(e);
02089         Expr ev0 = exprVar(e[0]);
02090         Expr ev1 = exprVar(e[1]);
02091 
02092         if (d_vcl->getFlags()["circuit"].getBool())
02093         {
02094           clauses.push_back(newExpr(d_vcl->getEM(), IFF_R, ev, ev0, ev1));
02095         }
02096 
02097         else
02098         {
02099           //   (e <=> (a <=> b)) <=>
02100           //   ((NOT e OR NOT a OR b) AND (NOT e OR a OR NOT b) AND
02101           //    (e OR a OR b) AND (e OR NOT a OR NOT b))
02102 
02103           clauses.push_back(ev.negate() || ev0.negate() || ev1);
02104           clauses.push_back(ev.negate() || ev0 || ev1.negate());
02105           clauses.push_back(ev || ev0 || ev1);
02106           clauses.push_back(ev || ev0.negate() || ev1.negate());
02107         }
02108       }
02109 
02110       else
02111       {
02112         cerr << e << endl;
02113         DebugAssert(false, "unhandled boolean");
02114       }
02115     }
02116 
02117     else
02118     {
02119       if (e.isITE())
02120       {
02121         //   (e = (IF a THEN b ELSE c ENDIF)) <=>
02122         //   ((a => (e = b)) AND (NOT a => (e = c))) <=>
02123         //   ((NOT a OR (e = b)) AND (a OR (e = c)))
02124 
02125         Expr ev = exprVar(e);
02126         Expr ev0 = exprVar(e[0]);
02127         Expr ev1 = exprVar(e[1]);
02128         Expr ev2 = exprVar(e[2]);
02129 
02130         clauses.push_back(ev0.negate() || d_vcl->eqExpr(ev, ev1));
02131         clauses.push_back(ev0 || d_vcl->eqExpr(ev, ev2));
02132       }
02133 
02134       else
02135       {
02136         if (!d_core->isAtomic(e))
02137         {
02138           Expr ev = exprVar(e);
02139           vector<Expr> newKids;
02140           for (int i=0; i < e.arity(); i++)
02141           {
02142             Expr evi = exprVar(e[i]);
02143             newKids.push_back(evi);
02144           }
02145 
02146           Expr res = newExpr(d_vcl->getEM(), getOp(e), newKids);
02147           if (d_core->getType(e) == d_vcl->boolType())
02148           {
02149             clauses.push_back(ev || res.negate());
02150             clauses.push_back(ev.negate() || res);
02151           }
02152           else
02153             clauses.push_back(d_vcl->eqExpr(ev, res));
02154         }
02155       }
02156     }
02157     TRACE("mycnf", "Jake Clauses", andExpr(clauses), "}");
02158   }
02159 
02160   //clauses.push_back(e);
02161 
02162   // Expr ee = theoryCore()->simplifyThm(d_vcl->andExpr(clauses)).getRHS();
02163   Expr ee = d_vcl->andExpr(clauses);
02164 //   for(Expr::iterator i = ee.begin(), iend=ee.end(); i!=iend;++i)
02165 //     TRACE("cnf-clauses", "Jake Clauses", *i, "");
02166   TRACE("cnf-clauses", "Unsimplified clauses: ", d_vcl->andExpr(clauses), "");
02167   TRACE("cnf-clauses", "Jake Clauses", ee, "");
02168   TRACE("mycnf", "CNF::cnf => ", ee, " }");
02169   return ee;
02170 }

Generated on Fri May 20 13:14:01 2005 for CVC Lite by  doxygen 1.3.9.1