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

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