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