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