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