00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "theory_array.h"
00023 #include "array_proof_rules.h"
00024 #include "typecheck_exception.h"
00025 #include "parser_exception.h"
00026 #include "smtlib_exception.h"
00027 #include "theory_core.h"
00028 #include "command_line_flags.h"
00029 #include "translator.h"
00030
00031
00032 using namespace std;
00033 using namespace CVC3;
00034
00035
00036
00037
00038
00039
00040 Theorem TheoryArray::renameExpr(const Expr& e) {
00041 Theorem thm = getCommonRules()->varIntroSkolem(e);
00042 DebugAssert(thm.isRewrite() && thm.getRHS().isSkolem(),
00043 "thm = "+thm.toString());
00044 theoryCore()->addToVarDB(thm.getRHS());
00045 return thm;
00046 }
00047
00048
00049
00050
00051
00052
00053
00054 TheoryArray::TheoryArray(TheoryCore* core)
00055 : Theory(core, "Arrays"), d_reads(core->getCM()->getCurrentContext()),
00056 d_applicationsInModel(core->getFlags()["applications"].getBool()),
00057 d_liftReadIte(core->getFlags()["liftReadIte"].getBool())
00058 {
00059 d_rules = createProofRules();
00060
00061
00062 getEM()->newKind(ARRAY, "_ARRAY", true);
00063 getEM()->newKind(READ, "_READ");
00064 getEM()->newKind(WRITE, "_WRITE");
00065 getEM()->newKind(ARRAY_LITERAL, "_ARRAY_LITERAL");
00066
00067 vector<int> kinds;
00068 kinds.push_back(ARRAY);
00069 kinds.push_back(READ);
00070 kinds.push_back(WRITE);
00071
00072 kinds.push_back(ARRAY_LITERAL);
00073
00074 registerTheory(this, kinds);
00075 }
00076
00077
00078
00079 TheoryArray::~TheoryArray() {
00080 if(d_rules != NULL) delete d_rules;
00081 }
00082
00083
00084 Theorem TheoryArray::rewrite(const Expr& e)
00085 {
00086 Theorem thm;
00087 if (isRead(e)) {
00088 switch(e[0].getKind()) {
00089 case WRITE:
00090 thm = d_rules->rewriteReadWrite(e);
00091 return transitivityRule(thm, simplify(thm.getRHS()));
00092 case ARRAY_LITERAL: {
00093 IF_DEBUG(debugger.counter("Read array literals")++);
00094 thm = d_rules->readArrayLiteral(e);
00095 return transitivityRule(thm, simplify(thm.getRHS()));
00096 }
00097 case ITE: {
00098 if (d_liftReadIte) {
00099 thm = d_rules->liftReadIte(e);
00100 return transitivityRule(thm, simplify(thm.getRHS()));
00101 }
00102 }
00103 default: {
00104 const Theorem& rep = e.getRep();
00105 if (rep.isNull()) return reflexivityRule(e);
00106 else return symmetryRule(rep);
00107 }
00108 }
00109 }
00110 else if (!e.isTerm()) {
00111 if (e.isEq() && e[0].isAtomic() && e[1].isAtomic() && isWrite(e[0])) {
00112 Expr left = e[0], right = e[1];
00113 int leftWrites = 1, rightWrites = 0;
00114
00115
00116 Expr e1 = left[0];
00117 while (isWrite(e1)) { leftWrites++; e1 = e1[0]; }
00118
00119 Expr e2 = right;
00120 while (isWrite(e2)) { rightWrites++; e2 = e2[0]; }
00121
00122 if (rightWrites == 0) {
00123 if (e1 == e2) {
00124 thm = d_rules->rewriteSameStore(e, leftWrites);
00125 return transitivityRule(thm, simplify(thm.getRHS()));
00126 }
00127 else {
00128 e.setRewriteNormal();
00129 return reflexivityRule(e);
00130 }
00131 }
00132
00133 if (leftWrites > rightWrites) {
00134 thm = getCommonRules()->rewriteUsingSymmetry(e);
00135 thm = transitivityRule(thm, d_rules->rewriteWriteWrite(thm.getRHS()));
00136 }
00137 else thm = d_rules->rewriteWriteWrite(e);
00138 return transitivityRule(thm, simplify(thm.getRHS()));
00139 }
00140 e.setRewriteNormal();
00141 return reflexivityRule(e);
00142 }
00143 else if (!e.isAtomic()) {
00144 e.setRewriteNormal();
00145 return reflexivityRule(e);
00146 }
00147 else if (isWrite(e)) {
00148 Expr store = e[0];
00149 while (isWrite(store)) store = store[0];
00150 DebugAssert(findExpr(e[2]) == e[2], "Expected own find");
00151 thm = simplify(Expr(READ, store, e[1]));
00152 if (thm.getRHS() == e[2]) {
00153 thm = d_rules->rewriteRedundantWrite1(thm, e);
00154 return transitivityRule(thm, simplify(thm.getRHS()));
00155 }
00156 if (isWrite(e[0])) {
00157 if (e[0][1] == e[1]) {
00158 return d_rules->rewriteRedundantWrite2(e);
00159 }
00160 if (e[0][1] > e[1]) {
00161 thm = d_rules->interchangeIndices(e);
00162 return transitivityRule(thm, simplify(thm.getRHS()));
00163 }
00164 }
00165 return reflexivityRule(e);
00166 }
00167 return reflexivityRule(e);
00168 }
00169
00170
00171 void TheoryArray::setup(const Expr& e)
00172 {
00173 if (e.isNot() || e.isEq()) return;
00174 DebugAssert(e.isAtomic(), "e should be atomic");
00175 for (int k = 0; k < e.arity(); ++k) {
00176 e[k].addToNotify(this, e);
00177 }
00178 if (isRead(e)) {
00179 Theorem thm = reflexivityRule(e);
00180 e.setSig(thm);
00181 e.setRep(thm);
00182
00183 TRACE("model", "TheoryArray: add array read ", e, "");
00184 d_reads.push_back(e);
00185 }
00186 else if (isWrite(e)) {
00187
00188 Expr store = e[0];
00189 while (isWrite(store)) store = store[0];
00190 Expr r = simplifyExpr(Expr(READ, store, e[1]));
00191 theoryCore()->setupTerm(r, this, theoryCore()->getTheoremForTerm(e));
00192 DebugAssert(r.isAtomic(), "Should be atomic");
00193 DebugAssert(r != e[2], "Should have been rewritten");
00194 r.addToNotify(this, e);
00195 }
00196 }
00197
00198
00199 void TheoryArray::update(const Theorem& e, const Expr& d)
00200 {
00201 int k, ar(d.arity());
00202
00203 if (isRead(d)) {
00204 const Theorem& dEQdsig = d.getSig();
00205 if (!dEQdsig.isNull()) {
00206 Expr dsig = dEQdsig.getRHS();
00207 Theorem thm = updateHelper(d);
00208 Expr sigNew = thm.getRHS();
00209 if (sigNew == dsig) return;
00210 dsig.setRep(Theorem());
00211 if (isWrite(sigNew[0])) {
00212 thm = transitivityRule(thm, d_rules->rewriteReadWrite(sigNew));
00213 Theorem renameTheorem = renameExpr(d);
00214 enqueueFact(transitivityRule(symmetryRule(renameTheorem), thm));
00215 d.setSig(Theorem());
00216 enqueueFact(renameTheorem);
00217 }
00218 else {
00219 const Theorem& repEQsigNew = sigNew.getRep();
00220 if (!repEQsigNew.isNull()) {
00221 d.setSig(Theorem());
00222 enqueueFact(transitivityRule(repEQsigNew, symmetryRule(thm)));
00223 }
00224 else {
00225 for (k = 0; k < ar; ++k) {
00226 if (sigNew[k] != dsig[k]) {
00227 sigNew[k].addToNotify(this, d);
00228 }
00229 }
00230 d.setSig(thm);
00231 sigNew.setRep(thm);
00232 }
00233 }
00234 }
00235 }
00236 else {
00237 DebugAssert(isWrite(d), "Expected write: d = "+d.toString());
00238 if (find(d).getRHS() == d) {
00239 Theorem thm = updateHelper(d);
00240 Expr sigNew = thm.getRHS();
00241
00242 Expr store = sigNew[0];
00243 while (isWrite(store)) store = store[0];
00244
00245
00246 Theorem thm2 = simplify(Expr(READ, store, sigNew[1]));
00247 if (thm2.getRHS() == sigNew[2]) {
00248 thm = transitivityRule(thm,
00249 d_rules->rewriteRedundantWrite1(thm2, sigNew));
00250 sigNew = thm.getRHS();
00251 }
00252 else if (isWrite(sigNew[0])) {
00253 if (sigNew[0][1] == sigNew[1]) {
00254 thm = transitivityRule(thm, d_rules->rewriteRedundantWrite2(sigNew));
00255 sigNew = thm.getRHS();
00256 }
00257 else if (sigNew[0][1] > sigNew[1]) {
00258 thm = transitivityRule(thm, d_rules->interchangeIndices(sigNew));
00259 sigNew = thm.getRHS();
00260 }
00261 }
00262
00263 if (d == sigNew) {
00264
00265 DebugAssert(!e.isNull(), "Shouldn't be possible");
00266 e.getRHS().addToNotify(this, d);
00267 }
00268 else if (sigNew.isAtomic()) {
00269 assertEqualities(thm);
00270 }
00271 else {
00272 Theorem renameTheorem = renameExpr(d);
00273 enqueueFact(transitivityRule(symmetryRule(renameTheorem), thm));
00274 assertEqualities(renameTheorem);
00275 }
00276 }
00277 }
00278 }
00279
00280
00281 Theorem TheoryArray::solve(const Theorem& eThm)
00282 {
00283 const Expr& e = eThm.getExpr();
00284 DebugAssert(e.isEq(), "TheoryArray::solve("+e.toString()+")");
00285 if (isWrite(e[0])) {
00286 DebugAssert(!isWrite(e[1]), "Should have been rewritten: e = "
00287 +e.toString());
00288 return symmetryRule(eThm);
00289 }
00290 return eThm;
00291 }
00292
00293
00294 void TheoryArray::checkType(const Expr& e)
00295 {
00296 switch (e.getKind()) {
00297 case ARRAY: {
00298 if (e.arity() != 2) throw Exception
00299 ("ARRAY type should have two arguments");
00300 Type t1(e[0]);
00301 if (t1.isBool()) throw Exception
00302 ("Array index types must be non-Boolean");
00303 if (t1.isFunction()) throw Exception
00304 ("Array index types cannot be functions");
00305 Type t2(e[1]);
00306 if (t2.isBool()) throw Exception
00307 ("Array value types must be non-Boolean");
00308 if (t2.isFunction()) throw Exception
00309 ("Array value types cannot be functions");
00310 break;
00311 }
00312 default:
00313 DebugAssert(false, "Unexpected kind in TheoryArray::checkType"
00314 +getEM()->getKindName(e.getKind()));
00315 }
00316
00317 }
00318
00319
00320 void TheoryArray::computeType(const Expr& e)
00321 {
00322 switch (e.getKind()) {
00323 case READ: {
00324 DebugAssert(e.arity() == 2,"");
00325 Type arrType = e[0].getType();
00326 if (!isArray(arrType)) {
00327 arrType = getBaseType(arrType);
00328 }
00329 if (!isArray(arrType))
00330 throw TypecheckException
00331 ("Expected an ARRAY type in\n\n "
00332 +e[0].toString()+"\n\nBut received this:\n\n "
00333 +arrType.toString()+"\n\nIn the expression:\n\n "
00334 +e.toString());
00335 Type idxType = getBaseType(e[1]);
00336 if(getBaseType(arrType[0]) != idxType && idxType != Type::anyType(getEM())) {
00337 throw TypecheckException
00338 ("The type of index expression:\n\n "
00339 +idxType.toString()
00340 +"\n\nDoes not match the ARRAY index type:\n\n "
00341 +arrType[0].toString()
00342 +"\n\nIn the expression: "+e.toString());
00343 }
00344 e.setType(arrType[1]);
00345 break;
00346 }
00347 case WRITE: {
00348 DebugAssert(e.arity() == 3,"");
00349 Type arrType = e[0].getType();
00350 if (!isArray(arrType)) {
00351 arrType = getBaseType(arrType);
00352 }
00353 Type idxType = getBaseType(e[1]);
00354 Type valType = getBaseType(e[2]);
00355 if (!isArray(arrType))
00356 throw TypecheckException
00357 ("Expected an ARRAY type in\n\n "
00358 +e[0].toString()+"\n\nBut received this:\n\n "
00359 +arrType.toString()+"\n\nIn the expression:\n\n "
00360 +e.toString());
00361 bool idxCorrect = getBaseType(arrType[0]) == idxType || idxType == Type::anyType(getEM());
00362 bool valCorrect = getBaseType(arrType[1]) == valType || valType == Type::anyType(getEM());;
00363 if(!idxCorrect) {
00364 throw TypecheckException
00365 ("The type of index expression:\n\n "
00366 +idxType.toString()
00367 +"\n\nDoes not match the ARRAY's type index:\n\n "
00368 +arrType[0].toString()
00369 +"\n\nIn the expression: "+e.toString());
00370 }
00371 if(!valCorrect) {
00372 throw TypecheckException
00373 ("The type of value expression:\n\n "
00374 +valType.toString()
00375 +"\n\nDoes not match the ARRAY's value type:\n\n "
00376 +arrType[1].toString()
00377 +"\n\nIn the expression: "+e.toString());
00378 }
00379 e.setType(arrType);
00380 break;
00381 }
00382 case ARRAY_LITERAL: {
00383 DebugAssert(e.isClosure(), "TheoryArray::computeType("+e.toString()+")");
00384 DebugAssert(e.getVars().size()==1,
00385 "TheoryArray::computeType("+e.toString()+")");
00386 Type ind(e.getVars()[0].getType());
00387 e.setType(arrayType(ind, e.getBody().getType()));
00388 break;
00389 }
00390 default:
00391 DebugAssert(false,"Unexpected type");
00392 break;
00393 }
00394 }
00395
00396
00397 Type TheoryArray::computeBaseType(const Type& t) {
00398 const Expr& e = t.getExpr();
00399 DebugAssert(e.getKind()==ARRAY && e.arity() == 2,
00400 "TheoryArray::computeBaseType("+t.toString()+")");
00401 vector<Expr> kids;
00402 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
00403 kids.push_back(getBaseType(Type(*i)).getExpr());
00404 }
00405 return Type(Expr(e.getOp(), kids));
00406 }
00407
00408
00409 void TheoryArray::computeModelTerm(const Expr& e, std::vector<Expr>& v) {
00410 switch(e.getKind()) {
00411 case WRITE:
00412
00413
00414
00415 v.push_back(e[0]);
00416 v.push_back(e[1]);
00417 v.push_back(e[2]);
00418 break;
00419 case READ:
00420
00421
00422 v.push_back(e[1]);
00423
00424
00425 default:
00426
00427 if(e.getType().getExpr().getKind() == ARRAY) {
00428 for(CDList<Expr>::const_iterator i=d_reads.begin(), iend=d_reads.end();
00429 i!=iend; ++i) {
00430 DebugAssert(isRead(*i) && (*i).arity()==2, "Bad array read: "
00431 +(*i).toString());
00432 if((*i)[0] == e) {
00433
00434
00435 v.push_back(*i);
00436
00437
00438
00439
00440 v.push_back((*i)[1]);
00441 }
00442 }
00443 }
00444 break;
00445 }
00446 }
00447
00448
00449 void TheoryArray::computeModel(const Expr& e, std::vector<Expr>& v) {
00450 static unsigned count(0);
00451
00452 switch(e.getKind()) {
00453 case WRITE: {
00454
00455 Expr res(getModelValue(e[0]).getRHS());
00456 Expr ind(getEM()->newBoundVarExpr("arr_var", int2string(count++)));
00457 Type tp(e.getType());
00458 DebugAssert(isArray(tp) && tp.arity()==2,
00459 "TheoryArray::computeModel(WRITE)");
00460 ind.setType(tp[0]);
00461 res = rewrite(Expr(READ, res, ind)).getRHS();
00462 Expr indVal(getModelValue(e[1]).getRHS());
00463 Expr updVal(getModelValue(e[2]).getRHS());
00464 res = (ind.eqExpr(indVal)).iteExpr(updVal, res);
00465 res = arrayLiteral(ind, res);
00466 assignValue(e, res);
00467 v.push_back(e);
00468 break;
00469 }
00470
00471
00472
00473
00474
00475
00476
00477
00478 default: {
00479
00480 v.push_back(e);
00481
00482 ExprHashMap<Expr> reads;
00483
00484 DebugAssert(getBaseType(e).getExpr().getKind() == ARRAY, "");
00485
00486 for(CDList<Expr>::const_iterator i=d_reads.begin(), iend=d_reads.end();
00487 i!=iend; ++i) {
00488 TRACE("model", "TheoryArray::computeModel: read = ", *i, "");
00489 DebugAssert(isRead(*i) && (*i).arity()==2, "Bad array read: "
00490 +(*i).toString());
00491 if((*i)[0] == e) {
00492
00493 Theorem asst(getModelValue((*i)[1]));
00494 Expr var;
00495 if(asst.getLHS()!=asst.getRHS()) {
00496 vector<Theorem> thms;
00497 vector<unsigned> changed;
00498 thms.push_back(asst);
00499 changed.push_back(1);
00500 Theorem subst(substitutivityRule(*i, changed, thms));
00501 assignValue(transitivityRule(symmetryRule(subst),
00502 getModelValue(*i)));
00503 var = subst.getRHS();
00504 } else
00505 var = *i;
00506 if(d_applicationsInModel) v.push_back(var);
00507
00508 Expr val(getModelValue(var).getRHS());
00509 DebugAssert(!val.isNull(), "TheoryArray::computeModel(): Variable "
00510 +var.toString()+" has a Null value");
00511 reads[var] = val;
00512 }
00513 }
00514
00515 if(reads.size()==0) {
00516 assignValue(reflexivityRule(e));
00517 } else {
00518
00519 Expr ind(getEM()->newBoundVarExpr("arr_var", int2string(count++)));
00520 Type tp(e.getType());
00521 DebugAssert(isArray(tp) && tp.arity()==2,
00522 "TheoryArray::computeModel(WRITE)");
00523 ind.setType(tp[0]);
00524 ExprHashMap<Expr>::iterator i=reads.begin(), iend=reads.end();
00525 DebugAssert(i!=iend,
00526 "TheoryArray::computeModel(): expected the reads "
00527 "table be non-empty");
00528
00529 Expr res((*i).second);
00530 ++i;
00531 DebugAssert(!res.isNull(), "TheoryArray::computeModel()");
00532 for(; i!=iend; ++i) {
00533
00534
00535
00536 if((*i).second == res) continue;
00537
00538 Expr cond = ind.eqExpr((*i).first[1]);
00539 res = cond.iteExpr((*i).second, res);
00540 }
00541
00542 res = arrayLiteral(ind, res);
00543 assignValue(e, res);
00544 }
00545 break;
00546 }
00547 }
00548 }
00549
00550
00551 Expr TheoryArray::computeTCC(const Expr& e)
00552 {
00553 Expr tcc(Theory::computeTCC(e));
00554 switch (e.getKind()) {
00555 case READ:
00556 DebugAssert(e.arity() == 2,"");
00557 return tcc.andExpr(getTypePred(e[0].getType()[0], e[1]));
00558 case WRITE: {
00559 DebugAssert(e.arity() == 3,"");
00560 Type arrType = e[0].getType();
00561 return rewriteAnd(getTypePred(arrType[0], e[1]).andExpr
00562 (getTypePred(arrType[1], e[2])).andExpr(tcc)).getRHS();
00563 }
00564 case ARRAY_LITERAL: {
00565 return tcc;
00566 }
00567 default:
00568 DebugAssert(false,"TheoryArray::computeTCC: Unexpected expression: "
00569 +e.toString());
00570 return tcc;
00571 }
00572 }
00573
00574
00575
00576
00577
00578
00579
00580 ExprStream& TheoryArray::print(ExprStream& os, const Expr& e)
00581 {
00582 d_theoryUsed = true;
00583 if (theoryCore()->getTranslator()->printArrayExpr(os, e)) return os;
00584 switch(os.lang()) {
00585 case PRESENTATION_LANG:
00586 switch(e.getKind()) {
00587 case READ:
00588 if(e.arity() == 1)
00589 os << "[" << push << e[0] << push << "]";
00590 else
00591 os << e[0] << "[" << push << e[1] << push << "]";
00592 break;
00593 case WRITE:
00594 os << "(" << push << e[0] << space << "WITH ["
00595 << push << e[1] << "] := " << push << e[2] << push << ")";
00596 break;
00597 case ARRAY:
00598 os << "ARRAY" << space << e[0] << space << "OF" << space << e[1];
00599 break;
00600 case ARRAY_LITERAL:
00601 if(e.isClosure()) {
00602 const vector<Expr>& vars = e.getVars();
00603 const Expr& body = e.getBody();
00604 os << "(" << push << "ARRAY" << space << "(" << push;
00605 bool first(true);
00606 for(size_t i=0; i<vars.size(); ++i) {
00607 if(first) first=false;
00608 else os << push << "," << pop << space;
00609 os << vars[i];
00610 if(vars[i].isVar())
00611 os << ":" << space << pushdag << vars[i].getType() << popdag;
00612 }
00613 os << push << "):" << pop << pop << space << body << push << ")";
00614 } else
00615 e.printAST(os);
00616 break;
00617 default:
00618
00619
00620 e.printAST(os);
00621 }
00622 break;
00623 case SMTLIB_LANG:
00624 switch(e.getKind()) {
00625 case READ:
00626 if(e.arity() == 2)
00627 os << "(" << push << "select" << space << e[0]
00628 << space << e[1] << push << ")";
00629 else
00630 e.printAST(os);
00631 break;
00632 case WRITE:
00633 if(e.arity() == 3)
00634 os << "(" << push << "store" << space << e[0]
00635 << space << e[1] << space << e[2] << push << ")";
00636 else
00637 e.printAST(os);
00638 break;
00639 case ARRAY:
00640 throw SmtlibException("ARRAY should be handled by printArrayExpr");
00641 break;
00642 default:
00643 throw SmtlibException("TheoryArray::print: default not supported");
00644
00645
00646 e.printAST(os);
00647 }
00648 break;
00649 case LISP_LANG:
00650 switch(e.getKind()) {
00651 case READ:
00652 if(e.arity() == 2)
00653 os << "(" << push << "READ" << space << e[0]
00654 << space << e[1] << push << ")";
00655 else
00656 e.printAST(os);
00657 break;
00658 case WRITE:
00659 if(e.arity() == 3)
00660 os << "(" << push << "WRITE" << space << e[0]
00661 << space << e[1] << space << e[2] << push << ")";
00662 else
00663 e.printAST(os);
00664 break;
00665 case ARRAY:
00666 os << "(" << push << "ARRAY" << space << e[0]
00667 << space << e[1] << push << ")";
00668 break;
00669 default:
00670
00671
00672 e.printAST(os);
00673 }
00674 break;
00675 default:
00676
00677
00678 e.printAST(os);
00679 }
00680 return os;
00681 }
00682
00683
00684
00685
00686
00687 Expr
00688 TheoryArray::parseExprOp(const Expr& e) {
00689
00690
00691
00692 if(RAW_LIST != e.getKind()) return e;
00693
00694 DebugAssert(e.arity() > 0,
00695 "TheoryArray::parseExprOp:\n e = "+e.toString());
00696
00697 const Expr& c1 = e[0][0];
00698 int kind = getEM()->getKind(c1.getString());
00699 switch(kind) {
00700 case READ:
00701 if(!(e.arity() == 3))
00702 throw ParserException("Bad array access expression: "+e.toString());
00703 return Expr(READ, parseExpr(e[1]), parseExpr(e[2]));
00704 case WRITE:
00705 if(!(e.arity() == 4))
00706 throw ParserException("Bad array update expression: "+e.toString());
00707 return Expr(WRITE, parseExpr(e[1]), parseExpr(e[2]), parseExpr(e[3]));
00708 case ARRAY: {
00709 vector<Expr> k;
00710 Expr::iterator i = e.begin(), iend=e.end();
00711
00712
00713 ++i;
00714
00715 for(; i!=iend; ++i)
00716 k.push_back(parseExpr(*i));
00717 return Expr(kind, k, e.getEM());
00718 break;
00719 }
00720 case ARRAY_LITERAL: {
00721 if(!(e.arity() == 3 && e[1].getKind() == RAW_LIST && e[1].arity() == 2))
00722 throw ParserException("Bad ARRAY literal expression: "+e.toString());
00723 const Expr& varPair = e[1];
00724 if(varPair.getKind() != RAW_LIST)
00725 throw ParserException("Bad variable declaration block in ARRAY "
00726 "literal expression: "+varPair.toString()+
00727 "\n e = "+e.toString());
00728 if(varPair[0].getKind() != ID)
00729 throw ParserException("Bad variable declaration in ARRAY"
00730 "literal expression: "+varPair.toString()+
00731 "\n e = "+e.toString());
00732 Type varTp(parseExpr(varPair[1]));
00733 vector<Expr> var;
00734 var.push_back(addBoundVar(varPair[0][0].getString(), varTp));
00735 Expr body(parseExpr(e[2]));
00736
00737 return getEM()->newClosureExpr(ARRAY_LITERAL, var, body);
00738 break;
00739 }
00740 default:
00741 DebugAssert(false,
00742 "TheoryArray::parseExprOp: wrong type: "
00743 + e.toString());
00744 break;
00745 }
00746 return e;
00747 }
00748
00749 namespace CVC3 {
00750
00751 Expr arrayLiteral(const Expr& ind, const Expr& body) {
00752 vector<Expr> vars;
00753 vars.push_back(ind);
00754 return body.getEM()->newClosureExpr(ARRAY_LITERAL, vars, body);
00755 }
00756
00757 }