CVC3
|
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 * License to use, copy, modify, sell and/or distribute this software 00011 * and its documentation for any purpose is hereby granted without 00012 * royalty, subject to the terms and conditions defined in the \ref 00013 * LICENSE file provided with this distribution. 00014 * 00015 * <hr> 00016 * 00017 */ 00018 /*****************************************************************************/ 00019 00020 00021 #include <fstream> 00022 #include "os.h" 00023 #include "vcl.h" 00024 #include "parser.h" 00025 #include "vc_cmd.h" 00026 #include "search_simple.h" 00027 #include "search_fast.h" 00028 #include "search_sat.h" 00029 #include "theory_core.h" 00030 #include "theory_uf.h" 00031 #include "theory_arith_old.h" 00032 #include "theory_arith_new.h" 00033 #include "theory_arith3.h" 00034 #include "theory_bitvector.h" 00035 #include "theory_array.h" 00036 #include "theory_quant.h" 00037 #include "theory_records.h" 00038 #include "theory_simulate.h" 00039 #include "theory_datatype.h" 00040 #include "theory_datatype_lazy.h" 00041 #include "translator.h" 00042 #include "typecheck_exception.h" 00043 #include "eval_exception.h" 00044 #include "expr_transform.h" 00045 #include "theorem_manager.h" 00046 #include "assumptions.h" 00047 #include "parser_exception.h" 00048 00049 00050 using namespace std; 00051 using namespace CVC3; 00052 00053 //namespace CVC3{ 00054 // VCL* myvcl; 00055 //} 00056 00057 /////////////////////////////////////////////////////////////////////////////// 00058 // Static ValidityChecker methods 00059 /////////////////////////////////////////////////////////////////////////////// 00060 00061 00062 00063 ValidityChecker* ValidityChecker::create(const CLFlags& flags) 00064 { 00065 return new VCL(flags); 00066 } 00067 00068 00069 CLFlags ValidityChecker::createFlags() { 00070 CLFlags flags; 00071 // We expect the user to type cvc3 -h to get help, which will set 00072 // the "help" flag to false; that's why it's initially true. 00073 00074 // Overall system control flags 00075 flags.addFlag("timeout", CLFlag(0, "Kill cvc3 process after given number of seconds (0==no limit)")); 00076 flags.addFlag("stimeout", CLFlag(0, "Set time resource limit in tenths of seconds for a query(0==no limit)")); 00077 flags.addFlag("resource", CLFlag(0, "Set finite resource limit (0==no limit)")); 00078 flags.addFlag("mm", CLFlag("chunks", "Memory manager (chunks, malloc)")); 00079 00080 // Information printing flags 00081 flags.addFlag("help",CLFlag(true, "print usage information and exit")); 00082 flags.addFlag("unsupported",CLFlag(true, "print usage for old/unsupported/experimental options")); 00083 flags.addFlag("version",CLFlag(true, "print version information and exit")); 00084 flags.addFlag("interactive", CLFlag(false, "Interactive mode")); 00085 flags.addFlag("stats", CLFlag(false, "Print run-time statistics")); 00086 flags.addFlag("seed", CLFlag(1, "Set the seed for random sequence")); 00087 flags.addFlag("printResults", CLFlag(true, "Print results of interactive commands.")); 00088 flags.addFlag("dump-log", CLFlag("", "Dump API call log in CVC3 input " 00089 "format to given file " 00090 "(off when file name is \"\")")); 00091 flags.addFlag("parse-only", CLFlag(false,"Parse the input, then exit.")); 00092 00093 //Translation related flags 00094 flags.addFlag("expResult", CLFlag("", "For smtlib translation. Give the expected result", false)); 00095 flags.addFlag("category", CLFlag("unknown", "For smtlib translation. Give the category", false)); 00096 flags.addFlag("translate", CLFlag(false, "Produce a complete translation from " 00097 "the input language to output language. ")); 00098 flags.addFlag("real2int", CLFlag(false, "When translating, convert reals to integers.", false)); 00099 flags.addFlag("convertArith", CLFlag(false, "When translating, try to rewrite arith terms into smt-lib subset", false)); 00100 flags.addFlag("convert2diff", CLFlag("", "When translating, try to force into difference logic. Legal values are int and real.", false)); 00101 flags.addFlag("iteLiftArith", CLFlag(false, "For translation. If true, ite's are lifted out of arith exprs.", false)); 00102 flags.addFlag("convertArray", CLFlag(false, "For translation. If true, arrays are converted to uninterpreted functions if possible.", false)); 00103 flags.addFlag("combineAssump", CLFlag(false, "For translation. If true, assumptions are combined into the query.", false)); 00104 flags.addFlag("convert2array", CLFlag(false, "For translation. If true, try to convert to array-only theory", false)); 00105 flags.addFlag("convertToBV",CLFlag(0, "For translation. Set to nonzero to convert ints to bv's of that length", false)); 00106 flags.addFlag("convert-eq-iff",CLFlag(false, "Convert equality on Boolean expressions to iff.", false)); 00107 flags.addFlag("preSimplify",CLFlag(false, "Simplify each assertion or query before translating it", false)); 00108 flags.addFlag("dump-tcc", CLFlag(false, "Compute and dump TCC only")); 00109 flags.addFlag("trans-skip-pp", CLFlag(false, "Skip preprocess step in translation module", false)); 00110 flags.addFlag("trans-skip-difficulty", CLFlag(false, "Leave out difficulty attribute during translation to SMT v2.0", false)); 00111 flags.addFlag("promote", CLFlag(true, "Promote undefined logic combinations to defined logic combinations during translation to SMT", false)); 00112 00113 // Parser related flags 00114 flags.addFlag("old-func-syntax",CLFlag(false, "Enable parsing of old-style function syntax", false)); 00115 00116 // Pretty-printing related flags 00117 flags.addFlag("dagify-exprs", 00118 CLFlag(true, "Print expressions with sharing as DAGs")); 00119 flags.addFlag("lang", CLFlag("presentation", "Input language " 00120 "(presentation, smt, smt2, internal)")); 00121 flags.addFlag("output-lang", CLFlag("", "Output language " 00122 "(presentation, smtlib, simplify, internal, lisp, tptp, spass)")); 00123 flags.addFlag("indent", CLFlag(false, "Print expressions with indentation")); 00124 flags.addFlag("width", CLFlag(80, "Suggested line width for printing")); 00125 flags.addFlag("print-depth", CLFlag(-1, "Max. depth to print expressions ")); 00126 flags.addFlag("print-assump", CLFlag(false, "Print assumptions in Theorems ")); 00127 00128 // Search Engine (SAT) related flags 00129 flags.addFlag("sat",CLFlag("minisat", "choose a SAT solver to use " 00130 "(sat, minisat)")); 00131 flags.addFlag("de",CLFlag("dfs", "choose a decision engine to use " 00132 "(dfs, sat)")); 00133 00134 // Proofs and Assumptions 00135 flags.addFlag("proofs", CLFlag(false, "Produce proofs")); 00136 flags.addFlag("check-proofs", 00137 CLFlag(IF_DEBUG(true ||) false, "Check proofs on-the-fly")); 00138 flags.addFlag("minimizeClauses", CLFlag(false, "Use brute-force minimization of clauses", false)); 00139 flags.addFlag("dynack", CLFlag(false, "Use dynamic Ackermannization", false)); 00140 flags.addFlag("smart-clauses", CLFlag(true, "Learn multiple clauses per conflict")); 00141 00142 00143 // Core framework switches 00144 flags.addFlag("tcc", CLFlag(false, "Check TCCs for each ASSERT and QUERY")); 00145 flags.addFlag("cnf", CLFlag(true, "Convert top-level Boolean formulas to CNF", false)); 00146 flags.addFlag("ignore-cnf-vars", CLFlag(false, "Do not split on aux. CNF vars (with +cnf)", false)); 00147 flags.addFlag("orig-formula", CLFlag(false, "Preserve the original formula with +cnf (for splitter heuristics)", false)); 00148 flags.addFlag("liftITE", CLFlag(false, "Eagerly lift all ITE exprs")); 00149 flags.addFlag("iflift", CLFlag(false, "Translate if-then-else terms to CNF (with +cnf)", false)); 00150 flags.addFlag("circuit", CLFlag(false, "With +cnf, use circuit propagation", false)); 00151 flags.addFlag("un-ite-ify", CLFlag(false, "Unconvert ITE expressions", false)); 00152 flags.addFlag("ite-cond-simp", 00153 CLFlag(false, "Replace ITE condition by TRUE/FALSE in subexprs", false)); 00154 flags.addFlag("preprocess", CLFlag(true, "Preprocess queries")); 00155 flags.addFlag("pp-pushneg", CLFlag(false, "Push negation in preprocessor")); 00156 flags.addFlag("pp-bryant", CLFlag(false, "Enable Bryant algorithm for UF", false)); 00157 flags.addFlag("pp-budget", CLFlag(0, "Budget for new preprocessing step", false)); 00158 flags.addFlag("pp-care", CLFlag(true, "Enable care-set preprocessing step", false)); 00159 flags.addFlag("simp-and", CLFlag(false, "Rewrite x&y to x&y[x/true]", false)); 00160 flags.addFlag("simp-or", CLFlag(false, "Rewrite x|y to x|y[x/false]", false)); 00161 flags.addFlag("pp-batch", CLFlag(false, "Ignore assumptions until query, then process all at once")); 00162 flags.addFlag("no-save-model", CLFlag(false, "Do NOT save model assumptions in context after invalid / sat query")); 00163 flags.addFlag("internal::userSetNoSaveModel", CLFlag(false, "set if user gave +no-save-model or -no-save-model explicitly", false)); 00164 00165 // Negate the query when translate into tptp 00166 flags.addFlag("negate-query", CLFlag(true, "Negate the query when translate into TPTP format"));; 00167 00168 // Concrete model generation (counterexamples) flags 00169 flags.addFlag("counterexample", CLFlag(false, "Dump counterexample if formula is invalid or satisfiable")); 00170 flags.addFlag("model", CLFlag(false, "Dump model if formula is invalid or satisfiable")); 00171 flags.addFlag("unknown-check-model", CLFlag(false, "Try to generate model if formula is unknown")); 00172 flags.addFlag("applications", CLFlag(true, "Add relevant function applications and array accesses to the concrete countermodel")); 00173 // Debugging flags (only for the debug build) 00174 // #ifdef _CVC3_DEBUG_MODE 00175 vector<pair<string,bool> > sv; 00176 flags.addFlag("trace", CLFlag(sv, "Tracing. Multiple flags add up.")); 00177 flags.addFlag("dump-trace", CLFlag("", "Dump debugging trace to " 00178 "given file (off when file name is \"\")")); 00179 // #endif 00180 // DP-specific flags 00181 00182 // Arithmetic 00183 flags.addFlag("arith-new",CLFlag(false, "Use new arithmetic dp", false)); 00184 flags.addFlag("arith3",CLFlag(false, "Use old arithmetic dp that works well with combined theories", false)); 00185 flags.addFlag("var-order", 00186 CLFlag(false, "Use simple variable order in arith", false)); 00187 flags.addFlag("ineq-delay", CLFlag(0, "Accumulate this many inequalities before processing (-1 for don't process until necessary)")); 00188 00189 flags.addFlag("nonlinear-sign-split", CLFlag(true, "Whether to split on the signs of nontrivial nonlinear terms")); 00190 00191 flags.addFlag("grayshadow-threshold", CLFlag(-1, "Ignore gray shadows bigger than this (makes solver incomplete)")); 00192 flags.addFlag("pathlength-threshold", CLFlag(-1, "Ignore gray shadows bigger than this (makes solver incomplete)")); 00193 00194 // Arrays 00195 flags.addFlag("liftReadIte", CLFlag(true, "Lift read of ite")); 00196 00197 //for LFSC stuff, disable Tseitin CNF conversion, by Yeting 00198 flags.addFlag("cnf-formula", CLFlag(false, "The input must be in CNF. This option automatically enables '-de sat' and disable preprocess")); 00199 00200 //for LFSC print out, by Yeting 00201 //flags.addFlag("lfsc", CLFlag(false, "the input is already in CNF. This option automatically enables -de sat and disable -preprocess")); 00202 00203 // for LFSC print, allows different modes by Liana 00204 flags.addFlag("lfsc-mode", 00205 CLFlag(0, "lfsc mode 0: off, 1:normal, 2:cvc3-mimic etc.")); 00206 00207 00208 // Quantifiers 00209 flags.addFlag("max-quant-inst", CLFlag(200, "The maximum number of" 00210 " naive instantiations")); 00211 00212 flags.addFlag("quant-new", 00213 CLFlag(true, "If this option is false, only naive instantiation is called")); 00214 00215 flags.addFlag("quant-lazy", CLFlag(false, "Instantiate lazily", false)); 00216 00217 flags.addFlag("quant-sem-match", 00218 CLFlag(false, "Attempt to match semantically when instantiating", false)); 00219 00220 // flags.addFlag("quant-const-match", 00221 // CLFlag(true, "When matching semantically, only match with constants", false)); 00222 00223 flags.addFlag("quant-complete-inst", 00224 CLFlag(false, "Try complete instantiation heuristic. +pp-batch will be automatically enabled")); 00225 00226 flags.addFlag("quant-max-IL", 00227 CLFlag(100, "The maximum Instantiation Level allowed")); 00228 00229 flags.addFlag("quant-inst-lcache", 00230 CLFlag(true, "Cache instantiations")); 00231 00232 flags.addFlag("quant-inst-gcache", 00233 CLFlag(false, "Cache instantiations", false)); 00234 00235 flags.addFlag("quant-inst-tcache", 00236 CLFlag(false, "Cache instantiations", false)); 00237 00238 00239 flags.addFlag("quant-inst-true", 00240 CLFlag(true, "Ignore true instantiations")); 00241 00242 flags.addFlag("quant-pullvar", 00243 CLFlag(false, "Pull out vars", false)); 00244 00245 flags.addFlag("quant-score", 00246 CLFlag(true, "Use instantiation level")); 00247 00248 flags.addFlag("quant-polarity", 00249 CLFlag(false, "Use polarity ", false)); 00250 00251 flags.addFlag("quant-eqnew", 00252 CLFlag(true, "Use new equality matching")); 00253 00254 flags.addFlag("quant-max-score", 00255 CLFlag(0, "Maximum initial dynamic score")); 00256 00257 flags.addFlag("quant-trans3", 00258 CLFlag(true, "Use trans heuristic")); 00259 00260 flags.addFlag("quant-trans2", 00261 CLFlag(true, "Use trans2 heuristic")); 00262 00263 flags.addFlag("quant-naive-num", 00264 CLFlag(1000, "Maximum number to call naive instantiation")); 00265 00266 flags.addFlag("quant-naive-inst", 00267 CLFlag(true, "Use naive instantiation")); 00268 00269 flags.addFlag("quant-man-trig", 00270 CLFlag(true, "Use manual triggers")); 00271 00272 flags.addFlag("quant-gfact", 00273 CLFlag(false, "Send facts to core directly", false)); 00274 00275 flags.addFlag("quant-glimit", 00276 CLFlag(1000, "Limit for gfacts", false)); 00277 00278 flags.addFlag("print-var-type", //by yeting, as requested by Sascha Boehme for proofs 00279 CLFlag(false, "Print types for bound variables")); 00280 00281 //Bitvectors 00282 flags.addFlag("bv32-flag", 00283 CLFlag(false, "assume that all bitvectors are 32bits with no overflow", false)); 00284 00285 // Uninterpreted Functions 00286 flags.addFlag("trans-closure", 00287 CLFlag(false,"enables transitive closure of binary relations", false)); 00288 00289 // Datatypes 00290 flags.addFlag("dt-smartsplits", 00291 CLFlag(true, "enables smart splitting in datatype theory", false)); 00292 flags.addFlag("dt-lazy", 00293 CLFlag(false, "lazy splitting on datatypes", false)); 00294 00295 00296 return flags; 00297 } 00298 00299 00300 ValidityChecker* ValidityChecker::create() 00301 { 00302 return new VCL(createFlags()); 00303 } 00304 00305 00306 /////////////////////////////////////////////////////////////////////////////// 00307 // VCL private methods 00308 /////////////////////////////////////////////////////////////////////////////// 00309 00310 00311 Theorem3 VCL::deriveClosure(const Theorem3& thm) { 00312 vector<Expr> assump; 00313 set<UserAssertion> assumpSet; 00314 // Compute the vector of assumptions for thm, and iteratively move 00315 // the assumptions to the RHS until done. Each closure step may 00316 // introduce new assumptions from the proofs of TCCs, so those need 00317 // to be dealt with in the same way, until no assumptions remain. 00318 Theorem3 res = thm; 00319 vector<Theorem> tccs; 00320 while(true) { 00321 { 00322 const Assumptions& a(res.getAssumptionsRef()); 00323 if (a.empty()) break; 00324 assump.clear(); 00325 assumpSet.clear(); 00326 Assumptions::iterator i=a.begin(), iend=a.end(); 00327 if(i!=iend) i->clearAllFlags(); 00328 // Collect the assumptions of 'res' *without* TCCs 00329 for(; i!=iend; ++i) 00330 getAssumptionsRec(*i, assumpSet, false); 00331 00332 // Build the vectors of assumptions and TCCs 00333 if(getFlags()["tcc"].getBool()) { 00334 tccs.clear(); 00335 for(set<UserAssertion>::iterator i=assumpSet.begin(), 00336 iend=assumpSet.end(); i!=iend; ++i) { 00337 assump.push_back(i->thm().getExpr()); 00338 tccs.push_back(i->tcc()); 00339 } 00340 } 00341 } 00342 // Derive the closure 00343 res = d_se->getCommonRules()->implIntro3(res, assump, tccs); 00344 } 00345 return res; 00346 } 00347 00348 00349 //! Recursive assumption graph traversal to find user assumptions 00350 /*! 00351 * If an assumption has a TCC, traverse the proof of TCC and add its 00352 * assumptions to the set recursively. 00353 */ 00354 void VCL::getAssumptionsRec(const Theorem& thm, 00355 set<UserAssertion>& assumptions, 00356 bool addTCCs) { 00357 if(thm.isNull() || thm.isRefl() || thm.isFlagged()) return; 00358 thm.setFlag(); 00359 if(thm.isAssump()) { 00360 if(d_userAssertions->count(thm.getExpr())>0) { 00361 const UserAssertion& a = (*d_userAssertions)[thm.getExpr()]; 00362 assumptions.insert(a); 00363 if(addTCCs) { 00364 DebugAssert(!a.tcc().isNull(), "getAssumptionsRec(a=" 00365 +a.thm().toString()+", thm = "+thm.toString()+")"); 00366 getAssumptionsRec(a.tcc(), assumptions, true); 00367 } 00368 } else { // it's a splitter 00369 UserAssertion a(thm, Theorem(), d_nextIdx++); 00370 assumptions.insert(a); 00371 } 00372 } 00373 else { 00374 const Assumptions& a(thm.getAssumptionsRef()); 00375 for(Assumptions::iterator i=a.begin(), iend=a.end(); i!=iend; ++i) 00376 getAssumptionsRec(*i, assumptions, addTCCs); 00377 } 00378 } 00379 00380 00381 void VCL::getAssumptions(const Assumptions& a, vector<Expr>& assumptions) 00382 { 00383 set<UserAssertion> assumpSet; 00384 if(a.empty()) return; 00385 Assumptions::iterator i=a.begin(), iend=a.end(); 00386 if(i!=iend) i->clearAllFlags(); 00387 for(; i!=iend; ++i) 00388 getAssumptionsRec(*i, assumpSet, getFlags()["tcc"].getBool()); 00389 // Order assumptions by their creation time 00390 for(set<UserAssertion>::iterator i=assumpSet.begin(), iend=assumpSet.end(); 00391 i!=iend; ++i) 00392 assumptions.push_back(i->thm().getExpr()); 00393 } 00394 00395 00396 IF_DEBUG( 00397 void VCL::dumpTrace(int scope) { 00398 vector<StrPair> fields; 00399 fields.push_back(strPair("scope", int2string(scope))); 00400 debugger.dumpTrace("scope", fields); 00401 } 00402 ) 00403 00404 00405 /////////////////////////////////////////////////////////////////////////////// 00406 // Public VCL methods 00407 /////////////////////////////////////////////////////////////////////////////// 00408 00409 00410 VCL::VCL(const CLFlags& flags) 00411 : d_flags(new CLFlags(flags)) 00412 { 00413 // Set the dependent flags so that they are consistent 00414 00415 if ((*d_flags)["dump-tcc"].getBool()) { 00416 d_flags->setFlag("translate", true); 00417 d_flags->setFlag("pp-batch", true); 00418 d_flags->setFlag("tcc", true); 00419 } 00420 00421 if ((*d_flags)["translate"].getBool()) { 00422 d_flags->setFlag("printResults", false); 00423 } 00424 00425 if ((*d_flags)["pp-bryant"].getBool()) { 00426 d_flags->setFlag("pp-batch", true); 00427 } 00428 00429 //added by Yeting 00430 if ((*d_flags)["quant-complete-inst"].getBool() && !(*d_flags)["translate"].getBool()) { 00431 d_flags->setFlag("pp-batch", true); 00432 } 00433 00434 //added by Yeting 00435 if ((*d_flags)["cnf-formula"].getBool()) { 00436 d_flags->setFlag("de", "sat"); 00437 d_flags->setFlag("preprocess", false); 00438 } 00439 00440 00441 IF_DEBUG( // Initialize the global debugger 00442 CVC3::debugger.init(&((*d_flags)["trace"].getStrVec()), 00443 &((*d_flags)["dump-trace"].getString())); 00444 ) 00445 init(); 00446 } 00447 00448 00449 void VCL::init() 00450 { 00451 d_nextIdx = 0; 00452 00453 d_statistics = new Statistics(); 00454 00455 d_cm = new ContextManager(); 00456 00457 // Initialize the database of user assertions. It has to be 00458 // initialized after d_cm. 00459 d_userAssertions = new(true) CDMap<Expr,UserAssertion>(getCurrentContext()); 00460 d_batchedAssertions = new(true) CDList<Expr>(getCurrentContext()); 00461 d_batchedAssertionsIdx = new(true) CDO<unsigned>(getCurrentContext(), 0); 00462 00463 d_em = new ExprManager(d_cm, *d_flags); 00464 00465 d_tm = new TheoremManager(d_cm, d_em, *d_flags); 00466 d_em->setTM(d_tm); 00467 00468 d_translator = new Translator(d_em, 00469 (*d_flags)["translate"].getBool(), 00470 (*d_flags)["real2int"].getBool(), 00471 (*d_flags)["convertArith"].getBool(), 00472 (*d_flags)["convert2diff"].getString(), 00473 (*d_flags)["iteLiftArith"].getBool(), 00474 (*d_flags)["expResult"].getString(), 00475 (*d_flags)["category"].getString(), 00476 (*d_flags)["convertArray"].getBool(), 00477 (*d_flags)["combineAssump"].getBool(), 00478 (*d_flags)["convertToBV"].getInt()); 00479 00480 d_dump = d_translator->start((*d_flags)["dump-log"].getString()); 00481 00482 d_theoryCore = new TheoryCore(d_cm, d_em, d_tm, d_translator, *d_flags, *d_statistics); 00483 00484 DebugAssert(d_theories.size() == 0, "Expected empty theories array"); 00485 d_theories.push_back(d_theoryCore); 00486 00487 // Fast rewriting of literals is done by setting their find to true or false. 00488 falseExpr().setFind(d_theoryCore->reflexivityRule(falseExpr())); 00489 trueExpr().setFind(d_theoryCore->reflexivityRule(trueExpr())); 00490 00491 d_theories.push_back(d_theoryUF = new TheoryUF(d_theoryCore)); 00492 00493 if ((*d_flags)["arith-new"].getBool()) { 00494 d_theories.push_back(d_theoryArith = new TheoryArithNew(d_theoryCore)); 00495 } 00496 else if ((*d_flags)["arith3"].getBool()) { 00497 d_theories.push_back(d_theoryArith = new TheoryArith3(d_theoryCore)); 00498 } 00499 else { 00500 d_theories.push_back(d_theoryArith = new TheoryArithOld(d_theoryCore)); 00501 } 00502 d_theoryCore->getExprTrans()->setTheoryArith(d_theoryArith); 00503 d_theories.push_back(d_theoryArray = new TheoryArray(d_theoryCore)); 00504 d_theories.push_back(d_theoryRecords = new TheoryRecords(d_theoryCore)); 00505 d_theories.push_back(d_theorySimulate = new TheorySimulate(d_theoryCore)); 00506 d_theories.push_back(d_theoryBitvector = new TheoryBitvector(d_theoryCore)); 00507 if ((*d_flags)["dt-lazy"].getBool()) { 00508 d_theories.push_back(d_theoryDatatype = new TheoryDatatypeLazy(d_theoryCore)); 00509 } 00510 else { 00511 d_theories.push_back(d_theoryDatatype = new TheoryDatatype(d_theoryCore)); 00512 } 00513 d_theories.push_back(d_theoryQuant = new TheoryQuant(d_theoryCore)); 00514 00515 d_translator->setTheoryCore(d_theoryCore); 00516 d_translator->setTheoryUF(d_theoryUF); 00517 d_translator->setTheoryArith(d_theoryArith); 00518 d_translator->setTheoryArray(d_theoryArray); 00519 d_translator->setTheoryQuant(d_theoryQuant); 00520 d_translator->setTheoryRecords(d_theoryRecords); 00521 d_translator->setTheorySimulate(d_theorySimulate); 00522 d_translator->setTheoryBitvector(d_theoryBitvector); 00523 d_translator->setTheoryDatatype(d_theoryDatatype); 00524 00525 // Must be created after TheoryCore, since it needs it. 00526 // When we have more than one search engine, select one to create 00527 // based on flags 00528 const string& satEngine = (*d_flags)["sat"].getString(); 00529 if (satEngine == "simple") 00530 d_se = new SearchSimple(d_theoryCore); 00531 else if (satEngine == "fast") 00532 d_se = new SearchEngineFast(d_theoryCore); 00533 else if (satEngine == "sat" || satEngine == "minisat") 00534 d_se = new SearchSat(d_theoryCore, satEngine); 00535 else 00536 throw CLException("Unrecognized SAT solver name: " 00537 +(*d_flags)["sat"].getString()); 00538 00539 // Initial scope level should be 1 00540 d_cm->push(); 00541 00542 d_stackLevel = new(true) CDO<int>(d_cm->getCurrentContext(), 0); 00543 00544 d_theoryCore->setResourceLimit((unsigned)((*d_flags)["resource"].getInt())); 00545 d_theoryCore->setTimeLimit((unsigned)((*d_flags)["stimeout"].getInt())); 00546 00547 // myvcl = this; 00548 } 00549 00550 00551 void VCL::destroy() 00552 { 00553 popto(0); 00554 d_cm->popto(0); 00555 delete d_stackLevel; 00556 free(d_stackLevel); 00557 d_translator->finish(); 00558 delete d_translator; 00559 00560 TRACE_MSG("delete", "Deleting SearchEngine {"); 00561 delete d_se; 00562 TRACE_MSG("delete", "Finished deleting SearchEngine }"); 00563 // This map contains expressions and theorems; delete it before 00564 // d_em, d_tm, and d_cm. 00565 TRACE_MSG("delete", "Deleting d_userAssertions {"); 00566 delete d_batchedAssertionsIdx; 00567 free(d_batchedAssertionsIdx); 00568 delete d_batchedAssertions; 00569 free(d_batchedAssertions); 00570 delete d_userAssertions; 00571 free(d_userAssertions); 00572 TRACE_MSG("delete", "Finished deleting d_userAssertions }"); 00573 // and set these to null so their destructors don't blow up 00574 d_lastQuery = Theorem3(); 00575 d_lastQueryTCC = Theorem(); 00576 d_lastClosure = Theorem3(); 00577 // Delete ExprManager BEFORE TheoremManager, since Exprs use Theorems 00578 TRACE_MSG("delete", "Clearing d_em {"); 00579 d_em->clear(); 00580 d_tm->clear(); 00581 TRACE_MSG("delete", "Finished clearing d_em }"); 00582 00583 for(size_t i=d_theories.size(); i!= 0; ) { 00584 --i; 00585 string name(d_theories[i]->getName()); 00586 TRACE("delete", "Deleting Theory[", name, "] {"); 00587 delete d_theories[i]; 00588 TRACE("delete", "Finished deleting Theory[", name, "] }"); 00589 } 00590 d_theories.clear(); 00591 00592 // TheoremManager does not call ~Theorem() destructors, and only 00593 // releases memory. At worst, we'll lose some Assumptions. 00594 TRACE_MSG("delete", "Deleting d_tm {"); 00595 delete d_tm; 00596 TRACE_MSG("delete", "Finished deleting d_tm }"); 00597 00598 TRACE_MSG("delete", "Deleting d_em {"); 00599 delete d_em; 00600 TRACE_MSG("delete", "Finished deleting d_em }"); 00601 00602 TRACE_MSG("delete", "Deleting d_cm {"); 00603 delete d_cm; 00604 TRACE_MSG("delete", "Finished deleting d_cm }"); 00605 delete d_statistics; 00606 TRACE_MSG("delete", "Finished deleting d_statistics }"); 00607 } 00608 00609 00610 VCL::~VCL() 00611 { 00612 destroy(); 00613 TRACE_MSG("delete", "Deleting d_flags [end of ~VCL()]"); 00614 delete d_flags; 00615 // No more TRACE-ing after this point (it needs d_flags) 00616 // Finalize the global debugger, 00617 // otherwise applications with more than one instance of VCL 00618 // may use refer to deallocated flags (e.g. test6 uses 2 VCLs) 00619 IF_DEBUG( CVC3::debugger.finalize(); ) 00620 } 00621 00622 00623 void VCL::reprocessFlags() { 00624 if (d_se->getName() != (*d_flags)["sat"].getString()) { 00625 delete d_se; 00626 const string& satEngine = (*d_flags)["sat"].getString(); 00627 if (satEngine == "simple") 00628 d_se = new SearchSimple(d_theoryCore); 00629 else if (satEngine == "fast") 00630 d_se = new SearchEngineFast(d_theoryCore); 00631 else if (satEngine == "sat" || satEngine == "minisat") 00632 d_se = new SearchSat(d_theoryCore, satEngine); 00633 else 00634 throw CLException("Unrecognized SAT solver name: " 00635 +(*d_flags)["sat"].getString()); 00636 } 00637 00638 int arithCur; 00639 if (d_theoryArith->getName() == "ArithmeticOld") arithCur = 1; 00640 else if (d_theoryArith->getName() == "ArithmeticNew") arithCur = 2; 00641 else { 00642 DebugAssert(d_theoryArith->getName() == "Arithmetic3", "unexpected name"); 00643 arithCur = 3; 00644 } 00645 00646 int arithNext; 00647 if ((*d_flags)["arith-new"].getBool()) arithNext = 2; 00648 else if ((*d_flags)["arith3"].getBool()) arithNext = 3; 00649 else arithNext = 1; 00650 00651 if (arithCur != arithNext) { 00652 delete d_theoryArith; 00653 switch (arithNext) { 00654 case 1: 00655 d_theoryArith = new TheoryArithOld(d_theoryCore); 00656 break; 00657 case 2: 00658 d_theoryArith = new TheoryArithNew(d_theoryCore); 00659 break; 00660 case 3: 00661 d_theoryArith = new TheoryArith3(d_theoryCore); 00662 break; 00663 } 00664 d_theories[2] = d_theoryArith; 00665 d_translator->setTheoryArith(d_theoryArith); 00666 } 00667 00668 if ((*d_flags)["dump-tcc"].getBool()) { 00669 d_flags->setFlag("translate", true); 00670 d_flags->setFlag("pp-batch", true); 00671 d_flags->setFlag("tcc", true); 00672 } 00673 00674 if ((*d_flags)["translate"].getBool()) { 00675 d_flags->setFlag("printResults", false); 00676 } 00677 00678 if ((*d_flags)["pp-bryant"].getBool()) { 00679 d_flags->setFlag("pp-batch", true); 00680 } 00681 00682 //added by Yeting 00683 if ((*d_flags)["quant-complete-inst"].getBool() && !(*d_flags)["translate"].getBool()) { 00684 d_flags->setFlag("pp-batch", true); 00685 } 00686 00687 if ((*d_flags)["cnf-formula"].getBool()) { 00688 d_flags->setFlag("de", "sat"); 00689 d_flags->setFlag("preprocess", false); 00690 } 00691 00692 00693 //TODO: handle more flags 00694 } 00695 00696 TheoryCore* VCL::core(){ 00697 return d_theoryCore; 00698 } 00699 00700 Type VCL::boolType(){ 00701 return d_theoryCore->boolType(); 00702 } 00703 00704 00705 Type VCL::realType() 00706 { 00707 return d_theoryArith->realType(); 00708 } 00709 00710 00711 Type VCL::intType() { 00712 return d_theoryArith->intType(); 00713 } 00714 00715 00716 Type VCL::subrangeType(const Expr& l, const Expr& r) { 00717 return d_theoryArith->subrangeType(l, r); 00718 } 00719 00720 00721 Type VCL::subtypeType(const Expr& pred, const Expr& witness) 00722 { 00723 return d_theoryCore->newSubtypeExpr(pred, witness); 00724 } 00725 00726 00727 Type VCL::tupleType(const Type& type0, const Type& type1) 00728 { 00729 vector<Type> types; 00730 types.push_back(type0); 00731 types.push_back(type1); 00732 return d_theoryRecords->tupleType(types); 00733 } 00734 00735 00736 Type VCL::tupleType(const Type& type0, const Type& type1, const Type& type2) 00737 { 00738 vector<Type> types; 00739 types.push_back(type0); 00740 types.push_back(type1); 00741 types.push_back(type2); 00742 return d_theoryRecords->tupleType(types); 00743 } 00744 00745 00746 Type VCL::tupleType(const vector<Type>& types) 00747 { 00748 return d_theoryRecords->tupleType(types); 00749 } 00750 00751 00752 Type VCL::recordType(const string& field, const Type& type) 00753 { 00754 vector<string> fields; 00755 vector<Type> kids; 00756 fields.push_back(field); 00757 kids.push_back(type); 00758 return Type(d_theoryRecords->recordType(fields, kids)); 00759 } 00760 00761 00762 Type VCL::recordType(const string& field0, const Type& type0, 00763 const string& field1, const Type& type1) { 00764 vector<string> fields; 00765 vector<Type> kids; 00766 fields.push_back(field0); 00767 fields.push_back(field1); 00768 kids.push_back(type0); 00769 kids.push_back(type1); 00770 sort2(fields, kids); 00771 return Type(d_theoryRecords->recordType(fields, kids)); 00772 } 00773 00774 00775 Type VCL::recordType(const string& field0, const Type& type0, 00776 const string& field1, const Type& type1, 00777 const string& field2, const Type& type2) 00778 { 00779 vector<string> fields; 00780 vector<Type> kids; 00781 fields.push_back(field0); 00782 fields.push_back(field1); 00783 fields.push_back(field2); 00784 kids.push_back(type0); 00785 kids.push_back(type1); 00786 kids.push_back(type2); 00787 sort2(fields, kids); 00788 return Type(d_theoryRecords->recordType(fields, kids)); 00789 } 00790 00791 00792 Type VCL::recordType(const vector<string>& fields, 00793 const vector<Type>& types) 00794 { 00795 DebugAssert(fields.size() == types.size(), 00796 "VCL::recordType: number of fields is different \n" 00797 "from the number of types"); 00798 // Create copies of the vectors to sort them 00799 vector<string> fs(fields); 00800 vector<Type> ts(types); 00801 sort2(fs, ts); 00802 return Type(d_theoryRecords->recordType(fs, ts)); 00803 } 00804 00805 00806 Type VCL::dataType(const string& name, 00807 const string& constructor, 00808 const vector<string>& selectors, const vector<Expr>& types) 00809 { 00810 vector<string> constructors; 00811 constructors.push_back(constructor); 00812 00813 vector<vector<string> > selectorsVec; 00814 selectorsVec.push_back(selectors); 00815 00816 vector<vector<Expr> > typesVec; 00817 typesVec.push_back(types); 00818 00819 return dataType(name, constructors, selectorsVec, typesVec); 00820 } 00821 00822 00823 Type VCL::dataType(const string& name, 00824 const vector<string>& constructors, 00825 const vector<vector<string> >& selectors, 00826 const vector<vector<Expr> >& types) 00827 { 00828 Expr res = d_theoryDatatype->dataType(name, constructors, selectors, types); 00829 if(d_dump) { 00830 d_translator->dump(res); 00831 } 00832 return Type(res[0]); 00833 } 00834 00835 00836 void VCL::dataType(const vector<string>& names, 00837 const vector<vector<string> >& constructors, 00838 const vector<vector<vector<string> > >& selectors, 00839 const vector<vector<vector<Expr> > >& types, 00840 vector<Type>& returnTypes) 00841 { 00842 Expr res = d_theoryDatatype->dataType(names, constructors, selectors, types); 00843 if(d_dump) { 00844 d_translator->dump(res); 00845 } 00846 for (int i = 0; i < res.arity(); ++i) { 00847 returnTypes.push_back(Type(res[i])); 00848 } 00849 } 00850 00851 00852 Type VCL::arrayType(const Type& typeIndex, const Type& typeData) 00853 { 00854 return ::arrayType(typeIndex, typeData); 00855 } 00856 00857 00858 Type VCL::bitvecType(int n) 00859 { 00860 return d_theoryBitvector->newBitvectorType(n); 00861 } 00862 00863 00864 Type VCL::funType(const Type& typeDom, const Type& typeRan) 00865 { 00866 return typeDom.funType(typeRan); 00867 } 00868 00869 00870 Type VCL::funType(const vector<Type>& typeDom, const Type& typeRan) { 00871 DebugAssert(typeDom.size() >= 1, "VCL::funType: missing domain types"); 00872 return Type::funType(typeDom, typeRan); 00873 } 00874 00875 00876 Type VCL::createType(const string& typeName) 00877 { 00878 if(d_dump) { 00879 d_translator->dump(Expr(TYPE, listExpr(idExpr(typeName)))); 00880 } 00881 return d_theoryCore->newTypeExpr(typeName); 00882 } 00883 00884 00885 Type VCL::createType(const string& typeName, const Type& def) 00886 { 00887 if (d_dump) { 00888 d_translator->dump(Expr(TYPE, idExpr(typeName), def.getExpr()), true); 00889 } 00890 return d_theoryCore->newTypeExpr(typeName, def); 00891 } 00892 00893 00894 Type VCL::lookupType(const string& typeName) 00895 { 00896 return d_theoryCore->lookupTypeExpr(typeName); 00897 } 00898 00899 00900 Expr VCL::varExpr(const string& name, const Type& type) 00901 { 00902 // Check if the ofstream is open (as opposed to the command line flag) 00903 if(d_dump) { 00904 d_translator->dump(Expr(CONST, idExpr(name), type.getExpr())); 00905 } 00906 return d_theoryCore->newVar(name, type); 00907 } 00908 00909 00910 Expr VCL::varExpr(const string& name, const Type& type, const Expr& def) 00911 { 00912 // Check if the ofstream is open (as opposed to the command line flag) 00913 if(d_dump) { 00914 d_translator->dump(Expr(CONST, idExpr(name), type.getExpr(), def), true); 00915 } 00916 // Prove the TCCs of the definition 00917 if(getFlags()["tcc"].getBool()) { 00918 Type tpDef(def.getType()), tpVar(type); 00919 // Make sure that def is in the subtype of tpVar; that is, prove 00920 // FORALL (x: tpDef): x = def => typePred(tpVar)(x) 00921 if(tpDef != tpVar) { 00922 // Typecheck the base types 00923 if(getBaseType(tpDef) != getBaseType(type)) { 00924 throw TypecheckException("Type mismatch in constant definition:\n" 00925 "Constant "+name+ 00926 " is declared with type:\n " 00927 +type.toString() 00928 +"\nBut the type of definition is\n " 00929 +tpDef.toString()); 00930 } 00931 TRACE("tccs", "CONST def: "+name+" : "+tpVar.toString() 00932 +" := <value> : ", tpDef, ";"); 00933 vector<Expr> boundVars; 00934 boundVars.push_back(boundVarExpr(name, "tcc", tpDef)); 00935 Expr body(boundVars[0].eqExpr(def).impExpr(getTypePred(tpVar, boundVars[0]))); 00936 Expr quant(forallExpr(boundVars, body)); 00937 try { 00938 checkTCC(quant); 00939 } catch(TypecheckException&) { 00940 throw TypecheckException 00941 ("Type mismatch in constant definition:\n" 00942 "Constant "+name+ 00943 " is declared with type:\n " 00944 +type.toString() 00945 +"\nBut the type of definition is\n " 00946 +def.getType().toString() 00947 +"\n\n which is not a subtype of the constant"); 00948 } 00949 } 00950 } 00951 return d_theoryCore->newVar(name, type, def); 00952 } 00953 00954 00955 Expr VCL::lookupVar(const string& name, Type* type) 00956 { 00957 return d_theoryCore->lookupVar(name, type); 00958 } 00959 00960 00961 Type VCL::getType(const Expr& e) 00962 { 00963 return e.getType(); 00964 } 00965 00966 00967 Type VCL::getBaseType(const Expr& e) 00968 { 00969 return d_theoryCore->getBaseType(e); 00970 } 00971 00972 00973 Type VCL::getBaseType(const Type& t) 00974 { 00975 return d_theoryCore->getBaseType(t); 00976 } 00977 00978 00979 Expr VCL::getTypePred(const Type&t, const Expr& e) 00980 { 00981 return d_theoryCore->getTypePred(t, e); 00982 } 00983 00984 00985 Expr VCL::stringExpr(const string& str) { 00986 return getEM()->newStringExpr(str); 00987 } 00988 00989 00990 Expr VCL::idExpr(const string& name) { 00991 return Expr(ID, stringExpr(name)); 00992 } 00993 00994 00995 Expr VCL::listExpr(const vector<Expr>& kids) { 00996 return Expr(RAW_LIST, kids, getEM()); 00997 } 00998 00999 01000 Expr VCL::listExpr(const Expr& e1) { 01001 return Expr(RAW_LIST, e1); 01002 } 01003 01004 01005 Expr VCL::listExpr(const Expr& e1, const Expr& e2) { 01006 return Expr(RAW_LIST, e1, e2); 01007 } 01008 01009 01010 Expr VCL::listExpr(const Expr& e1, const Expr& e2, const Expr& e3) { 01011 return Expr(RAW_LIST, e1, e2, e3); 01012 } 01013 01014 01015 Expr VCL::listExpr(const string& op, const vector<Expr>& kids) { 01016 vector<Expr> newKids; 01017 newKids.push_back(idExpr(op)); 01018 newKids.insert(newKids.end(), kids.begin(), kids.end()); 01019 return listExpr(newKids); 01020 } 01021 01022 01023 Expr VCL::listExpr(const string& op, const Expr& e1) { 01024 return Expr(RAW_LIST, idExpr(op), e1); 01025 } 01026 01027 01028 Expr VCL::listExpr(const string& op, const Expr& e1, 01029 const Expr& e2) { 01030 return Expr(RAW_LIST, idExpr(op), e1, e2); 01031 } 01032 01033 01034 Expr VCL::listExpr(const string& op, const Expr& e1, 01035 const Expr& e2, const Expr& e3) { 01036 vector<Expr> kids; 01037 kids.push_back(idExpr(op)); 01038 kids.push_back(e1); 01039 kids.push_back(e2); 01040 kids.push_back(e3); 01041 return listExpr(kids); 01042 } 01043 01044 01045 void VCL::printExpr(const Expr& e) { 01046 printExpr(e, cout); 01047 } 01048 01049 01050 void VCL::printExpr(const Expr& e, ostream& os) { 01051 os << e << endl; 01052 } 01053 01054 01055 Expr VCL::parseExpr(const Expr& e) { 01056 return d_theoryCore->parseExprTop(e); 01057 } 01058 01059 01060 Type VCL::parseType(const Expr& e) { 01061 return Type(d_theoryCore->parseExpr(e)); 01062 } 01063 01064 01065 Expr VCL::importExpr(const Expr& e) 01066 { 01067 return d_em->rebuild(e); 01068 } 01069 01070 01071 Type VCL::importType(const Type& t) 01072 { 01073 return Type(d_em->rebuild(t.getExpr())); 01074 } 01075 01076 void VCL::cmdsFromString(const std::string& s, InputLanguage lang=PRESENTATION_LANG) 01077 { 01078 stringstream ss(s,stringstream::in); 01079 return loadFile(ss,lang,false); 01080 } 01081 01082 Expr VCL::exprFromString(const std::string& s) 01083 { 01084 stringstream ss("PRINT " + s + ";",stringstream::in); 01085 Parser p(this,d_translator,PRESENTATION_LANG,ss); 01086 Expr e = p.next(); 01087 if( e.isNull() ) { 01088 throw ParserException("Parser result is null: '" + s + "'"); 01089 } 01090 DebugAssert(e.getKind() == RAW_LIST, "Expected list expression"); 01091 DebugAssert(e.arity() == 2, "Expected two children"); 01092 return parseExpr(e[1]); 01093 } 01094 01095 Expr VCL::trueExpr() 01096 { 01097 return d_em->trueExpr(); 01098 } 01099 01100 01101 Expr VCL::falseExpr() 01102 { 01103 return d_em->falseExpr(); 01104 } 01105 01106 01107 Expr VCL::notExpr(const Expr& child) 01108 { 01109 return !child; 01110 } 01111 01112 01113 Expr VCL::andExpr(const Expr& left, const Expr& right) 01114 { 01115 return left && right; 01116 } 01117 01118 01119 Expr VCL::andExpr(const vector<Expr>& children) 01120 { 01121 if (children.size() == 0) 01122 throw Exception("andExpr requires at least one child"); 01123 return Expr(AND, children); 01124 } 01125 01126 01127 Expr VCL::orExpr(const Expr& left, const Expr& right) 01128 { 01129 return left || right; 01130 } 01131 01132 01133 Expr VCL::orExpr(const vector<Expr>& children) 01134 { 01135 if (children.size() == 0) 01136 throw Exception("orExpr requires at least one child"); 01137 return Expr(OR, children); 01138 } 01139 01140 01141 Expr VCL::impliesExpr(const Expr& hyp, const Expr& conc) 01142 { 01143 return hyp.impExpr(conc); 01144 } 01145 01146 01147 Expr VCL::iffExpr(const Expr& left, const Expr& right) 01148 { 01149 return left.iffExpr(right); 01150 } 01151 01152 01153 Expr VCL::eqExpr(const Expr& child0, const Expr& child1) 01154 { 01155 return child0.eqExpr(child1); 01156 } 01157 01158 Expr VCL::distinctExpr(const std::vector<Expr>& children) 01159 { 01160 return Expr(DISTINCT, children); 01161 } 01162 01163 Expr VCL::iteExpr(const Expr& ifpart, const Expr& thenpart, const Expr& elsepart) 01164 { 01165 return ifpart.iteExpr(thenpart, elsepart); 01166 } 01167 01168 01169 Op VCL::createOp(const string& name, const Type& type) 01170 { 01171 if (!type.isFunction()) 01172 throw Exception("createOp: expected function type"); 01173 if(d_dump) { 01174 d_translator->dump(Expr(CONST, idExpr(name), type.getExpr())); 01175 } 01176 return d_theoryCore->newFunction(name, type, 01177 getFlags()["trans-closure"].getBool()); 01178 } 01179 01180 01181 Op VCL::createOp(const string& name, const Type& type, const Expr& def) 01182 { 01183 if (!type.isFunction()) 01184 throw TypecheckException 01185 ("Type error in createOp:\n" 01186 "Constant "+name+ 01187 " is declared with type:\n " 01188 +type.toString() 01189 +"\n which is not a function type"); 01190 if (getBaseType(type) != getBaseType(def.getType())) 01191 throw TypecheckException 01192 ("Type mismatch in createOp:\n" 01193 "Function "+name+ 01194 " is declared with type:\n " 01195 +type.toString() 01196 +"\nBut the type of definition is\n " 01197 +def.getType().toString() 01198 +"\n\n which does not match"); 01199 if(d_dump) { 01200 d_translator->dump(Expr(CONST, idExpr(name), type.getExpr(), def), true); 01201 } 01202 // Prove the TCCs of the definition 01203 if(getFlags()["tcc"].getBool()) { 01204 Type tpDef(def.getType()); 01205 // Make sure that def is within the subtype; that is, prove 01206 // FORALL (xs: argType): typePred_{return_type}(def(xs)) 01207 if(tpDef != type) { 01208 vector<Expr> boundVars; 01209 for (int i = 0; i < type.arity()-1; ++i) { 01210 boundVars.push_back(d_em->newBoundVarExpr(type[i])); 01211 } 01212 Expr app = Expr(def.mkOp(), boundVars); 01213 Expr body(getTypePred(type[type.arity()-1], app)); 01214 Expr quant(forallExpr(boundVars, body)); 01215 Expr tcc = quant.andExpr(d_theoryCore->getTCC(quant)); 01216 // Query the subtyping formula 01217 bool typesMatch = true; 01218 try { 01219 checkTCC(tcc); 01220 } catch (TypecheckException&) { 01221 typesMatch = false; 01222 } 01223 if(!typesMatch) { 01224 throw TypecheckException 01225 ("Type mismatch in createOp:\n" 01226 "Function "+name+ 01227 " is declared with type:\n " 01228 +type.toString() 01229 +"\nBut the definition is\n " 01230 +def.toString() 01231 +"\n\nwhose type could not be proved to be a subtype"); 01232 } 01233 } 01234 } 01235 return d_theoryCore->newFunction(name, type, def); 01236 } 01237 01238 01239 Op VCL::lookupOp(const string& name, Type* type) 01240 { 01241 return d_theoryCore->lookupFunction(name, type); 01242 } 01243 01244 01245 Expr VCL::funExpr(const Op& op, const Expr& child) 01246 { 01247 return Expr(op, child); 01248 } 01249 01250 01251 Expr VCL::funExpr(const Op& op, const Expr& left, const Expr& right) 01252 { 01253 return Expr(op, left, right); 01254 } 01255 01256 01257 Expr VCL::funExpr(const Op& op, const Expr& child0, const Expr& child1, const Expr& child2) 01258 { 01259 return Expr(op, child0, child1, child2); 01260 } 01261 01262 01263 Expr VCL::funExpr(const Op& op, const vector<Expr>& children) 01264 { 01265 return Expr(op, children); 01266 } 01267 01268 bool VCL::addPairToArithOrder(const Expr& smaller, const Expr& bigger) 01269 { 01270 if (d_dump) { 01271 d_translator->dump(Expr(ARITH_VAR_ORDER, smaller, bigger), true); 01272 } 01273 return d_theoryArith->addPairToArithOrder(smaller, bigger); 01274 } 01275 01276 Expr VCL::ratExpr(int n, int d) 01277 { 01278 DebugAssert(d != 0,"denominator cannot be 0"); 01279 return d_em->newRatExpr(Rational(n,d)); 01280 } 01281 01282 01283 Expr VCL::ratExpr(const string& n, const string& d, int base) 01284 { 01285 return d_em->newRatExpr(Rational(n.c_str(), d.c_str(), base)); 01286 } 01287 01288 01289 Expr VCL::ratExpr(const string& n, int base) 01290 { 01291 string::size_type pos = n.rfind("."); 01292 if (pos == string::npos) { 01293 return d_em->newRatExpr(Rational(n.c_str(), base)); 01294 } 01295 string afterdec = n.substr(pos+1); 01296 string beforedec = n.substr(0, pos); 01297 if (afterdec.size() == 0 || beforedec.size() == 0) { 01298 throw Exception("Cannot convert string to rational: "+n); 01299 } 01300 pos = beforedec.rfind("."); 01301 if (pos != string::npos) { 01302 throw Exception("Cannot convert string to rational: "+n); 01303 } 01304 Rational r = Rational(beforedec.c_str(), base); 01305 Rational fracPart = Rational(afterdec.c_str(), base); 01306 if( r < 0 || ((r == 0) && (beforedec.rfind("-") != string::npos)) ) { 01307 r = r - (fracPart / pow(afterdec.size(), (Rational)base)); 01308 } 01309 else { 01310 r = r + (fracPart / pow(afterdec.size(), (Rational)base)); 01311 } 01312 return d_em->newRatExpr(r); 01313 } 01314 01315 01316 Expr VCL::uminusExpr(const Expr& child) 01317 { 01318 return -child; 01319 } 01320 01321 01322 Expr VCL::plusExpr(const Expr& left, const Expr& right) 01323 { 01324 return left + right; 01325 } 01326 01327 Expr VCL::plusExpr(const std::vector<Expr>& children) 01328 { 01329 return Expr(PLUS, children); 01330 } 01331 01332 01333 Expr VCL::minusExpr(const Expr& left, const Expr& right) 01334 { 01335 return left - right; 01336 } 01337 01338 01339 Expr VCL::multExpr(const Expr& left, const Expr& right) 01340 { 01341 return left * right; 01342 } 01343 01344 01345 Expr VCL::powExpr(const Expr& x, const Expr& n) 01346 { 01347 return ::powExpr(n, x); 01348 } 01349 01350 01351 Expr VCL::divideExpr(const Expr& num, const Expr& denom) 01352 { 01353 return ::divideExpr(num,denom); 01354 } 01355 01356 01357 Expr VCL::ltExpr(const Expr& left, const Expr& right) 01358 { 01359 return ::ltExpr(left, right); 01360 } 01361 01362 01363 Expr VCL::leExpr(const Expr& left, const Expr& right) 01364 { 01365 return ::leExpr(left, right); 01366 } 01367 01368 01369 Expr VCL::gtExpr(const Expr& left, const Expr& right) 01370 { 01371 return ::gtExpr(left, right); 01372 } 01373 01374 01375 Expr VCL::geExpr(const Expr& left, const Expr& right) 01376 { 01377 return ::geExpr(left, right); 01378 } 01379 01380 01381 Expr VCL::recordExpr(const string& field, const Expr& expr) 01382 { 01383 vector<string> fields; 01384 vector<Expr> kids; 01385 kids.push_back(expr); 01386 fields.push_back(field); 01387 return d_theoryRecords->recordExpr(fields, kids); 01388 } 01389 01390 01391 Expr VCL::recordExpr(const string& field0, const Expr& expr0, 01392 const string& field1, const Expr& expr1) 01393 { 01394 vector<string> fields; 01395 vector<Expr> kids; 01396 fields.push_back(field0); 01397 fields.push_back(field1); 01398 kids.push_back(expr0); 01399 kids.push_back(expr1); 01400 sort2(fields, kids); 01401 return d_theoryRecords->recordExpr(fields, kids); 01402 } 01403 01404 01405 Expr VCL::recordExpr(const string& field0, const Expr& expr0, 01406 const string& field1, const Expr& expr1, 01407 const string& field2, const Expr& expr2) 01408 { 01409 vector<string> fields; 01410 vector<Expr> kids; 01411 fields.push_back(field0); 01412 fields.push_back(field1); 01413 fields.push_back(field2); 01414 kids.push_back(expr0); 01415 kids.push_back(expr1); 01416 kids.push_back(expr2); 01417 sort2(fields, kids); 01418 return d_theoryRecords->recordExpr(fields, kids); 01419 } 01420 01421 01422 Expr VCL::recordExpr(const vector<string>& fields, 01423 const vector<Expr>& exprs) 01424 { 01425 DebugAssert(fields.size() > 0, "VCL::recordExpr()"); 01426 DebugAssert(fields.size() == exprs.size(),"VCL::recordExpr()"); 01427 // Create copies of the vectors to sort them 01428 vector<string> fs(fields); 01429 vector<Expr> es(exprs); 01430 sort2(fs, es); 01431 return d_theoryRecords->recordExpr(fs, es); 01432 } 01433 01434 01435 Expr VCL::recSelectExpr(const Expr& record, const string& field) 01436 { 01437 return d_theoryRecords->recordSelect(record, field); 01438 } 01439 01440 01441 Expr VCL::recUpdateExpr(const Expr& record, const string& field, 01442 const Expr& newValue) 01443 { 01444 return d_theoryRecords->recordUpdate(record, field, newValue); 01445 } 01446 01447 01448 Expr VCL::readExpr(const Expr& array, const Expr& index) 01449 { 01450 return Expr(READ, array, index); 01451 } 01452 01453 01454 Expr VCL::writeExpr(const Expr& array, const Expr& index, const Expr& newValue) 01455 { 01456 return Expr(WRITE, array, index, newValue); 01457 } 01458 01459 01460 Expr VCL::newBVConstExpr(const std::string& s, int base) 01461 { 01462 return d_theoryBitvector->newBVConstExpr(s, base); 01463 } 01464 01465 01466 Expr VCL::newBVConstExpr(const std::vector<bool>& bits) 01467 { 01468 return d_theoryBitvector->newBVConstExpr(bits); 01469 } 01470 01471 01472 Expr VCL::newBVConstExpr(const Rational& r, int len) 01473 { 01474 return d_theoryBitvector->newBVConstExpr(r, len); 01475 } 01476 01477 01478 Expr VCL::newConcatExpr(const Expr& t1, const Expr& t2) 01479 { 01480 return d_theoryBitvector->newConcatExpr(t1, t2); 01481 } 01482 01483 01484 Expr VCL::newConcatExpr(const std::vector<Expr>& kids) 01485 { 01486 return d_theoryBitvector->newConcatExpr(kids); 01487 } 01488 01489 01490 Expr VCL::newBVExtractExpr(const Expr& e, int hi, int low) 01491 { 01492 return d_theoryBitvector->newBVExtractExpr(e, hi, low); 01493 } 01494 01495 01496 Expr VCL::newBVNegExpr(const Expr& t1) 01497 { 01498 return d_theoryBitvector->newBVNegExpr(t1); 01499 } 01500 01501 01502 Expr VCL::newBVAndExpr(const Expr& t1, const Expr& t2) 01503 { 01504 return d_theoryBitvector->newBVAndExpr(t1, t2); 01505 } 01506 01507 01508 Expr VCL::newBVAndExpr(const std::vector<Expr>& kids) 01509 { 01510 return d_theoryBitvector->newBVAndExpr(kids); 01511 } 01512 01513 01514 Expr VCL::newBVOrExpr(const Expr& t1, const Expr& t2) 01515 { 01516 return d_theoryBitvector->newBVOrExpr(t1, t2); 01517 } 01518 01519 01520 Expr VCL::newBVOrExpr(const std::vector<Expr>& kids) 01521 { 01522 return d_theoryBitvector->newBVOrExpr(kids); 01523 } 01524 01525 01526 Expr VCL::newBVXorExpr(const Expr& t1, const Expr& t2) 01527 { 01528 return d_theoryBitvector->newBVXorExpr(t1, t2); 01529 } 01530 01531 01532 Expr VCL::newBVXorExpr(const std::vector<Expr>& kids) 01533 { 01534 return d_theoryBitvector->newBVXorExpr(kids); 01535 } 01536 01537 01538 Expr VCL::newBVXnorExpr(const Expr& t1, const Expr& t2) 01539 { 01540 return d_theoryBitvector->newBVXnorExpr(t1, t2); 01541 } 01542 01543 01544 Expr VCL::newBVXnorExpr(const std::vector<Expr>& kids) 01545 { 01546 return d_theoryBitvector->newBVXnorExpr(kids); 01547 } 01548 01549 01550 Expr VCL::newBVNandExpr(const Expr& t1, const Expr& t2) 01551 { 01552 return d_theoryBitvector->newBVNandExpr(t1, t2); 01553 } 01554 01555 01556 Expr VCL::newBVNorExpr(const Expr& t1, const Expr& t2) 01557 { 01558 return d_theoryBitvector->newBVNorExpr(t1, t2); 01559 } 01560 01561 01562 Expr VCL::newBVCompExpr(const Expr& t1, const Expr& t2) 01563 { 01564 return d_theoryBitvector->newBVCompExpr(t1, t2); 01565 } 01566 01567 01568 Expr VCL::newBVLTExpr(const Expr& t1, const Expr& t2) 01569 { 01570 return d_theoryBitvector->newBVLTExpr(t1, t2); 01571 } 01572 01573 01574 Expr VCL::newBVLEExpr(const Expr& t1, const Expr& t2) 01575 { 01576 return d_theoryBitvector->newBVLEExpr(t1, t2); 01577 } 01578 01579 01580 Expr VCL::newBVSLTExpr(const Expr& t1, const Expr& t2) 01581 { 01582 return d_theoryBitvector->newBVSLTExpr(t1, t2); 01583 } 01584 01585 01586 Expr VCL::newBVSLEExpr(const Expr& t1, const Expr& t2) 01587 { 01588 return d_theoryBitvector->newBVSLEExpr(t1, t2); 01589 } 01590 01591 01592 Expr VCL::newSXExpr(const Expr& t1, int len) 01593 { 01594 return d_theoryBitvector->newSXExpr(t1, len); 01595 } 01596 01597 01598 Expr VCL::newBVUminusExpr(const Expr& t1) 01599 { 01600 return d_theoryBitvector->newBVUminusExpr(t1); 01601 } 01602 01603 01604 Expr VCL::newBVSubExpr(const Expr& t1, const Expr& t2) 01605 { 01606 return d_theoryBitvector->newBVSubExpr(t1, t2); 01607 } 01608 01609 01610 Expr VCL::newBVPlusExpr(int numbits, const std::vector<Expr>& k) 01611 { 01612 return d_theoryBitvector->newBVPlusPadExpr(numbits, k); 01613 } 01614 01615 Expr VCL::newBVPlusExpr(int numbits, const Expr& t1, const Expr& t2) 01616 { 01617 std::vector<Expr> k; 01618 k.push_back(t1); 01619 k.push_back(t2); 01620 return newBVPlusExpr(numbits, k); 01621 } 01622 01623 01624 Expr VCL::newBVMultExpr(int numbits, const Expr& t1, const Expr& t2) 01625 { 01626 return d_theoryBitvector->newBVMultPadExpr(numbits, t1, t2); 01627 } 01628 01629 Expr VCL::newBVUDivExpr(const Expr& t1, const Expr& t2) 01630 { 01631 return d_theoryBitvector->newBVUDivExpr(t1, t2); 01632 } 01633 01634 Expr VCL::newBVURemExpr(const Expr& t1, const Expr& t2) 01635 { 01636 return d_theoryBitvector->newBVURemExpr(t1, t2); 01637 } 01638 01639 Expr VCL::newBVSDivExpr(const Expr& t1, const Expr& t2) 01640 { 01641 return d_theoryBitvector->newBVSDivExpr(t1, t2); 01642 } 01643 01644 Expr VCL::newBVSRemExpr(const Expr& t1, const Expr& t2) 01645 { 01646 return d_theoryBitvector->newBVSRemExpr(t1, t2); 01647 } 01648 01649 Expr VCL::newBVSModExpr(const Expr& t1, const Expr& t2) 01650 { 01651 return d_theoryBitvector->newBVSModExpr(t1, t2); 01652 } 01653 01654 01655 Expr VCL::newFixedLeftShiftExpr(const Expr& t1, int r) 01656 { 01657 return d_theoryBitvector->newFixedLeftShiftExpr(t1, r); 01658 } 01659 01660 01661 Expr VCL::newFixedConstWidthLeftShiftExpr(const Expr& t1, int r) 01662 { 01663 return d_theoryBitvector->newFixedConstWidthLeftShiftExpr(t1, r); 01664 } 01665 01666 01667 Expr VCL::newFixedRightShiftExpr(const Expr& t1, int r) 01668 { 01669 return d_theoryBitvector->newFixedRightShiftExpr(t1, r); 01670 } 01671 01672 01673 Expr VCL::newBVSHL(const Expr& t1, const Expr& t2) 01674 { 01675 return Expr(BVSHL, t1, t2); 01676 } 01677 01678 01679 Expr VCL::newBVLSHR(const Expr& t1, const Expr& t2) 01680 { 01681 return Expr(BVLSHR, t1, t2); 01682 } 01683 01684 01685 Expr VCL::newBVASHR(const Expr& t1, const Expr& t2) 01686 { 01687 return Expr(BVASHR, t1, t2); 01688 } 01689 01690 01691 Rational VCL::computeBVConst(const Expr& e) 01692 { 01693 return d_theoryBitvector->computeBVConst(e); 01694 } 01695 01696 01697 Expr VCL::tupleExpr(const vector<Expr>& exprs) { 01698 DebugAssert(exprs.size() > 0, "VCL::tupleExpr()"); 01699 return d_theoryRecords->tupleExpr(exprs); 01700 } 01701 01702 01703 Expr VCL::tupleSelectExpr(const Expr& tuple, int index) 01704 { 01705 return d_theoryRecords->tupleSelect(tuple, index); 01706 } 01707 01708 01709 Expr VCL::tupleUpdateExpr(const Expr& tuple, int index, const Expr& newValue) 01710 { 01711 return d_theoryRecords->tupleUpdate(tuple, index, newValue); 01712 } 01713 01714 01715 Expr VCL::datatypeConsExpr(const string& constructor, const vector<Expr>& args) 01716 { 01717 return d_theoryDatatype->datatypeConsExpr(constructor, args); 01718 } 01719 01720 01721 Expr VCL::datatypeSelExpr(const string& selector, const Expr& arg) 01722 { 01723 return d_theoryDatatype->datatypeSelExpr(selector, arg); 01724 } 01725 01726 01727 Expr VCL::datatypeTestExpr(const string& constructor, const Expr& arg) 01728 { 01729 return d_theoryDatatype->datatypeTestExpr(constructor, arg); 01730 } 01731 01732 01733 Expr VCL::boundVarExpr(const string& name, const string& uid, 01734 const Type& type) { 01735 return d_em->newBoundVarExpr(name, uid, type); 01736 } 01737 01738 01739 Expr VCL::forallExpr(const vector<Expr>& vars, const Expr& body) { 01740 DebugAssert(vars.size() > 0, "VCL::foralLExpr()"); 01741 return d_em->newClosureExpr(FORALL, vars, body); 01742 } 01743 01744 Expr VCL::forallExpr(const vector<Expr>& vars, const Expr& body, 01745 const Expr& trigger) { 01746 DebugAssert(vars.size() > 0, "VCL::foralLExpr()"); 01747 return d_em->newClosureExpr(FORALL, vars, body, trigger); 01748 } 01749 01750 Expr VCL::forallExpr(const vector<Expr>& vars, const Expr& body, 01751 const vector<Expr>& triggers) { 01752 DebugAssert(vars.size() > 0, "VCL::foralLExpr()"); 01753 return d_em->newClosureExpr(FORALL, vars, body, triggers); 01754 } 01755 01756 Expr VCL::forallExpr(const vector<Expr>& vars, const Expr& body, 01757 const vector<vector<Expr> >& triggers) { 01758 DebugAssert(vars.size() > 0, "VCL::foralLExpr()"); 01759 return d_em->newClosureExpr(FORALL, vars, body, triggers); 01760 } 01761 01762 void VCL::setTriggers(const Expr& e, const vector< vector<Expr> >& triggers) { 01763 e.setTriggers(triggers); 01764 } 01765 01766 void VCL::setTriggers(const Expr& e, const vector<Expr>& triggers) { 01767 e.setTriggers(triggers); 01768 } 01769 01770 void VCL::setTrigger(const Expr& e, const Expr& trigger) { 01771 e.setTrigger(trigger); 01772 } 01773 01774 void VCL::setMultiTrigger(const Expr& e, const vector<Expr>& multiTrigger) { 01775 e.setMultiTrigger(multiTrigger); 01776 } 01777 01778 Expr VCL::existsExpr(const vector<Expr>& vars, const Expr& body) { 01779 return d_em->newClosureExpr(EXISTS, vars, body); 01780 } 01781 01782 01783 Op VCL::lambdaExpr(const vector<Expr>& vars, const Expr& body) { 01784 return d_em->newClosureExpr(LAMBDA, vars, body).mkOp(); 01785 } 01786 01787 Op VCL::transClosure(const Op& op) { 01788 const string& name = op.getExpr().getName(); 01789 return d_em->newSymbolExpr(name, TRANS_CLOSURE).mkOp(); 01790 } 01791 01792 01793 Expr VCL::simulateExpr(const Expr& f, const Expr& s0, 01794 const vector<Expr>& inputs, const Expr& n) { 01795 vector<Expr> kids; 01796 kids.push_back(f); 01797 kids.push_back(s0); 01798 kids.insert(kids.end(), inputs.begin(), inputs.end()); 01799 kids.push_back(n); 01800 return Expr(SIMULATE, kids); 01801 } 01802 01803 01804 void VCL::setResourceLimit(unsigned limit) 01805 { 01806 d_theoryCore->setResourceLimit(limit); 01807 } 01808 01809 01810 Theorem VCL::checkTCC(const Expr& tcc) 01811 { 01812 Theorem tccThm; 01813 d_se->push(); 01814 QueryResult res = d_se->checkValid(tcc, tccThm); 01815 switch (res) { 01816 case VALID: 01817 d_lastQueryTCC = tccThm; 01818 d_se->pop(); 01819 break; 01820 case INVALID: 01821 throw TypecheckException("Failed TCC:\n\n " 01822 +tcc.toString() 01823 +"\n\nWhich simplified to:\n\n " 01824 +simplify(tcc).toString() 01825 +"\n\nAnd the last formula is not valid " 01826 "in the current context."); 01827 case ABORT: 01828 throw TypecheckException("Budget exceeded:\n\n " 01829 "Unable to verify TCC:\n\n " 01830 +tcc.toString() 01831 +"\n\nWhich simplified to:\n\n " 01832 +simplify(tcc).toString()); 01833 case UNKNOWN: 01834 throw TypecheckException("Result unknown:\n\n " 01835 "Unable to verify TCC:\n\n " 01836 +tcc.toString() 01837 +"\n\nWhich simplified to:\n\n " 01838 +simplify(tcc).toString() 01839 +"\n\nAnd the last formula is unknown " 01840 "in the current context."); 01841 default: 01842 FatalAssert(false, "Unexpected case"); 01843 } 01844 return tccThm; 01845 } 01846 01847 01848 void VCL::assertFormula(const Expr& e) 01849 { 01850 if (getFlags()["no-save-model"].getBool() && d_modelStackPushed) { 01851 d_modelStackPushed = false; 01852 pop(); 01853 } 01854 01855 // Typecheck the user input 01856 if(!e.getType().isBool()) { 01857 throw TypecheckException("Non-BOOLEAN formula in ASSERT:\n " 01858 +Expr(ASSERT, e).toString() 01859 +"\nDerived type of the formula:\n " 01860 +e.getType().toString()); 01861 } 01862 01863 if (getFlags()["pp-batch"].getBool()) { 01864 d_batchedAssertions->push_back(e); 01865 } 01866 else { 01867 // Check if the ofstream is open (as opposed to the command line flag) 01868 if(d_dump) { 01869 Expr e2 = e; 01870 if (getFlags()["preSimplify"].getBool()) { 01871 e2 = d_theoryCore->getExprTrans()->preprocess(e).getRHS(); 01872 } 01873 if (d_translator->dumpAssertion(e2)) return; 01874 } 01875 01876 TRACE("vclassertFormula", "VCL::assertFormula(", e, ") {"); 01877 01878 // See if e was already asserted before 01879 if(d_userAssertions->count(e) > 0) { 01880 TRACE_MSG("vclassertFormula", "VCL::assertFormula[repeated assertion] => }"); 01881 return; 01882 } 01883 // Check the validity of the TCC 01884 Theorem tccThm; 01885 if(getFlags()["tcc"].getBool()) { 01886 Expr tcc(d_theoryCore->getTCC(e)); 01887 tccThm = checkTCC(tcc); 01888 } 01889 01890 Theorem thm = d_se->newUserAssumption(e); 01891 (*d_userAssertions)[e] = UserAssertion(thm, tccThm, d_nextIdx++); 01892 } 01893 TRACE_MSG("vclassertFormula", "VCL::assertFormula => }"); 01894 } 01895 01896 01897 void VCL::registerAtom(const Expr& e) 01898 { 01899 //TODO: add to interactive interface 01900 d_se->registerAtom(e); 01901 } 01902 01903 01904 Expr VCL::getImpliedLiteral() 01905 { 01906 //TODO: add to interactive interface 01907 Theorem thm = d_se->getImpliedLiteral(); 01908 if (thm.isNull()) return Expr(); 01909 return thm.getExpr(); 01910 } 01911 01912 01913 Expr VCL::simplify(const Expr& e) { 01914 //TODO: add to interactive interface 01915 return simplifyThm(e).getRHS(); 01916 } 01917 01918 01919 Theorem VCL::simplifyThm(const Expr& e) 01920 { 01921 e.getType(); 01922 Theorem res = d_theoryCore->getExprTrans()->preprocess(e); 01923 Theorem simpThm = d_theoryCore->simplify(res.getRHS()); 01924 res = d_theoryCore->transitivityRule(res, simpThm); 01925 return res; 01926 } 01927 01928 01929 QueryResult VCL::query(const Expr& e) 01930 { 01931 TRACE("query", "VCL::query(", e,") {"); 01932 01933 if (getFlags()["no-save-model"].getBool()) { 01934 if(d_modelStackPushed) { 01935 d_modelStackPushed = false; 01936 pop(); 01937 } 01938 push(); 01939 d_modelStackPushed = true; 01940 } 01941 01942 // Typecheck the user input 01943 if(!e.getType().isBool()) { 01944 throw TypecheckException("Non-BOOLEAN formula in QUERY:\n " 01945 +Expr(QUERY, e).toString() 01946 +"\nDerived type of the formula:\n " 01947 +e.getType().toString()); 01948 } 01949 01950 Expr qExpr = e; 01951 if (getFlags()["pp-batch"].getBool()) { 01952 // Add batched assertions 01953 vector<Expr> kids; 01954 for (; (*d_batchedAssertionsIdx) < d_batchedAssertions->size(); 01955 (*d_batchedAssertionsIdx) = (*d_batchedAssertionsIdx) + 1) { 01956 kids.push_back((*d_batchedAssertions)[(*d_batchedAssertionsIdx)]); 01957 } 01958 if (kids.size() > 0) { 01959 qExpr = kids.size() == 1 ? kids[0] : Expr(AND, kids); 01960 qExpr = qExpr.impExpr(e); 01961 } 01962 } 01963 01964 if (d_dump && !getFlags()["dump-tcc"].getBool()) { 01965 Expr e2 = qExpr; 01966 if (getFlags()["preSimplify"].getBool()) { 01967 e2 = d_theoryCore->getExprTrans()->preprocess(qExpr).getRHS(); 01968 } 01969 if (d_translator->dumpQuery(e2)) return UNKNOWN; 01970 } 01971 01972 // Check the validity of the TCC 01973 Theorem tccThm = d_se->getCommonRules()->trueTheorem(); 01974 if(getFlags()["tcc"].getBool()) { 01975 Expr tcc(d_theoryCore->getTCC(qExpr)); 01976 if (getFlags()["dump-tcc"].getBool()) { 01977 Expr e2 = tcc; 01978 if (getFlags()["preSimplify"].getBool()) { 01979 e2 = d_theoryCore->getExprTrans()->preprocess(tcc).getRHS(); 01980 } 01981 if (d_translator->dumpQuery(e2)) return UNKNOWN; 01982 } 01983 // FIXME: we have to guarantee that the TCC of 'tcc' is always valid 01984 tccThm = checkTCC(tcc); 01985 } 01986 Theorem res; 01987 QueryResult qres = d_se->checkValid(qExpr, res); 01988 switch (qres) { 01989 case VALID: 01990 d_lastQuery = d_se->getCommonRules()->queryTCC(res, tccThm); 01991 break; 01992 default: 01993 d_lastQueryTCC = Theorem(); 01994 d_lastQuery = Theorem3(); 01995 d_lastClosure = Theorem3(); 01996 } 01997 TRACE("query", "VCL::query => ", 01998 qres == VALID ? "VALID" : 01999 qres == INVALID ? "INVALID" : 02000 qres == ABORT ? "ABORT" : "UNKNOWN", " }"); 02001 02002 if (d_dump) d_translator->dumpQueryResult(qres); 02003 02004 return qres; 02005 } 02006 02007 02008 QueryResult VCL::checkUnsat(const Expr& e) 02009 { 02010 return query(e.negate()); 02011 } 02012 02013 02014 QueryResult VCL::checkContinue() 02015 { 02016 if(d_dump) { 02017 d_translator->dump(d_em->newLeafExpr(CONTINUE), true); 02018 } 02019 vector<Expr> assertions; 02020 d_se->getCounterExample(assertions); 02021 Theorem thm; 02022 if (assertions.size() == 0) { 02023 return d_se->restart(falseExpr(), thm); 02024 } 02025 Expr eAnd = assertions.size() == 1 ? assertions[0] : andExpr(assertions); 02026 return d_se->restart(!eAnd, thm); 02027 } 02028 02029 02030 QueryResult VCL::restart(const Expr& e) 02031 { 02032 if (d_dump) { 02033 d_translator->dump(Expr(RESTART, e), true); 02034 } 02035 Theorem thm; 02036 return d_se->restart(e, thm); 02037 } 02038 02039 02040 void VCL::returnFromCheck() 02041 { 02042 //TODO: add to interactive interface 02043 d_se->returnFromCheck(); 02044 } 02045 02046 02047 void VCL::getUserAssumptions(vector<Expr>& assumptions) 02048 { 02049 // TODO: add to interactive interface 02050 d_se->getUserAssumptions(assumptions); 02051 } 02052 02053 02054 void VCL::getInternalAssumptions(vector<Expr>& assumptions) 02055 { 02056 // TODO: add to interactive interface 02057 d_se->getInternalAssumptions(assumptions); 02058 } 02059 02060 02061 void VCL::getAssumptions(vector<Expr>& assumptions) 02062 { 02063 if(d_dump) { 02064 d_translator->dump(d_em->newLeafExpr(ASSUMPTIONS), true); 02065 } 02066 d_se->getAssumptions(assumptions); 02067 } 02068 02069 02070 //yeting, for proof translation 02071 Expr VCL::getProofQuery() 02072 { 02073 if (d_lastQuery.isNull()){ 02074 throw EvalException 02075 ("Invalid Query,n"); 02076 } 02077 return d_lastQuery.getExpr(); 02078 02079 // Theorem thm = d_se->lastThm(); 02080 // if (thm.isNull()) return; 02081 // thm.getLeafAssumptions(assumptions); 02082 } 02083 02084 02085 void VCL::getAssumptionsUsed(vector<Expr>& assumptions) 02086 { 02087 throw EvalException ("getAssumptionsUsed not currently supported"); 02088 if(d_dump) { 02089 d_translator->dump(d_em->newLeafExpr(DUMP_ASSUMPTIONS), true); 02090 } 02091 Theorem thm = d_se->lastThm(); 02092 if (thm.isNull()) return; 02093 thm.getLeafAssumptions(assumptions); 02094 } 02095 02096 02097 void VCL::getCounterExample(vector<Expr>& assertions, bool inOrder) 02098 { 02099 if(d_dump) { 02100 d_translator->dump(d_em->newLeafExpr(COUNTEREXAMPLE), true); 02101 } 02102 if (!(*d_flags)["translate"].getBool()) 02103 d_se->getCounterExample(assertions, inOrder); 02104 } 02105 02106 02107 void VCL::getConcreteModel(ExprMap<Expr> & m) 02108 { 02109 if(d_dump) { 02110 d_translator->dump(d_em->newLeafExpr(COUNTERMODEL), true); 02111 } 02112 if (!(*d_flags)["translate"].getBool()) 02113 d_se->getConcreteModel(m); 02114 } 02115 02116 QueryResult VCL::tryModelGeneration() { 02117 if (!d_theoryCore->incomplete()) throw Exception("Model generation should be called only after an UNKNOWN result"); 02118 QueryResult qres = UNKNOWN; 02119 int scopeLevel = d_cm->scopeLevel(); 02120 try { 02121 while (qres == UNKNOWN) 02122 { 02123 Theorem thm; 02124 d_se->push(); 02125 // Try to generate the model 02126 if (d_se->tryModelGeneration(thm)) 02127 // If success, we are satisfiable 02128 qres = INVALID; 02129 else 02130 { 02131 // Generate the clause to get rid of the faults 02132 vector<Expr> assumptions; 02133 thm.getLeafAssumptions(assumptions, true /*negate*/); 02134 if (!thm.getExpr().isFalse()) assumptions.push_back(thm.getExpr()); 02135 // Pop back to where we were 02136 while (d_cm->scopeLevel() > scopeLevel) d_se->pop(); 02137 // Restart with the new clause 02138 qres = restart(orExpr(assumptions)); 02139 // Keep this level 02140 scopeLevel = d_cm->scopeLevel(); 02141 } 02142 } 02143 } catch (Exception& e) { 02144 // Pop back to where we were 02145 while (d_cm->scopeLevel() > scopeLevel) d_se->pop(); 02146 } 02147 return qres; 02148 } 02149 02150 FormulaValue VCL::value(const Expr& e) { 02151 DebugAssert(!e.isTerm(), "vcl::value: e is not a formula"); 02152 return d_se->getValue(e); 02153 } 02154 02155 bool VCL::inconsistent(vector<Expr>& assumptions) 02156 { 02157 // TODO: add to interactive interface 02158 if (d_theoryCore->inconsistent()) { 02159 // TODO: do we need local getAssumptions? 02160 getAssumptions(d_theoryCore->inconsistentThm().getAssumptionsRef(), 02161 assumptions); 02162 return true; 02163 } 02164 return false; 02165 } 02166 02167 bool VCL::inconsistent() 02168 { 02169 return d_theoryCore->inconsistent(); 02170 } 02171 02172 02173 bool VCL::incomplete() { 02174 // TODO: add to interactive interface 02175 // Return true only after a failed query 02176 return (d_lastQuery.isNull() && d_theoryCore->incomplete()); 02177 } 02178 02179 02180 bool VCL::incomplete(vector<string>& reasons) { 02181 // TODO: add to interactive interface 02182 // Return true only after a failed query 02183 return (d_lastQuery.isNull() && d_theoryCore->incomplete(reasons)); 02184 } 02185 02186 02187 Proof VCL::getProof() 02188 { 02189 if(d_dump) { 02190 d_translator->dump(d_em->newLeafExpr(DUMP_PROOF), true); 02191 } 02192 02193 if(d_lastQuery.isNull()) 02194 throw EvalException 02195 ("Method getProof() (or command DUMP_PROOF)\n" 02196 " must be called only after a Valid QUERY"); 02197 return d_se->getProof(); 02198 } 02199 02200 Expr VCL::getAssignment() { 02201 if(d_dump) { 02202 d_translator->dump(d_em->newLeafExpr(GET_ASSIGNMENT), true); 02203 } 02204 return d_theoryCore->getAssignment(); 02205 } 02206 02207 Expr VCL::getValue(Expr e) { 02208 if(d_dump) { 02209 d_translator->dump(Expr(GET_VALUE, e), true); 02210 } 02211 return simplify(e); 02212 } 02213 02214 Expr VCL::getTCC(){ 02215 static Expr null; 02216 if(d_dump) { 02217 d_translator->dump(d_em->newLeafExpr(DUMP_TCC), true); 02218 } 02219 if(d_lastQueryTCC.isNull()) return null; 02220 else return d_lastQueryTCC.getExpr(); 02221 } 02222 02223 02224 void VCL::getAssumptionsTCC(vector<Expr>& assumptions) 02225 { 02226 if(d_dump) { 02227 d_translator->dump(d_em->newLeafExpr(DUMP_TCC_ASSUMPTIONS), true); 02228 } 02229 if(d_lastQuery.isNull()) 02230 throw EvalException 02231 ("Method getAssumptionsTCC() (or command DUMP_TCC_ASSUMPTIONS)\n" 02232 " must be called only after a Valid QUERY"); 02233 getAssumptions(d_lastQueryTCC.getAssumptionsRef(), assumptions); 02234 } 02235 02236 02237 Proof VCL::getProofTCC() { 02238 static Proof null; 02239 if(d_dump) { 02240 d_translator->dump(d_em->newLeafExpr(DUMP_TCC_PROOF), true); 02241 } 02242 if(d_lastQueryTCC.isNull()) return null; 02243 else return d_lastQueryTCC.getProof(); 02244 } 02245 02246 02247 Expr VCL::getClosure() { 02248 static Expr null; 02249 if(d_dump) { 02250 d_translator->dump(d_em->newLeafExpr(DUMP_CLOSURE), true); 02251 } 02252 if(d_lastClosure.isNull() && !d_lastQuery.isNull()) { 02253 // Construct the proof of closure and cache it in d_lastClosure 02254 d_lastClosure = deriveClosure(d_lastQuery); 02255 } 02256 if(d_lastClosure.isNull()) return null; 02257 else return d_lastClosure.getExpr(); 02258 } 02259 02260 02261 Proof VCL::getProofClosure() { 02262 static Proof null; 02263 if(d_dump) { 02264 d_translator->dump(d_em->newLeafExpr(DUMP_CLOSURE_PROOF), true); 02265 } 02266 if(d_lastClosure.isNull() && !d_lastQuery.isNull()) { 02267 // Construct the proof of closure and cache it in d_lastClosure 02268 d_lastClosure = deriveClosure(d_lastQuery); 02269 } 02270 if(d_lastClosure.isNull()) return null; 02271 else return d_lastClosure.getProof(); 02272 } 02273 02274 02275 int VCL::stackLevel() 02276 { 02277 return d_stackLevel->get(); 02278 } 02279 02280 02281 void VCL::push() 02282 { 02283 if (getFlags()["no-save-model"].getBool() && d_modelStackPushed) { 02284 d_modelStackPushed = false; 02285 pop(); 02286 } else if (d_dump) { 02287 d_translator->dump(d_em->newLeafExpr(PUSH), true); 02288 } 02289 d_se->push(); 02290 d_stackLevel->set(stackLevel()+1); 02291 } 02292 02293 02294 void VCL::pop() 02295 { 02296 if (getFlags()["no-save-model"].getBool() && d_modelStackPushed) { 02297 d_modelStackPushed = false; 02298 pop(); 02299 } else if (d_dump) { 02300 d_translator->dump(d_em->newLeafExpr(POP), true); 02301 } 02302 if (stackLevel() == 0) { 02303 throw EvalException 02304 ("POP called with no previous call to PUSH"); 02305 } 02306 int level = stackLevel(); 02307 while (level == stackLevel()) 02308 d_se->pop(); 02309 } 02310 02311 02312 void VCL::popto(int toLevel) 02313 { 02314 // Check if the ofstream is open (as opposed to the command line flag) 02315 if(d_dump) { 02316 d_translator->dump(Expr(POPTO, ratExpr(toLevel, 1)), true); 02317 } 02318 if (toLevel < 0) toLevel = 0; 02319 while (stackLevel() > toLevel) { 02320 d_se->pop(); 02321 } 02322 } 02323 02324 02325 int VCL::scopeLevel() 02326 { 02327 return d_cm->scopeLevel(); 02328 } 02329 02330 02331 void VCL::pushScope() 02332 { 02333 throw EvalException ("Scope-level push/pop is no longer supported"); 02334 d_cm->push(); 02335 if(d_dump) { 02336 d_translator->dump(d_em->newLeafExpr(PUSH_SCOPE), true); 02337 } 02338 IF_DEBUG(if((*d_flags)["dump-trace"].getString() != "") 02339 dumpTrace(scopeLevel());) 02340 } 02341 02342 02343 void VCL::popScope() 02344 { 02345 throw EvalException ("Scope-level push/pop is no longer supported"); 02346 if(d_dump) { 02347 d_translator->dump(d_em->newLeafExpr(POP_SCOPE), true); 02348 } 02349 if (scopeLevel() == 1) { 02350 cout << "Cannot POP from scope level 1" << endl; 02351 } 02352 else d_cm->pop(); 02353 IF_DEBUG(if((*d_flags)["dump-trace"].getString() != "") 02354 dumpTrace(scopeLevel());) 02355 } 02356 02357 02358 void VCL::poptoScope(int toLevel) 02359 { 02360 throw EvalException ("Scope-level push/pop is no longer supported"); 02361 if(d_dump) { 02362 d_translator->dump(Expr(POPTO_SCOPE, ratExpr(toLevel, 1)), true); 02363 } 02364 if (toLevel < 1) { 02365 d_cm->popto(0); 02366 d_cm->push(); 02367 } 02368 else d_cm->popto(toLevel); 02369 IF_DEBUG(if((*d_flags)["dump-trace"].getString() != "") 02370 dumpTrace(scopeLevel());) 02371 } 02372 02373 02374 Context* VCL::getCurrentContext() 02375 { 02376 return d_cm->getCurrentContext(); 02377 } 02378 02379 02380 void VCL::reset() 02381 { 02382 destroy(); 02383 init(); 02384 } 02385 02386 void VCL::logAnnotation(const Expr& annot) 02387 { 02388 if (d_dump) { 02389 d_translator->dump(annot); 02390 } 02391 } 02392 02393 void VCL::loadFile(const string& fileName, InputLanguage lang, 02394 bool interactive, bool calledFromParser) { 02395 // TODO: move these? 02396 Parser parser(this, d_translator, lang, interactive, fileName); 02397 VCCmd cmd(this, &parser, calledFromParser); 02398 cmd.processCommands(); 02399 } 02400 02401 02402 void VCL::loadFile(istream& is, InputLanguage lang, 02403 bool interactive) { 02404 // TODO: move these? 02405 Parser parser(this, d_translator, lang, is, interactive); 02406 VCCmd cmd(this, &parser); 02407 cmd.processCommands(); 02408 } 02409 02410 02411 // Verbosity: <= 0 = print nothing, only calculate 02412 // 1 = only print current level 02413 // n = print n recursive levels 02414 02415 unsigned long VCL::getMemory(int verbosity) 02416 { 02417 unsigned long memSelf = sizeof(VCL); 02418 unsigned long mem = 0; 02419 02420 mem += d_cm->getMemory(verbosity - 1); 02421 mem += d_em->getMemory(verbosity - 1); 02422 // mem += d_tm->getMemory(verbosity - 1); 02423 // mem += d_se->getMemory(verbosity - 1); 02424 02425 // mem += d_theoryCore->getMemory(verbosity - 1); 02426 // mem += d_theoryUF->getMemory(verbosity - 1); 02427 // mem += d_theoryArith->getMemory(verbosity - 1); 02428 // mem += d_theoryArray->getMemory(verbosity - 1); 02429 // mem += d_theoryQuant->getMemory(verbosity - 1); 02430 // mem += d_theoryRecords->getMemory(verbosity - 1); 02431 // mem += d_theorySimulate->getMemory(verbosity - 1); 02432 // mem += d_theoryBitvector->getMemory(verbosity - 1); 02433 // mem += d_theoryDatatype->getMemory(verbosity - 1); 02434 // mem += d_translator->getMemory(verbosity - 1); 02435 02436 // mem += getMemoryVec(verbosity, d_theories, false, true); 02437 02438 // mem += d_flags->getMemory(verbosity - 1); 02439 // mem += d_stackLevel->getMemory(verbosity - 1); 02440 // mem += d_statistics->getMemory(verbosity - 1); 02441 // mem += d_userAssertions->getMemory(verbosity - 1); 02442 // mem += d_batchedAssertions->getMemory(verbosity - 1); 02443 // mem += d_batchedAssertionsIdx->getMemory(verbosity - 1); 02444 02445 //TODO: how to get memory for Expr and Theorems? 02446 02447 MemoryTracker::print("VCL", verbosity, memSelf, mem); 02448 02449 return mem + memSelf; 02450 } 02451 02452 void VCL::setTimeLimit(unsigned limit) { 02453 d_theoryCore->setTimeLimit(limit); 02454 }