CVC3
|
00001 /*****************************************************************************/ 00002 /*! 00003 * \file vc_cmd.cpp 00004 * 00005 * Author: Clark Barrett 00006 * 00007 * Created: Fri Dec 13 22:39:02 2002 00008 * 00009 * <hr> 00010 * License to use, copy, modify, sell and/or distribute this software 00011 * and its documentation for any purpose is hereby granted without 00012 * royalty, subject to the terms and conditions defined in the \ref 00013 * LICENSE file provided with this distribution. 00014 * 00015 * <hr> 00016 * 00017 */ 00018 /*****************************************************************************/ 00019 00020 #include <fstream> 00021 #include "vc_cmd.h" 00022 #include "vc.h" 00023 #include "parser.h" 00024 #include "eval_exception.h" 00025 #include "typecheck_exception.h" 00026 #include "command_line_flags.h" 00027 #include "expr_stream.h" 00028 00029 using namespace std; 00030 using namespace CVC3; 00031 00032 VCCmd::VCCmd(ValidityChecker* vc, Parser* parser, bool calledFromParser) 00033 : d_vc(vc), d_parser(parser), d_name_of_cur_ctxt("DEFAULT"), 00034 d_calledFromParser(calledFromParser) 00035 { 00036 d_map[d_name_of_cur_ctxt.c_str()] = d_vc->getCurrentContext(); 00037 } 00038 00039 VCCmd::~VCCmd() { } 00040 00041 void VCCmd::findAxioms(const Expr& e, ExprMap<bool>& skolemAxioms, 00042 ExprMap<bool>& visited) { 00043 if(visited.count(e)>0) 00044 return; 00045 else visited[e] = true; 00046 if(e.isSkolem()) { 00047 skolemAxioms.insert(e.getExistential(), true); 00048 return; 00049 } 00050 if(e.isClosure()) { 00051 findAxioms(e.getBody(), skolemAxioms, visited); 00052 } 00053 if(e.arity()>0) { 00054 Expr::iterator end = e.end(); 00055 for(Expr::iterator i = e.begin(); i!=end; ++i) 00056 findAxioms(*i, skolemAxioms, visited); 00057 } 00058 00059 } 00060 00061 Expr VCCmd::skolemizeAx(const Expr& e) 00062 { 00063 vector<Expr>vars; 00064 const vector<Expr>boundVars = e.getVars(); 00065 for(unsigned int i=0; i<boundVars.size(); i++) { 00066 Expr skolV(e.skolemExpr(i)); 00067 vars.push_back(skolV); 00068 } 00069 Expr sub = e.getBody().substExpr(boundVars, vars); 00070 return e.iffExpr(sub); 00071 } 00072 00073 bool VCCmd::evaluateNext() 00074 { 00075 readAgain: 00076 if(d_parser->done()) return false; // No more commands 00077 Expr e; 00078 try { 00079 TRACE_MSG("commands", "** [commands] Parsing command..."); 00080 e = d_parser->next(); 00081 TRACE("commands verbose", "evaluateNext(", e, ")"); 00082 } 00083 catch(Exception& e) { 00084 cerr << "*** " << e << endl; 00085 IF_DEBUG(++(debugger.counter("parse errors"));) 00086 } 00087 // The parser may return a Null Expr in case of parse errors or end 00088 // of file. The right thing to do is to ignore it and repeat 00089 // reading. 00090 if(e.isNull()) { 00091 TRACE_MSG("commands", "** [commands] Null command; read again"); 00092 goto readAgain; 00093 } 00094 if( d_vc->getFlags()["parse-only"].getBool() ) { 00095 TRACE_MSG("commands", "** [commands] parse-only; skipping evaluateCommand"); 00096 goto readAgain; 00097 } 00098 00099 return evaluateCommand(e); 00100 } 00101 00102 void VCCmd::reportResult(QueryResult qres, bool checkingValidity) 00103 { 00104 if (d_vc->getFlags()["printResults"].getBool()) { 00105 if (d_vc->getEM()->getOutputLang() == SMTLIB_LANG 00106 || d_vc->getEM()->getOutputLang() == SMTLIB_V2_LANG) { 00107 switch (qres) { 00108 case VALID: 00109 cout << "unsat" << endl; 00110 break; 00111 case INVALID: 00112 cout << "sat" << endl; 00113 break; 00114 case ABORT: 00115 case UNKNOWN: 00116 cout << "unknown" << endl; 00117 break; 00118 default: 00119 FatalAssert(false, "Unexpected case"); 00120 } 00121 } 00122 else { 00123 switch (qres) { 00124 case VALID: 00125 cout << (checkingValidity ? "Valid." : "Unsatisfiable.") << endl; 00126 break; 00127 case INVALID: 00128 cout << (checkingValidity ? "Invalid." : "Satisfiable.") << endl; 00129 break; 00130 case ABORT: 00131 cout << "Unknown: resource limit exhausted." << endl; 00132 break; 00133 case UNKNOWN: { 00134 // Vector of reasons in case of incomplete result 00135 vector<string> reasons; 00136 IF_DEBUG(bool b =) d_vc->incomplete(reasons); 00137 DebugAssert(b, "Expected incompleteness"); 00138 cout << "Unknown.\n\n"; 00139 cout << "CVC3 was incomplete in this example due to:"; 00140 for(vector<string>::iterator i=reasons.begin(), iend=reasons.end(); 00141 i!=iend; ++i) 00142 cout << "\n * " << (*i); 00143 cout << endl << endl; 00144 break; 00145 } 00146 default: 00147 FatalAssert(false, "Unexpected case"); 00148 } 00149 } 00150 cout << flush; 00151 } 00152 //d_vc->printStatistics(); 00153 // exit(0); 00154 } 00155 00156 00157 void VCCmd::printModel() 00158 { 00159 ExprMap<Expr> m; 00160 d_vc->getConcreteModel(m); 00161 00162 cout << "Current scope level is " << d_vc->scopeLevel() << "." << endl; 00163 ExprMap<Expr>::iterator it = m.begin(), end = m.end(); 00164 if(it == end) 00165 cout << " Did not find concrete model for any vars" << endl; 00166 else { 00167 cout << "%Satisfiable Variable Assignment: % \n"; 00168 for(; it!= end; it++) { 00169 Expr eq; 00170 if(it->first.getType().isBool()) { 00171 DebugAssert((it->second).isBoolConst(), 00172 "Bad variable assignement: e = "+(it->first).toString() 00173 +"\n\n val = "+(it->second).toString()); 00174 if((it->second).isTrue()) 00175 eq = it->first; 00176 else 00177 eq = !(it->first); 00178 } 00179 else 00180 eq = (it->first).eqExpr(it->second); 00181 cout << Expr(ASSERT, eq) << "\n"; 00182 } 00183 } 00184 } 00185 00186 00187 // For debugging: there are missing cases: user-defined types, symbols inside of quantifiers, etc. 00188 void VCCmd::printSymbols(Expr e, ExprMap<bool>& cache) 00189 { 00190 if (cache.find(e) != cache.end()) return; 00191 switch (e.getKind()) { 00192 case SKOLEM_VAR: 00193 case UCONST: { 00194 cout << e << " : "; 00195 ExprStream os(d_vc->getEM()); 00196 os.dagFlag(false); 00197 os << e.getType().getExpr(); 00198 cout << ";" << endl; 00199 break; 00200 } 00201 case APPLY: { 00202 Expr op = e.getOpExpr(); 00203 if ((op.getKind() == UFUNC) && (cache.find(op) == cache.end())) { 00204 cout << op << " : "; 00205 ExprStream os(d_vc->getEM()); 00206 os.dagFlag(false); 00207 os << op.getType().getExpr(); 00208 cout << ";" << endl; 00209 cache[op] = true; 00210 } 00211 // fall through 00212 } 00213 default: { 00214 Expr::iterator i = e.begin(), iend = e.end(); 00215 for (; i != iend; ++i) { 00216 printSymbols(*i, cache); 00217 } 00218 break; 00219 } 00220 } 00221 cache[e] = true; 00222 } 00223 00224 00225 bool debug_skolem = false; 00226 00227 00228 void VCCmd::printCounterExample() 00229 { 00230 vector<Expr> assertions; 00231 ExprMap<bool> skolemAxioms; 00232 ExprMap<bool> visited; 00233 00234 d_vc->getCounterExample(assertions); 00235 00236 // get variable information 00237 ExprMap<bool> cache; 00238 unsigned i; 00239 for (i = 0; i < assertions.size(); i++) { 00240 printSymbols(assertions[i], cache); 00241 } 00242 00243 cout << "% Current scope level is " << d_vc->scopeLevel() << "." << endl; 00244 if (assertions.size() == 0) { 00245 cout << "% There are no assertions\n"; 00246 } else { 00247 00248 cout << "% Assertions which make the QUERY invalid:\n"; 00249 00250 for (i = 0; i < assertions.size(); i++) { 00251 cout << Expr(ASSERT, assertions[i]) << "\n"; 00252 findAxioms(assertions[i], skolemAxioms, visited); 00253 } 00254 00255 if (debug_skolem) { 00256 cout << "% Including skolemization axioms:\n"; 00257 00258 ExprMap<bool>::iterator end = skolemAxioms.end(); 00259 for(ExprMap<bool>::iterator it = skolemAxioms.begin(); it!=end; it++) 00260 cout << "ASSERT " << skolemizeAx((*it).first) << ";" << endl; 00261 } 00262 } 00263 cout << endl; 00264 } 00265 00266 00267 bool VCCmd::evaluateCommand(const Expr& e0) 00268 { 00269 TRACE("commands", "evaluateCommand(", e0.toString(PRESENTATION_LANG), ") {"); 00270 Expr e(e0); 00271 if(e.getKind() != RAW_LIST || e.arity() == 0 || e[0].getKind() != ID) 00272 throw EvalException("Invalid command: "+e.toString()); 00273 const string& kindName = e[0][0].getString(); 00274 int kind = d_vc->getEM()->getKind(kindName); 00275 if(kind == NULL_KIND) 00276 throw EvalException("Unknown command: "+e.toString()); 00277 switch(kind) { 00278 case CONST: { // (CONST (id_1 ... id_n) type) or (CONST id type) 00279 if(e.arity() == 3) { 00280 Type t(d_vc->parseExpr(e[2])); 00281 vector<Expr> vars; 00282 if(e[1].getKind() == RAW_LIST) 00283 vars = e[1].getKids(); 00284 else 00285 vars.push_back(e[1]); 00286 for(vector<Expr>::iterator i=vars.begin(), iend=vars.end(); i!=iend; ++i) { 00287 if((*i).getKind() != ID) 00288 throw EvalException("Constant name must be an identifier: " 00289 +i->toString()); 00290 } 00291 if (t.isFunction()) { 00292 for(vector<Expr>::iterator i=vars.begin(), iend=vars.end(); 00293 i!=iend; ++i) { 00294 Op op = d_vc->createOp((*i)[0].getString(), t); 00295 TRACE("commands", "evaluateNext: declare new uninterpreted function: ", 00296 op, ""); 00297 } 00298 } 00299 else { 00300 for(vector<Expr>::iterator i=vars.begin(), iend=vars.end(); 00301 i!=iend; ++i) { 00302 // Add to variable list 00303 Expr v = d_vc->varExpr((*i)[0].getString(), t); 00304 TRACE_MSG("commands", "** [commands] Declare new variable"); 00305 TRACE("commands verbose", "evaluateNext: declare new UCONST: ", 00306 v, ""); 00307 } 00308 } 00309 } else if(e.arity() == 4) { // Constant definition (CONST id type def) 00310 TRACE_MSG("commands", "** [commands] Define new constant"); 00311 // Set the type for later typechecking 00312 DebugAssert(e[1].getKind() == ID, "Expected ID kind"); 00313 Type t(d_vc->parseExpr(e[2])); 00314 Expr def(d_vc->parseExpr(e[3])); 00315 00316 if(t.isFunction()) { 00317 d_vc->createOp(e[1][0].getString(), t, def); 00318 TRACE("commands verbose", "evaluateNext: define new function: ", 00319 e[1][0].getString(), ""); 00320 } else { 00321 d_vc->varExpr(e[1][0].getString(), t, def); 00322 TRACE("commands verbose", "evaluateNext: define new variable: ", 00323 e[1][0].getString(), ""); 00324 } 00325 } else 00326 throw EvalException("Wrong number of arguments in CONST: "+e.toString()); 00327 break; 00328 } 00329 case DEFUN: { // (DEFUN name ((x y z type1) ... ) resType [ body ]) 00330 if(e.arity() != 5 && e.arity() != 4) 00331 throw EvalException 00332 ("DEFUN requires 3 or 4 arguments:" 00333 " (DEFUN f (args) type [ body ]):\n\n " 00334 +e.toString()); 00335 if(e[2].getKind() != RAW_LIST) 00336 throw EvalException 00337 ("2nd argument of DEFUN must be a list of arguments:\n\n " 00338 +e.toString()); 00339 00340 // Build a CONST declaration and parse it recursively 00341 00342 // Build the function type 00343 vector<Expr> argTps; 00344 for(Expr::iterator i=e[2].begin(), iend=e[2].end(); i!=iend; ++i) { 00345 if(i->getKind() != RAW_LIST || i->arity() < 2) 00346 throw EvalException 00347 ("DEFUN: bad argument declaration:\n\n "+i->toString() 00348 +"\n\nIn the following statement:\n\n " 00349 +e.toString()); 00350 Expr tp((*i)[i->arity()-1]); 00351 for(int j=0, jend=i->arity()-1; j<jend; ++j) 00352 argTps.push_back(tp); 00353 } 00354 argTps.push_back(e[3]); 00355 Expr fnType = d_vc->listExpr("ARROW", argTps); 00356 Expr newDecl; // The resulting transformed declaration 00357 if(e.arity() == 5) { 00358 // Build the LAMBDA expression 00359 Expr lambda(d_vc->listExpr("LAMBDA", e[2], e[4])); 00360 // Construct the (CONST name fnType lambda) declaration 00361 newDecl = d_vc->listExpr("CONST", e[1], fnType, lambda); 00362 } else { 00363 newDecl = d_vc->listExpr("CONST", e[1], fnType); 00364 } 00365 // Parse the new declaration 00366 return evaluateCommand(newDecl); 00367 break; 00368 } 00369 case TYPEDEF: { 00370 if (e.arity() == 2) { 00371 // Datatype command 00372 DebugAssert(e.arity() == 2, "Bad TYPEDEF"); 00373 Expr res = d_vc->parseExpr(e[1]); 00374 // convert res to vectors 00375 00376 Expr eNames = res[0]; 00377 Expr eCons = res[1]; 00378 Expr eSel = res[2]; 00379 Expr eTypes = res[3]; 00380 00381 vector<string> names; 00382 vector<vector<string> > constructors(eNames.arity()); 00383 vector<vector<vector<string> > > selectors(eNames.arity()); 00384 vector<vector<vector<Expr> > > types(eNames.arity()); 00385 00386 int i, j, k; 00387 for (i = 0; i < eNames.arity(); ++i) { 00388 names.push_back(eNames[i].getString()); 00389 selectors[i].resize(eSel[i].arity()); 00390 types[i].resize(eTypes[i].arity()); 00391 for (j = 0; j < eCons[i].arity(); ++j) { 00392 constructors[i].push_back(eCons[i][j].getString()); 00393 for (k = 0; k < eSel[i][j].arity(); ++k) { 00394 selectors[i][j].push_back(eSel[i][j][k].getString()); 00395 types[i][j].push_back(eTypes[i][j][k]); 00396 } 00397 } 00398 } 00399 00400 vector<Type> returnTypes; 00401 d_vc->dataType(names, constructors, selectors, types, returnTypes); 00402 break; 00403 } 00404 DebugAssert(e.arity() == 3, "Bad TYPEDEF"); 00405 Expr def(d_vc->parseExpr(e[2])); 00406 Type t = d_vc->createType(e[1][0].getString(), def); 00407 TRACE("commands", "evaluateNext: declare new TYPEDEF: ", t, ""); 00408 } 00409 break; 00410 case TYPE: { 00411 if(e.arity() < 2) 00412 throw EvalException("Bad TYPE declaration: "+e.toString()); 00413 Expr::iterator i=e.begin(), iend=e.end(); 00414 ++i; // Skip "TYPE" symbol 00415 for(; i!=iend; ++i) { 00416 if(i->getKind() != ID) 00417 throw EvalException("Type name must be an identifier: "+i->toString()); 00418 Type t = d_vc->createType((*i)[0].getString()); 00419 TRACE("commands", "evaluateNext: declare new TYPEDECL: ", t, ""); 00420 } 00421 } 00422 break; 00423 case ASSERT: { 00424 if(e.arity() != 2) 00425 throw EvalException("ASSERT requires exactly one argument, but is given " 00426 +int2string(e.arity()-1)+":\n "+e.toString()); 00427 TRACE_MSG("commands", "** [commands] Asserting formula"); 00428 d_vc->assertFormula(d_vc->parseExpr(e[1])); 00429 break; 00430 } 00431 case QUERY: { 00432 if(e.arity() != 2) 00433 throw EvalException("QUERY requires exactly one argument, but is given " 00434 +int2string(e.arity()-1)+":\n "+e.toString()); 00435 TRACE_MSG("commands", "** [commands] Query formula"); 00436 QueryResult qres = d_vc->query(d_vc->parseExpr(e[1])); 00437 if (qres == UNKNOWN && d_vc->getFlags()["unknown-check-model"].getBool()) 00438 qres = d_vc->tryModelGeneration(); 00439 reportResult(qres); 00440 if (qres == INVALID) { 00441 if (d_vc->getFlags()["counterexample"].getBool()) { 00442 printCounterExample(); 00443 } 00444 if (d_vc->getFlags()["model"].getBool()) { 00445 printModel(); 00446 } 00447 } 00448 break; 00449 } 00450 case CHECKSAT: { 00451 QueryResult qres; 00452 TRACE_MSG("commands", "** [commands] CheckSat"); 00453 if (e.arity() == 1) { 00454 qres = d_vc->checkUnsat(d_vc->trueExpr()); 00455 } 00456 else if (e.arity() == 2) { 00457 qres = d_vc->checkUnsat(d_vc->parseExpr(e[1])); 00458 } 00459 else { 00460 throw EvalException("CHECKSAT requires no more than one argument, but is given " 00461 +int2string(e.arity()-1)+":\n "+e.toString()); 00462 } 00463 if (qres == UNKNOWN && !d_vc->getFlags()["translate"].getBool() && d_vc->getFlags()["unknown-check-model"].getBool()) 00464 qres = d_vc->tryModelGeneration(); 00465 reportResult(qres, false); 00466 if (qres == SATISFIABLE) { 00467 if (d_vc->getFlags()["counterexample"].getBool()) { 00468 printCounterExample(); 00469 } 00470 if (d_vc->getFlags()["model"].getBool()) { 00471 printModel(); 00472 } 00473 } 00474 // {//for debug only by yeting 00475 // Proof p = d_vc->getProof(); 00476 // if (d_vc->getFlags()["printResults"].getBool()) { 00477 // cout << p << endl; 00478 // cout << flush; 00479 // } 00480 // } 00481 00482 00483 break; 00484 } 00485 case CONTINUE: { 00486 if (e.arity() != 1) { 00487 throw EvalException("CONTINUE takes no arguments"); 00488 } 00489 TRACE_MSG("commands", "** [commands] Continue"); 00490 QueryResult qres = d_vc->checkContinue(); 00491 if (d_vc->getFlags()["printResults"].getBool()) { 00492 switch (qres) { 00493 case VALID: 00494 cout << "No more models found." << endl; 00495 break; 00496 case INVALID: 00497 cout << "Model found" << endl; 00498 break; 00499 case ABORT: 00500 cout << "Unknown: resource limit exhausted." << endl; 00501 break; 00502 case UNKNOWN: { 00503 // Vector of reasons in case of incomplete result 00504 vector<string> reasons; 00505 IF_DEBUG(bool b =) d_vc->incomplete(reasons); 00506 DebugAssert(b, "Expected incompleteness"); 00507 cout << "Unknown.\n\n"; 00508 cout << "CVC3 was incomplete in this example due to:"; 00509 for(vector<string>::iterator i=reasons.begin(), iend=reasons.end(); 00510 i!=iend; ++i) 00511 cout << "\n * " << (*i); 00512 cout << endl << endl; 00513 break; 00514 } 00515 default: 00516 FatalAssert(false, "Unexpected case"); 00517 } 00518 cout << flush; 00519 } 00520 break; 00521 } 00522 case RESTART: { 00523 if(e.arity() != 2) 00524 throw EvalException("RESTART requires exactly one argument, but is given " 00525 +int2string(e.arity()-1)+":\n "+e.toString()); 00526 TRACE_MSG("commands", "** [commands] Restart formula"); 00527 QueryResult qres = d_vc->restart(d_vc->parseExpr(e[1])); 00528 reportResult(qres); 00529 if (qres == INVALID) { 00530 if (d_vc->getFlags()["counterexample"].getBool()) { 00531 printCounterExample(); 00532 } 00533 if (d_vc->getFlags()["model"].getBool()) { 00534 printModel(); 00535 } 00536 } 00537 break; 00538 } 00539 case TRANSFORM: { 00540 if(e.arity() != 2) 00541 throw EvalException 00542 ("TRANSFORM requires exactly one argument, but is given " 00543 +int2string(e.arity()-1)+":\n "+e.toString()); 00544 TRACE_MSG("commands", "** [commands] Transforming expression"); 00545 Expr ee = d_vc->parseExpr(e[1]); 00546 e = d_vc->simplify(ee); 00547 if (d_vc->getFlags()["printResults"].getBool()) d_vc->printExpr(e); 00548 break; 00549 } 00550 case PRINT: 00551 if(e.arity() != 2) 00552 throw EvalException 00553 ("PRINT requires exactly one argument, but is given " 00554 +int2string(e.arity()-1)+":\n "+e.toString()); 00555 d_vc->printExpr(d_vc->parseExpr(e[1])); 00556 break; 00557 case PUSH: 00558 case POP: 00559 case PUSH_SCOPE: 00560 case POP_SCOPE: { 00561 int arg; 00562 if (e.arity() == 1) arg = 1; 00563 else { 00564 DebugAssert(e.arity() == 2 && e[1].getKind() == RATIONAL_EXPR, 00565 "Bad argument to "+kindName); 00566 arg = e[1].getRational().getInt(); 00567 if(arg <= 0) 00568 throw EvalException("Argument to PUSH or POP is <= 0"); 00569 } 00570 if (kind == PUSH) { 00571 for (int i = 0; i < arg; i++) { 00572 d_vc->push(); 00573 } 00574 } 00575 else if (kind == POP) { 00576 if(arg > d_vc->stackLevel()) 00577 throw EvalException("Argument to POP is out of range:\n" 00578 " current stack level = " 00579 +int2string(d_vc->stackLevel()) 00580 +"\n argument = " 00581 +int2string(arg)); 00582 for (int i = 0; i < arg; i++) { 00583 d_vc->pop(); 00584 } 00585 } 00586 else if (kind == PUSH_SCOPE) { 00587 for (int i = 0; i < arg; i++) { 00588 d_vc->pushScope(); 00589 } 00590 } 00591 else if (kind == POP_SCOPE) { 00592 if(arg >= d_vc->scopeLevel()) 00593 throw EvalException("Argument to POP_SCOPE is out of range:\n" 00594 " current scope = " 00595 +int2string(d_vc->scopeLevel()) 00596 +"\n argument = " 00597 +int2string(arg)); 00598 for (int i = 0; i < arg; i++) { 00599 d_vc->popScope(); 00600 } 00601 } 00602 break; 00603 } 00604 case POPTO: 00605 case POPTO_SCOPE: { 00606 int arg; 00607 if (e.arity() == 1) arg = 0; 00608 else { 00609 DebugAssert(e.arity() == 2 && e[1].getKind() == RATIONAL_EXPR, 00610 "Bad argument to "+kindName); 00611 arg = e[1].getRational().getInt(); 00612 } 00613 if (kind == POPTO) { 00614 d_vc->popto(arg); 00615 } 00616 else { 00617 d_vc->poptoScope(arg); 00618 } 00619 break; 00620 } 00621 case RESET: { 00622 throw ResetException(); 00623 break; 00624 } 00625 case WHERE: 00626 case ASSERTIONS: 00627 case ASSUMPTIONS: 00628 { 00629 vector<Expr> assertions; 00630 ExprMap<bool> skolemAxioms; 00631 ExprMap<bool> visited; 00632 00633 d_vc->getAssumptions(assertions); 00634 00635 if (d_vc->getFlags()["printResults"].getBool()) { 00636 cout << "Current stack level is " << d_vc->stackLevel() 00637 << " (scope " << d_vc->scopeLevel() << ")." << endl; 00638 if (assertions.size() == 0) { 00639 cout << "% No active assumptions\n"; 00640 } else { 00641 cout << "% Active assumptions:\n"; 00642 for (unsigned i = 0; i < assertions.size(); i++) { 00643 cout << "ASSERT " << assertions[i] << ";" << endl; 00644 findAxioms(assertions[i], skolemAxioms, visited); 00645 } 00646 ExprMap<bool>::iterator it = skolemAxioms.begin(); 00647 ExprMap<bool>::iterator end = skolemAxioms.end(); 00648 if (it != end) { 00649 cout << "% Skolemization axioms" << endl; 00650 for(; it!=end; ++it) 00651 cout << "ASSERT " << skolemizeAx((*it).first) << ";" << endl; 00652 } 00653 } 00654 cout << endl; 00655 } 00656 break; 00657 } 00658 case COUNTEREXAMPLE: { 00659 if (d_vc->getFlags()["printResults"].getBool()) { 00660 printCounterExample(); 00661 } 00662 break; 00663 } 00664 case COUNTERMODEL: { 00665 if (d_vc->getFlags()["printResults"].getBool()) { 00666 try { 00667 printModel(); 00668 } catch (Exception& e) { 00669 throw EvalException(e.toString()); 00670 } 00671 } 00672 break; 00673 } 00674 case TRACE: { // Set a trace flag 00675 #ifdef _CVC3_DEBUG_MODE 00676 if(e.arity() != 2) 00677 throw EvalException("TRACE takes exactly one string argument"); 00678 if(!e[1].isString()) 00679 throw EvalException("TRACE requires a string argument"); 00680 debugger.traceFlag(e[1].getString()) = true; 00681 #endif 00682 } 00683 break; 00684 case UNTRACE: { // Unset a trace flag 00685 #ifdef _CVC3_DEBUG_MODE 00686 if(e.arity() != 2) 00687 throw EvalException("UNTRACE takes exactly one string argument"); 00688 if(!e[1].isString()) 00689 throw EvalException("UNTRACE requires a string argument"); 00690 debugger.traceFlag(e[1].getString()) = false; 00691 #endif 00692 } 00693 break; 00694 case OPTION: { 00695 if(e.arity() != 3) 00696 throw EvalException("OPTION takes exactly two arguments " 00697 "(name and value of a flag)"); 00698 if(!e[1].isString()) 00699 throw EvalException("OPTION: flag name must be a string"); 00700 CLFlags& flags = d_vc->getFlags(); 00701 string name(e[1].getString()); 00702 vector<string> names; 00703 size_t n = flags.countFlags(name, names); 00704 if(n != 1) 00705 throw EvalException("OPTION: found "+int2string(n) 00706 +" flags matching "+name 00707 +".\nThe flag name must uniquely resolve."); 00708 name = names[0]; 00709 const CLFlag& flag(flags[name]); 00710 // If the flag is set on the command line, ignore it 00711 if(flag.modified()) break; 00712 switch(flag.getType()) { 00713 case CLFLAG_BOOL: 00714 if(!(e[2].isRational() && e[2].getRational().isInteger())) 00715 throw EvalException("OPTION: flag "+name 00716 +" expects a boolean value (0 or 1"); 00717 flags.setFlag(name, e[2].getRational().getInt() != 0); 00718 break; 00719 case CLFLAG_INT: 00720 if(!(e[2].isRational() && e[2].getRational().isInteger())) 00721 throw EvalException("OPTION: flag "+name+" expects an integer value"); 00722 flags.setFlag(name, e[2].getRational().getInt()); 00723 break; 00724 case CLFLAG_STRING: 00725 if(!e[2].isString()) 00726 throw EvalException("OPTION: flag "+name+" expects a string value"); 00727 flags.setFlag(name, e[2].getString()); 00728 break; 00729 default: 00730 throw EvalException("OPTION: the type of flag "+name 00731 +" is not supported by the OPTION commnand"); 00732 break; 00733 } 00734 d_vc->reprocessFlags(); 00735 } 00736 break; 00737 case GET_VALUE: { 00738 ExprMap<Expr> m; 00739 d_vc->getConcreteModel(m); 00740 00741 if (d_vc->getFlags()["printResults"].getBool()) { 00742 cout << "("; 00743 } 00744 for(int i = 0; i < e[1].arity(); ++i) { 00745 Expr res = d_vc->getValue(d_vc->parseExpr(e[1][i])); 00746 if (d_vc->getFlags()["printResults"].getBool()) { 00747 cout << res; 00748 if(i < e[1].arity() - 1) { 00749 cout << endl; 00750 } 00751 } 00752 } 00753 if (d_vc->getFlags()["printResults"].getBool()) { 00754 cout << ")" << endl; 00755 } 00756 break; 00757 } 00758 case GET_ASSIGNMENT: { 00759 ExprMap<Expr> m; 00760 d_vc->getConcreteModel(m); 00761 00762 Expr res = d_vc->getAssignment(); 00763 if (d_vc->getFlags()["printResults"].getBool()) { 00764 cout << res << endl; 00765 cout << flush; 00766 } 00767 break; 00768 } 00769 case DUMP_PROOF: { 00770 Proof p = d_vc->getProof(); 00771 if (d_vc->getFlags()["printResults"].getBool()) { 00772 cout << p << endl; 00773 cout << flush; 00774 } 00775 break; 00776 } 00777 case DUMP_ASSUMPTIONS: { // Assumption tracking 00778 vector<Expr> assertions; 00779 00780 bool b = d_vc->inconsistent(assertions); 00781 DebugAssert(b, "not inconsistent"); 00782 00783 if (d_vc->getFlags()["printResults"].getBool()) { 00784 if(assertions.size() == 0) { 00785 cout << "% No relevant assumptions\n"; 00786 } else { 00787 cout << "% Relevant assumptions:\n"; 00788 for (unsigned i = 0; i < assertions.size(); i++) { 00789 cout << Expr(ASSERT, assertions[i]) << "\n"; 00790 } 00791 } 00792 cout << endl << flush; 00793 } 00794 break; 00795 } 00796 case DUMP_TCC: { 00797 const Expr& tcc = d_vc->getTCC(); 00798 00799 if (d_vc->getFlags()["printResults"].getBool()) { 00800 if(tcc.isNull()) 00801 cout << "% No TCC is avaialble" << endl; 00802 else 00803 cout << "% TCC for the last declaration, ASSERT, or QUERY:\n\n" 00804 << tcc << endl; 00805 } 00806 break; 00807 } 00808 case DUMP_TCC_ASSUMPTIONS: { 00809 vector<Expr> assertions; 00810 d_vc->getAssumptionsTCC(assertions); 00811 if (d_vc->getFlags()["printResults"].getBool()) { 00812 if(assertions.size() == 0) { 00813 cout << "% No relevant assumptions\n"; 00814 } else { 00815 cout << "% Relevant assumptions for the last TCC:\n"; 00816 for (unsigned i = 0; i < assertions.size(); i++) { 00817 cout << Expr(ASSERT, assertions[i]) << "\n"; 00818 } 00819 } 00820 cout << endl << flush; 00821 } 00822 break; 00823 } 00824 case DUMP_TCC_PROOF: { 00825 const Proof& tcc = d_vc->getProofTCC(); 00826 if (d_vc->getFlags()["printResults"].getBool()) { 00827 if(tcc.isNull()) 00828 cout << "% No TCC is avaialble" << endl; 00829 else 00830 cout << "% Proof of TCC for the last declaration, ASSERT, or QUERY:\n\n" 00831 << tcc << endl; 00832 } 00833 break; 00834 } 00835 case DUMP_CLOSURE: { 00836 const Expr& cl = d_vc->getClosure(); 00837 if (d_vc->getFlags()["printResults"].getBool()) { 00838 if(cl.isNull()) 00839 cout << "% No closure is avaialble" << endl; 00840 else 00841 cout << "% Closure for the last QUERY:\n\n" << cl << endl; 00842 } 00843 break; 00844 } 00845 case DUMP_CLOSURE_PROOF: { 00846 const Proof& cl = d_vc->getProofClosure(); 00847 if (d_vc->getFlags()["printResults"].getBool()) { 00848 if(cl.isNull()) 00849 cout << "% No closure is avaialble" << endl; 00850 else 00851 cout << "% Proof of closure for the last QUERY:\n\n" << cl << endl; 00852 } 00853 break; 00854 } 00855 case ECHO: 00856 if(e.arity() != 2) 00857 throw EvalException("ECHO: wrong number of arguments: " 00858 + e.toString()); 00859 if(!e[1].isString()) 00860 throw EvalException("ECHO: the argument must be a string: " 00861 +e.toString()); 00862 if (d_vc->getFlags()["printResults"].getBool()) { 00863 cout << e[1].getString(); 00864 cout << endl << flush; 00865 } 00866 break; 00867 case SEQ: { 00868 Expr::iterator i=e.begin(), iend=e.end(); 00869 ++i; // Skip "SEQ" symbol 00870 bool success = true; 00871 for(; i!=iend; ++i) { 00872 try { 00873 success = success && evaluateCommand(*i); 00874 } catch(ResetException& e) { 00875 if (++i == iend) throw e; 00876 throw EvalException("RESET can only be the last command in a sequence"); 00877 } 00878 } 00879 return success; 00880 } 00881 case ARITH_VAR_ORDER: { 00882 if (e.arity() <= 2) 00883 throw EvalException("ARITH_VAR_ORDER takes at least two arguments"); 00884 Expr smaller; 00885 Expr bigger = d_vc->parseExpr(e[1]); 00886 for (int i = 2; i < e.arity(); i ++) { 00887 smaller = bigger; 00888 bigger = d_vc->parseExpr(e[i]); 00889 if (!d_vc->addPairToArithOrder(smaller, bigger)) 00890 throw EvalException("ARITH_VAR_ORDER only takes arithmetic terms"); 00891 } 00892 return true; 00893 } 00894 case ANNOTATION: { 00895 for (int i = 1; i < e.arity(); ++i) { 00896 if (e[i].arity() == 1) { 00897 d_vc->logAnnotation(Expr(ANNOTATION, e[i][0])); 00898 } 00899 else { 00900 DebugAssert(e[i].arity() == 2, "Expected arity 2"); 00901 d_vc->logAnnotation(Expr(ANNOTATION, e[i][0], e[i][1])); 00902 } 00903 } 00904 break; 00905 } 00906 case INCLUDE: { // read in the specified file 00907 if(e.arity() != 2) 00908 throw EvalException("INCLUDE takes exactly one string argument"); 00909 if(!e[1].isString()) 00910 throw EvalException("INCLUDE requires a string argument"); 00911 ifstream fs; 00912 fs.open(e[1].getString().c_str(),ios::in); 00913 if(!fs.is_open()) { 00914 fs.close(); 00915 throw EvalException("File "+e[1].getString()+" does not exist"); 00916 } 00917 fs.close(); 00918 d_vc->loadFile(e[1].getString(), 00919 d_vc->getEM()->getInputLang(), 00920 d_vc->getFlags()["interactive"].getBool(), 00921 true /* nested call */); 00922 break; 00923 } 00924 case HELP: 00925 cout << "Use the -help command-line option for help." << endl; 00926 break; 00927 case DUMP_SIG: 00928 case DBG: 00929 case SUBSTITUTE: 00930 case GET_CHILD: 00931 case GET_TYPE: 00932 case CHECK_TYPE: 00933 case FORGET: 00934 case CALL: 00935 default: 00936 throw EvalException("Unknown command: " + e.toString()); 00937 break; 00938 } 00939 TRACE_MSG("commands", "evaluateCommand => true }"); 00940 return true; 00941 } 00942 00943 00944 void VCCmd::processCommands() 00945 { 00946 bool error(false); 00947 try { 00948 bool success(true); 00949 while(success) { 00950 try { 00951 success = evaluateNext(); 00952 } catch (ResetException& e) { 00953 if (d_calledFromParser) { 00954 throw EvalException("RESET not supported within INCLUDEd file"); 00955 } 00956 d_parser->reset(); 00957 d_vc->reset(); 00958 success = true; 00959 } catch (EvalException& e) { 00960 error= true; 00961 cerr << "*** Eval Error:\n " << e << endl; 00962 } 00963 } 00964 00965 } 00966 00967 catch(Exception& e) { 00968 cerr << "*** Fatal exception:\n" << e << endl; 00969 error= true; 00970 } catch(...) { 00971 cerr << "*** Unknown fatal exception caught" << endl; 00972 error= true; 00973 } 00974 00975 if (error) 00976 { 00977 d_parser->printLocation(cerr); 00978 cerr << ": this is the location of the error" << endl; 00979 } 00980 }