00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "theory_uf.h"
00022 #include "uf_proof_rules.h"
00023 #include "typecheck_exception.h"
00024 #include "parser_exception.h"
00025 #include "smtlib_exception.h"
00026 #include "command_line_flags.h"
00027 #include "theory_core.h"
00028 #include "translator.h"
00029
00030 #include "theory_records.h"
00031
00032
00033 using namespace std;
00034 using namespace CVC3;
00035
00036
00037
00038
00039
00040
00041
00042 TheoryUF::TheoryUF(TheoryCore* core)
00043 : Theory(core, "Uninterpreted Functions"),
00044 d_applicationsInModel(core->getFlags()["applications"].getBool()),
00045 d_funApplications(core->getCM()->getCurrentContext()),
00046 d_funApplicationsIdx(core->getCM()->getCurrentContext(), 0)
00047
00048 {
00049 d_rules = createProofRules();
00050
00051
00052 getEM()->newKind(TRANS_CLOSURE, "_TRANS_CLOSURE");
00053 getEM()->newKind(OLD_ARROW, "_OLD_ARROW", true);
00054
00055 vector<int> kinds;
00056
00057 kinds.push_back(TYPEDECL);
00058 kinds.push_back(LAMBDA);
00059 kinds.push_back(ARROW);
00060 kinds.push_back(OLD_ARROW);
00061 kinds.push_back(UFUNC);
00062 kinds.push_back(TRANS_CLOSURE);
00063
00064 registerTheory(this, kinds);
00065 }
00066
00067
00068 TheoryUF::~TheoryUF() {
00069 delete d_rules;
00070 }
00071
00072
00073
00074
00075
00076 void TheoryUF::assertFact(const Theorem& e)
00077 {
00078 const Expr& expr = e.getExpr();
00079 switch (expr.getKind()) {
00080 case NOT:
00081 break;
00082 case APPLY:
00083 if (expr.getOpExpr().computeTransClosure()) {
00084 enqueueFact(d_rules->relToClosure(e));
00085 }
00086 else if (expr.getOpKind() == TRANS_CLOSURE) {
00087
00088 DebugAssert(expr.isApply(), "Should be apply");
00089 Expr rel = resolveID(expr.getOpExpr().getName());
00090 DebugAssert(!rel.isNull(), "Expected known identifier");
00091 DebugAssert(rel.isSymbol() && rel.getKind()==UFUNC && expr.arity()==2,
00092 "Unexpected use of transitive closure: "+expr.toString());
00093
00094
00095 ExprMap<TCMapPair*>::iterator i = d_transClosureMap.find(rel);
00096 TCMapPair* pTable;
00097 if (i == d_transClosureMap.end()) {
00098 pTable = new TCMapPair();
00099 d_transClosureMap[rel] = pTable;
00100 }
00101 else {
00102 pTable = (*i).second;
00103 }
00104
00105 ExprMap<CDList<Theorem>*>::iterator i2 = pTable->appearsFirstMap.find(expr[0]);
00106 CDList<Theorem>* pList;
00107 if (i2 == pTable->appearsFirstMap.end()) {
00108 pList = new(true) CDList<Theorem>(theoryCore()->getCM()->getCurrentContext());
00109 pTable->appearsFirstMap[expr[0]] = pList;
00110 }
00111 else {
00112 pList = (*i2).second;
00113 }
00114 pList->push_back(e);
00115
00116 i2 = pTable->appearsSecondMap.find(expr[1]);
00117 if (i2 == pTable->appearsSecondMap.end()) {
00118 pList = new(true) CDList<Theorem>(theoryCore()->getCM()->getCurrentContext());
00119 pTable->appearsSecondMap[expr[1]] = pList;
00120 }
00121 else {
00122 pList = (*i2).second;
00123 }
00124 pList->push_back(e);
00125
00126
00127 size_t s,l;
00128 i2 = pTable->appearsFirstMap.find(expr[1]);
00129 if (i2 != pTable->appearsFirstMap.end()) {
00130 pList = (*i2).second;
00131 s = pList->size();
00132 for (l = 0; l < s; ++l) {
00133 enqueueFact(d_rules->relTrans(e,(*pList)[l]));
00134 }
00135 }
00136
00137 i2 = pTable->appearsSecondMap.find(expr[0]);
00138 if (i2 != pTable->appearsSecondMap.end()) {
00139 pList = (*i2).second;
00140 s = pList->size();
00141 for (l = 0; l < s; ++l) {
00142 enqueueFact(d_rules->relTrans((*pList)[l],e));
00143 }
00144 }
00145 }
00146 break;
00147 default:
00148 break;
00149 }
00150 }
00151
00152
00153 void TheoryUF::checkSat(bool fullEffort)
00154 {
00155
00156 for(; d_funApplicationsIdx < d_funApplications.size();
00157 d_funApplicationsIdx = d_funApplicationsIdx + 1) {
00158 const Expr& e = d_funApplications[d_funApplicationsIdx];
00159 if(e.getOp().getExpr().isLambda()) {
00160 IF_DEBUG(debugger.counter("Expanded lambdas (checkSat)")++;)
00161 enqueueFact(d_rules->applyLambda(e));
00162 }
00163 }
00164 }
00165
00166
00167 Theorem TheoryUF::rewrite(const Expr& e)
00168 {
00169 if (e.isApply()) {
00170 const Expr& op = e.getOpExpr();
00171 int opKind = op.getKind();
00172 switch(opKind) {
00173 case LAMBDA: {
00174 Theorem res = d_rules->applyLambda(e);
00175
00176 res = transitivityRule(res, simplify(res.getRHS()));
00177 IF_DEBUG(debugger.counter("Expanded lambdas")++;)
00178 return res;
00179 }
00180 default:
00181 if (e.getType().isBool()) return reflexivityRule(e);
00182 else return rewriteCC(e);
00183 }
00184 }
00185 else {
00186 e.setRewriteNormal();
00187 return reflexivityRule(e);
00188 }
00189 }
00190
00191
00192 void TheoryUF::setup(const Expr& e)
00193 {
00194 if (e.getKind() != APPLY) return;
00195
00196
00197
00198
00199
00200
00201 setupCC(e);
00202
00203
00204 TRACE("model", "TheoryUF: add function application ", e, "");
00205 d_funApplications.push_back(e);
00206 }
00207
00208
00209 void TheoryUF::update(const Theorem& e, const Expr& d)
00210 {
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 const Theorem& dEQdsig = d.getSig();
00245 if (!dEQdsig.isNull()) {
00246 const Expr& dsig = dEQdsig.getRHS();
00247 Theorem thm = updateHelper(d);
00248 const Expr& sigNew = thm.getRHS();
00249 if (sigNew == dsig) {
00250
00251 return;
00252 }
00253 dsig.setRep(Theorem());
00254 const Theorem& repEQsigNew = sigNew.getRep();
00255 if (!repEQsigNew.isNull()) {
00256 d.setSig(Theorem());
00257 enqueueFact(transitivityRule(repEQsigNew, symmetryRule(thm)));
00258 }
00259 else if (d.getType().isBool()) {
00260 d.setSig(Theorem());
00261 enqueueFact(thm);
00262 }
00263 else {
00264 int k, ar(d.arity());
00265 for (k = 0; k < ar; ++k) {
00266 if (sigNew[k] != dsig[k]) {
00267 sigNew[k].addToNotify(this, d);
00268 }
00269 }
00270 d.setSig(thm);
00271 sigNew.setRep(thm);
00272 if (dsig != sigNew && d.isApply() && findExpr(d).isTrue()) {
00273 if (d.getOpExpr().computeTransClosure()) {
00274 thm = getCommonRules()->iffTrueElim(transitivityRule(symmetryRule(thm),
00275 find(d)));
00276 enqueueFact(d_rules->relToClosure(thm));
00277 }
00278 else if (d.getOpKind() == TRANS_CLOSURE) {
00279 thm = getCommonRules()->iffTrueElim(transitivityRule(symmetryRule(thm),
00280 find(d)));
00281 enqueueFact(thm);
00282 }
00283 }
00284 }
00285 }
00286 }
00287
00288
00289 void TheoryUF::checkType(const Expr& e)
00290 {
00291 switch (e.getKind()) {
00292 case ARROW: {
00293 if (e.arity() < 2) throw Exception
00294 ("Function type needs at least two arguments"
00295 +e.toString());
00296 Expr::iterator i = e.begin(), iend = e.end();
00297 for (; i != iend; ) {
00298 Type t(*i);
00299 ++i;
00300 if (i == iend && t.isBool()) break;
00301 if (t.isBool()) throw Exception
00302 ("Function argument types must be non-Boolean: "
00303 +e.toString());
00304 if (t.isFunction()) throw Exception
00305 ("Function domain or range types cannot be functions: "
00306 +e.toString());
00307 }
00308 break;
00309 }
00310 case TYPEDECL: {
00311 break;
00312 }
00313 default:
00314 DebugAssert(false, "Unexpected kind in TheoryUF::checkType"
00315 +getEM()->getKindName(e.getKind()));
00316 }
00317 }
00318
00319
00320 Cardinality TheoryUF::finiteTypeInfo(Expr& e, Unsigned& n,
00321 bool enumerate, bool computeSize)
00322 {
00323 DebugAssert(e.getKind() == ARROW,
00324 "Unexpected kind in TheoryUF::finiteTypeInfo");
00325 Expr::iterator i = e.begin(), iend = e.end();
00326 Cardinality card = CARD_FINITE, cardTmp;
00327 Unsigned thisSize = 1, size;
00328 bool getSize = enumerate || computeSize;
00329 for (; i != iend; ) {
00330 Expr e2 = (*i);
00331 cardTmp = theoryOf(e2)->finiteTypeInfo(e2, size, getSize, false);
00332 if (cardTmp == CARD_INFINITE) {
00333 return CARD_INFINITE;
00334 }
00335 else if (cardTmp == CARD_UNKNOWN) {
00336 card = CARD_UNKNOWN;
00337 getSize = false;
00338
00339 }
00340 else if (getSize) {
00341 thisSize = thisSize * size;
00342
00343 if (thisSize > 1000000) thisSize = 0;
00344 if (thisSize == 0) {
00345 getSize = false;
00346 }
00347 }
00348 }
00349
00350 if (card == CARD_FINITE) {
00351
00352 if (enumerate) {
00353
00354 e = Expr();
00355 }
00356
00357 if (computeSize) {
00358 n = thisSize;
00359 }
00360
00361 }
00362
00363 return card;
00364 }
00365
00366
00367 void TheoryUF::computeType(const Expr& e)
00368 {
00369 switch (e.getKind()) {
00370 case LAMBDA: {
00371 vector<Type> args;
00372 const vector<Expr>& vars = e.getVars();
00373 DebugAssert(vars.size() > 0,
00374 "TheorySimulate::computeType("+e.toString()+")");
00375 for(vector<Expr>::const_iterator i=vars.begin(), iend=vars.end();
00376 i!=iend; ++i)
00377 args.push_back((*i).getType());
00378 e.setType(Type::funType(args, e.getBody().getType()));
00379 break;
00380 }
00381 case APPLY: {
00382 theoryOf(APPLY)->computeType(e);
00383 break;
00384 }
00385 case TRANS_CLOSURE: {
00386 DebugAssert(e.isSymbol(), "Expected symbol");
00387 Expr funExpr = resolveID(e.getName());
00388 if (funExpr.isNull()) {
00389 throw TypecheckException
00390 ("Attempt to take transitive closure of unknown id: "
00391 +e.getName());
00392 }
00393 Type funType = funExpr.getType();
00394 if(!funType.isFunction()) {
00395 throw TypecheckException
00396 ("Attempt to take transitive closure of non-function:\n\n"
00397 +funExpr.toString() + "\n\n which has type: "
00398 +funType.toString());
00399 }
00400 if(funType.arity()!=3) {
00401 throw TypecheckException
00402 ("Attempt to take transitive closure of non-binary function:\n\n"
00403 +funExpr.toString() + "\n\n which has type: "
00404 +funType.toString());
00405 }
00406 if (!funType[2].isBool()) {
00407 throw TypecheckException
00408 ("Attempt to take transitive closure of function:\n\n"
00409 +funExpr.toString() + "\n\n which does not return BOOLEAN");
00410 }
00411 e.setType(funType);
00412 break;
00413 }
00414 default:
00415 DebugAssert(false,"Unexpected type: "+e.toString());
00416 break;
00417 }
00418 }
00419
00420
00421 Type TheoryUF::computeBaseType(const Type& t) {
00422 const Expr& e = t.getExpr();
00423 switch(e.getKind()) {
00424 case ARROW: {
00425 DebugAssert(e.arity() > 0, "Expected non-empty ARROW");
00426 vector<Expr> kids;
00427 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
00428 kids.push_back(getBaseType(Type(*i)).getExpr());
00429 }
00430 return Type(Expr(e.getOp(), kids));
00431 }
00432 case TYPEDECL: return t;
00433 default:
00434 DebugAssert(false,
00435 "TheoryUF::computeBaseType("+t.toString()+")");
00436 return t;
00437 }
00438 }
00439
00440
00441 void TheoryUF::computeModelTerm(const Expr& e, std::vector<Expr>& v) {
00442 for(CDList<Expr>::const_iterator i=d_funApplications.begin(),
00443 iend=d_funApplications.end(); i!=iend; ++i) {
00444 if((*i).isApply() && (*i).getOp().getExpr() == e) {
00445
00446
00447 v.push_back(*i);
00448
00449
00450
00451 for(Expr::iterator j=(*i).begin(), jend=(*i).end(); j!=jend; ++j)
00452
00453 v.push_back(*j);
00454 }
00455 }
00456 }
00457
00458
00459 void TheoryUF::computeModel(const Expr& e, std::vector<Expr>& vars) {
00460
00461
00462
00463
00464
00465
00466 vars.push_back(e);
00467
00468 ExprHashMap<Expr> appls;
00469 for(CDList<Expr>::const_iterator i=d_funApplications.begin(),
00470 iend=d_funApplications.end(); i!=iend; ++i) {
00471 if((*i).isApply() && (*i).getOp().getExpr() == e) {
00472
00473 vector<Theorem> thms;
00474 vector<unsigned> changed;
00475 for(int j=0; j<(*i).arity(); ++j) {
00476 Theorem asst(getModelValue((*i)[j]));
00477 if(asst.getLHS()!=asst.getRHS()) {
00478 thms.push_back(asst);
00479 changed.push_back(j);
00480 }
00481 }
00482 Expr var;
00483 if(changed.size()>0) {
00484
00485
00486 Theorem subst = substitutivityRule(*i, changed, thms);
00487 assignValue(transitivityRule(symmetryRule(subst), getModelValue(*i)));
00488 var = subst.getRHS();
00489 } else
00490 var = *i;
00491 if(d_applicationsInModel) vars.push_back(var);
00492
00493 appls[var] = getModelValue(var).getRHS();
00494 }
00495 }
00496
00497 if(appls.size()==0) {
00498 assignValue(reflexivityRule(e));
00499 } else {
00500
00501 vector<Expr> args;
00502 Type tp(e.getType());
00503 static unsigned count(0);
00504 DebugAssert(tp.isFunction(), "TheoryUF::computeModel("+e.toString()
00505 +" : "+tp.toString()+")");
00506 for(int i=0, iend=tp.arity()-1; i<iend; ++i) {
00507 string str = "uf_"+int2string(count);
00508 Expr v = getEM()->newBoundVarExpr(str, int2string(count++));
00509 v.setType(tp[i]);
00510 args.push_back(v);
00511 }
00512 DebugAssert(args.size()>0, "TheoryUF::computeModel()");
00513 ExprHashMap<Expr>::iterator i=appls.begin(), iend=appls.end();
00514 DebugAssert(i!=iend, "TheoryUF::computeModel(): empty appls hash");
00515
00516 Expr res((*i).second); ++i;
00517 for(; i!=iend; ++i) {
00518
00519
00520
00521 if((*i).second == res) continue;
00522
00523
00524 Expr cond;
00525 vector<Expr> eqs;
00526 for(int j=0, jend=args.size(); j<jend; ++j)
00527 eqs.push_back(args[j].eqExpr((*i).first[j]));
00528 if(eqs.size()==1)
00529 cond = eqs[0];
00530 else
00531 cond = andExpr(eqs);
00532
00533 res = cond.iteExpr((*i).second, res);
00534 }
00535 res = lambdaExpr(args, res);
00536 assignValue(e, res);
00537 }
00538 }
00539
00540
00541 Expr TheoryUF::computeTCC(const Expr& e)
00542 {
00543 switch (e.getKind()) {
00544 case APPLY: {
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 vector<Expr> preds;
00566 preds.push_back(Theory::computeTCC(e));
00567 DebugAssert(e.isApply(), "Should be application");
00568 Expr op(e.getOp().getExpr());
00569 Type funType(op.getType());
00570 DebugAssert(funType.isFunction() || funType.isBool(),
00571 "TheoryUF::computeTCC(): funType = "
00572 +funType.toString());
00573 if(funType.isFunction()) {
00574 DebugAssert(funType.arity() == e.arity()+1,
00575 "TheoryUF::computeTCC(): funType = "
00576 +funType.toString()+"\n e = "+e.toString());
00577 for(int i=0, iend=e.arity(); i<iend; ++i) {
00578
00579
00580
00581 if(funType[i] != e[i].getType())
00582 preds.push_back(getTypePred(funType[i], e[i]));
00583 }
00584 }
00585
00586 while(op.getKind()==LETDECL) op = op[1];
00587
00588 if(op.isLambda()) {
00589 preds.push_back(Expr(lambdaExpr(op.getVars(),
00590 getTCC(op.getBody())).mkOp(),
00591 e.getKids()));
00592 }
00593 return rewriteAnd(andExpr(preds)).getRHS();
00594 }
00595 case LAMBDA:
00596 return trueExpr();
00597 default:
00598 DebugAssert(false,"Unexpected type: "+e.toString());
00599 return trueExpr();
00600 }
00601 }
00602
00603
00604
00605
00606
00607
00608 ExprStream& TheoryUF::print(ExprStream& os, const Expr& e) {
00609 switch(os.lang()) {
00610 case SIMPLIFY_LANG:
00611 switch(e.getKind()) {
00612 case OLD_ARROW:
00613 case ARROW:
00614 os<<"ERROR:ARROW:unsupported in Simplify\n";
00615 break;
00616 case LAMBDA: {
00617 os<<"ERROR:LAMBDA:unsupported in Simplify\n";
00618 break;
00619 }
00620 case TRANS_CLOSURE:
00621 os<<"ERROR:TRANS_CLOSURE:unsupported in Simplify\n";
00622 break;
00623 case TYPEDECL:
00624 os<<"ERROR:TYPEDECL:unsupported in Simplify\n";
00625 break;
00626 case UFUNC:
00627 case APPLY:
00628 if(e.isApply()) os << "(" << e.getOp().getExpr()<<" ";
00629 if(e.arity() > 0) {
00630 bool first(true);
00631 for (Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
00632 if(first) first = false;
00633 else os << " " ;
00634 os << *i;
00635 }
00636 os << ")";
00637 }
00638 break;
00639 default: {
00640 DebugAssert(false, "TheoryUF::print: Unexpected expression: "
00641 +getEM()->getKindName(e.getKind()));
00642 }
00643 }
00644 break;
00645
00646 case TPTP_LANG:
00647 switch(e.getKind()) {
00648 case OLD_ARROW:
00649 case ARROW:
00650 if(e.arity() < 2) e.printAST(os);
00651 else {
00652 os << "(" << push;
00653 bool first(true);
00654 for(int i=0, iend=e.arity()-1; i<iend; ++i) {
00655 if(first) first=false;
00656 else os << " * " ;
00657 os << e[i];
00658 }
00659 os << ")" ;
00660 os << " > " << e[e.arity()-1];
00661 }
00662 break;
00663
00664 case LAMBDA: {
00665 os<<"ERROR:LAMBDA:unsupported in TPTP\n";
00666 break;
00667 }
00668 case TRANS_CLOSURE:
00669 os<<"ERROR:TRANS_CLOSURE:unsupported in TPTP\n";
00670 break;
00671 case TYPEDECL:
00672 if(e.arity() != 1) e.printAST(os);
00673 else os << e[0].getString();
00674 break;
00675
00676 case UFUNC:
00677 DebugAssert(e.isSymbol(), "Expected symbol");
00678 os << to_lower(e.getName());
00679 break;
00680
00681 case APPLY:
00682 if(e.isApply()) os <<e.getOpExpr()<<"(";
00683 if(e.arity() > 0) {
00684 bool first(true);
00685 for (Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
00686 if(first) first = false;
00687 else os << "," ;
00688 os << *i;
00689 }
00690 os << ")";
00691 }
00692 break;
00693 default: {
00694 DebugAssert(false, "TheoryUF::print: Unexpected expression: "
00695 +getEM()->getKindName(e.getKind()));
00696 }
00697 }
00698 break;
00699
00700
00701 case PRESENTATION_LANG:
00702 switch(e.getKind()) {
00703 case OLD_ARROW:
00704 case ARROW:
00705 if(e.arity() < 2) e.printAST(os);
00706 else {
00707 if(e.arity() == 2)
00708 os << e[0];
00709 else {
00710 os << "(" << push;
00711 bool first(true);
00712 for(int i=0, iend=e.arity()-1; i<iend; ++i) {
00713 if(first) first=false;
00714 else os << "," << space;
00715 os << e[i];
00716 }
00717 os << push << ")" << pop << pop;
00718 }
00719 os << space << "->" << space << e[e.arity()-1];
00720 }
00721 break;
00722 case TYPEDECL:
00723
00724
00725
00726 if(e.arity() != 1) e.printAST(os);
00727 else os << e[0].getString();
00728 break;
00729 case LAMBDA: {
00730 DebugAssert(e.isLambda(), "Expected Lambda");
00731 os << "(" << push << "LAMBDA" << space << push;
00732 const vector<Expr>& vars = e.getVars();
00733 bool first(true);
00734 os << "(" << push;
00735 for(vector<Expr>::const_iterator i=vars.begin(), iend=vars.end();
00736 i!=iend; ++i) {
00737 if(first) first = false;
00738 else os << push << "," << pop << space;
00739 os << *i;
00740
00741
00742 if(i->isVar())
00743 os << ":" << space << pushdag << (*i).getType() << popdag;
00744 }
00745 os << push << "): " << pushdag << push
00746 << e.getBody() << push << ")";
00747 break;
00748 }
00749 case APPLY:
00750 os << e.getOpExpr();
00751 if(e.arity() > 0) {
00752 os << "(" << push;
00753 bool first(true);
00754 for (Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
00755 if(first) first = false;
00756 else os << "," << space;
00757 os << *i;
00758 }
00759 os << push << ")";
00760 }
00761 break;
00762 case TRANS_CLOSURE:
00763 DebugAssert(e.isSymbol(), "Expected symbol");
00764 os << e.getName() << "*";
00765 break;
00766 case UFUNC:
00767 DebugAssert(e.isSymbol(), "Expected symbol");
00768 os << e.getName();
00769 break;
00770 default: {
00771 DebugAssert(false, "TheoryUF::print: Unexpected expression: "
00772 +getEM()->getKindName(e.getKind()));
00773 }
00774 }
00775 break;
00776 case SMTLIB_LANG:
00777 switch(e.getKind()) {
00778 case OLD_ARROW:
00779 case ARROW: {
00780 if(e.arity() < 2) {
00781 throw SmtlibException("TheoryUF::print: Expected 2 or more arguments to ARROW");
00782
00783 }
00784 d_theoryUsed = true;
00785 os << push;
00786 bool oldDagFlag = os.dagFlag(false);
00787 int iend = e.arity();
00788 if (e[iend-1].getKind() == BOOLEAN) --iend;
00789 for(int i=0; i<iend; ++i) {
00790 if (i != 0) os << space;
00791 os << e[i];
00792 }
00793 os.dagFlag(oldDagFlag);
00794 break;
00795 }
00796 case TYPEDECL:
00797 if (e.arity() == 1 && e[0].isString()) {
00798 os << e[0].getString();
00799 break;
00800 }
00801
00802
00803
00804 throw SmtlibException("TheoryUF::print: TYPEDECL not supported");
00805
00806
00807
00808 break;
00809 case APPLY:
00810 if (e.arity() == 0) os << e.getOp().getExpr();
00811 else {
00812 os << "(" << push << e.getOp().getExpr();
00813 for (int i=0, iend=e.arity(); i<iend; ++i)
00814 os << space << e[i];
00815 if (e.getOpKind() == TRANS_CLOSURE) {
00816 os << space << ":transclose";
00817 }
00818 os << push << ")";
00819 }
00820 break;
00821 case TRANS_CLOSURE:
00822 os << e.getName();
00823 break;
00824 case UFUNC:
00825 DebugAssert(e.isSymbol(), "Expected symbol");
00826 os << theoryCore()->getTranslator()->fixConstName(e.getName());
00827 break;
00828 default: {
00829 DebugAssert(false, "TheoryUF::print: SMTLIB_LANG: Unexpected expression: "
00830 +getEM()->getKindName(e.getKind()));
00831 }
00832 }
00833 break;
00834 case LISP_LANG:
00835 switch(e.getKind()) {
00836 case OLD_ARROW:
00837 case ARROW:
00838 if(e.arity() < 2) e.printAST(os);
00839 os << "(" << push << "ARROW";
00840 for(int i=0, iend=e.arity(); i<iend; ++i)
00841 os << space << e[i];
00842 os << push << ")";
00843 break;
00844 case TRANS_CLOSURE:
00845 e.printAST(os);
00846 break;
00847 case TYPEDECL:
00848
00849
00850
00851 if(e.arity() != 1) e.printAST(os);
00852 else if(e[0].isString()) os << e[0].getString();
00853 else e[0].print(os);
00854 break;
00855 case LAMBDA: {
00856 DebugAssert(e.isLambda(), "Expected LAMBDA");
00857 os << "(" << push << "LAMBDA" << space;
00858 const vector<Expr>& vars = e.getVars();
00859 bool first(true);
00860 os << "(" << push;
00861 for(vector<Expr>::const_iterator i=vars.begin(), iend=vars.end();
00862 i!=iend; ++i) {
00863 if(first) first = false;
00864 else os << space;
00865 os << "(" << push << *i;
00866
00867
00868 if(i->isVar())
00869 os << space << pushdag << (*i).getType() << popdag;
00870 os << push << ")" << pop << pop;
00871 }
00872 os << push << ")" << pop << pop << pushdag
00873 << e.getBody() << push << ")";
00874 break;
00875 }
00876 case APPLY:
00877 DebugAssert(e.isApply(), "Expected Apply");
00878 if (e.arity() == 0) os << e.getOp().getExpr();
00879 else {
00880 os << "(" << push << e.getOp().getExpr();
00881 for (int i=0, iend=e.arity(); i<iend; ++i)
00882 os << space << e[i];
00883 os << push << ")";
00884 }
00885 break;
00886 default: {
00887 DebugAssert(false, "TheoryUF::print: Unexpected expression: "
00888 +getEM()->getKindName(e.getKind()));
00889 }
00890 }
00891 break;
00892 default:
00893
00894
00895 e.printAST(os);
00896 break;
00897 }
00898 return os;
00899 }
00900
00901
00902
00903
00904
00905 Expr
00906 TheoryUF::parseExprOp(const Expr& e) {
00907
00908
00909 if(RAW_LIST != e.getKind()) return e;
00910
00911 DebugAssert(e.arity() > 0,
00912 "TheoryUF::parseExprOp:\n e = "+e.toString());
00913
00914 if (e[0].getKind() == RAW_LIST) {
00915 if(e.arity() < 2)
00916 throw ParserException("Bad function application: "+e.toString());
00917 Expr::iterator i=e.begin(), iend=e.end();
00918 Expr op(parseExpr(*i)); ++i;
00919 vector<Expr> args;
00920 for(; i!=iend; ++i) args.push_back(parseExpr(*i));
00921 return Expr(op.mkOp(), args);
00922 }
00923
00924 DebugAssert(e[0].getKind() == ID || e[0][0].getKind() == ID,
00925 "Expected identifier");
00926 int kind = e[0].getKind();
00927 if (kind == ID) kind = getEM()->getKind(e[0][0].getString());
00928 switch(kind) {
00929 case OLD_ARROW: {
00930 if (!theoryCore()->getFlags()["old-func-syntax"].getBool()) {
00931 throw ParserException("You seem to be using the old syntax for function types.\n"
00932 "Please convert to the new syntax or run with +old-func-syntax");
00933 }
00934 DebugAssert(e.arity()==3,"Expected arity 3 in OLD_ARROW");
00935 Expr arg = parseExpr(e[1]);
00936 vector<Expr> k;
00937 if (arg.getOpKind() == TUPLE_TYPE) {
00938 Expr::iterator i = arg.begin(), iend=arg.end();
00939 for (; i != iend; ++i) {
00940 k.push_back(*i);
00941 }
00942 }
00943 else k.push_back(arg);
00944 k.push_back(parseExpr(e[2]));
00945 return Expr(ARROW, k);
00946 }
00947 case ARROW:
00948 case TYPEDECL: {
00949 vector<Expr> k;
00950 Expr::iterator i = e.begin(), iend=e.end();
00951
00952
00953 ++i;
00954
00955 for(; i!=iend; ++i)
00956 k.push_back(parseExpr(*i));
00957 return Expr(kind, k, e.getEM());
00958 break;
00959 }
00960 case TRANS_CLOSURE: {
00961 if(e.arity() != 4)
00962 throw ParserException("Wrong number of arguments to "
00963 "TRANS_CLOSURE expression\n"
00964 " (expected 3 arguments): "+e.toString());
00965 const string& name = e[1][0].getString();
00966 Expr funExpr = resolveID(name);
00967 if (funExpr.isNull())
00968 throw ParserException("Attempt to take transitive closure of unknown "
00969 "predicate"+name);
00970 return transClosureExpr(name, parseExpr(e[2]), parseExpr(e[3]));
00971 }
00972 case LAMBDA: {
00973 if(!(e.arity() == 3 && e[1].getKind() == RAW_LIST && e[1].arity() > 0))
00974 throw ParserException("Bad LAMBDA expression: "+e.toString());
00975
00976 vector<pair<string,Type> > vars;
00977 for(Expr::iterator i=e[1].begin(), iend=e[1].end(); i!=iend; ++i) {
00978 if(i->getKind() != RAW_LIST || i->arity() < 2)
00979 throw ParserException("Bad variable declaration block in LAMBDA "
00980 "expression: "+i->toString()+
00981 "\n e = "+e.toString());
00982
00983
00984
00985 Type tp(parseExpr((*i)[i->arity()-1]));
00986 for(int j=0, jend=i->arity()-1; j<jend; ++j) {
00987 if((*i)[j].getKind() != ID)
00988 throw ParserException("Bad variable declaration in LAMBDA"
00989 " expression: "+(*i)[j].toString()+
00990 "\n e = "+e.toString());
00991 vars.push_back(pair<string,Type>((*i)[j][0].getString(), tp));
00992 }
00993 }
00994
00995 vector<Expr> boundVars;
00996 for(vector<pair<string,Type> >::iterator i=vars.begin(), iend=vars.end();
00997 i!=iend; ++i)
00998 boundVars.push_back(addBoundVar(i->first, i->second));
00999
01000 Expr body(parseExpr(e[2]));
01001
01002 return lambdaExpr(boundVars, body);
01003 break;
01004 }
01005 case RAW_LIST:
01006 default: {
01007 if(e.arity() < 2)
01008 throw ParserException("Bad function application: "+e.toString());
01009 Expr::iterator i=e.begin(), iend=e.end();
01010 Expr op(parseExpr(*i)); ++i;
01011 vector<Expr> args;
01012 for(; i!=iend; ++i) args.push_back(parseExpr(*i));
01013 return Expr(op.mkOp(), args);
01014 }
01015 }
01016 return e;
01017 }
01018
01019
01020 Expr TheoryUF::lambdaExpr(const vector<Expr>& vars, const Expr& body) {
01021 return getEM()->newClosureExpr(LAMBDA, vars, body);
01022 }
01023
01024
01025 Expr TheoryUF::transClosureExpr(const std::string& name, const Expr& e1,
01026 const Expr& e2) {
01027 return Expr(getEM()->newSymbolExpr(name, TRANS_CLOSURE).mkOp(), e1, e2);
01028 }