theory_array.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file theory_array.cpp
00004  * 
00005  * Author: Clark Barrett
00006  * 
00007  * Created: Thu Feb 27 00:38:55 2003
00008  *
00009  * <hr>
00010  *
00011  * License to use, copy, modify, sell and/or distribute this software
00012  * and its documentation for any purpose is hereby granted without
00013  * royalty, subject to the terms and conditions defined in the \ref
00014  * LICENSE file provided with this distribution.
00015  * 
00016  * <hr>
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 // TheoryArray Private Methods                                               //
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 // TheoryArray Public Methods                                                //
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   // Register new local kinds with ExprManager
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 // Destructor: delete the proof rules class if it's present
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       // Count nested writes
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     // Record the read operator for concrete models
00183     TRACE("model", "TheoryArray: add array read ", e, "");
00184     d_reads.push_back(e);
00185   }
00186   else if (isWrite(e)) {
00187     // there is a hidden dependency of write(a,i,v) on read(a,i)
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       // TODO: calling simplify from update is generally bad
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   // Hidden dependency must have changed.  Update notify list.
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     // a WITH [i] := v -- report a, i and v as the model terms.
00413 //     getModelTerm(e[1], v);
00414 //     getModelTerm(e[2], v);
00415     v.push_back(e[0]);
00416     v.push_back(e[1]);
00417     v.push_back(e[2]);
00418     break;
00419   case READ:
00420     // For a[i], add the index i
00421     // getModelTerm(e[1], v);
00422     v.push_back(e[1]);
00423     // And continue to collect the reads a[i][j] (remember, e is of
00424     // ARRAY type)
00425   default:
00426     // For array terms, find all their reads
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     // Add both the read operator a[i]
00434     // getModelTerm(*i, v);
00435     v.push_back(*i);
00436       // and the index 'i' to the model terms.  Reason: the index to
00437       // the array should better be a concrete value, and it might not
00438       // necessarily be in the current list of model terms.
00439     // getModelTerm((*i)[1], v);
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); // For bound vars
00451 
00452   switch(e.getKind()) {
00453   case WRITE: {
00454     // We should already have a value for the original array
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 //   case READ: {
00471 //     // Get the assignment for the index
00472 //     Expr idx(getModelValue(e[1]).getRHS());
00473 //     // And the assignment for the 
00474 //     var = read(idxThm.getRHS(), e[0]);
00475 //   }
00476     // And continue to collect the reads a[i][j] (remember, e is of
00477     // ARRAY type)
00478   default: {
00479     // Assign 'e' a value later.
00480     v.push_back(e);
00481     // Map of e[i] to val for concrete values of i and val
00482     ExprHashMap<Expr> reads;
00483     // For array terms, find all their reads
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   // Get the value of the index
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   // Record it in the map
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     // Create an array literal
00515     if(reads.size()==0) { // Leave the array uninterpreted
00516       assignValue(reflexivityRule(e));
00517     } else {
00518       // Bound var for the index
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       // Use one of the concrete values as a default
00529       Expr res((*i).second);
00530       ++i;
00531       DebugAssert(!res.isNull(), "TheoryArray::computeModel()");
00532       for(; i!=iend; ++i) {
00533   // Optimization: if the current value is the same as that of the
00534   // next application, skip this case; i.e. keep 'res' instead of
00535   // building ite(cond, res, res).
00536   if((*i).second == res) continue;
00537   // ITE condition
00538   Expr cond = ind.eqExpr((*i).first[1]);
00539   res = cond.iteExpr((*i).second, res);
00540       }
00541       // Construct the array literal
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 // Pretty-printing                                           //
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       // Print the top node in the default LISP format, continue with
00619       // pretty-printing for children.
00620       e.printAST(os);
00621     }
00622     break; // end of case PRESENTATION_LANGUAGE
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       // Print the top node in the default LISP format, continue with
00645       // pretty-printing for children.
00646       e.printAST(os);
00647     }
00648     break; // end of case LISP_LANGUAGE
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       // Print the top node in the default LISP format, continue with
00671       // pretty-printing for children.
00672       e.printAST(os);
00673     }
00674     break; // end of case LISP_LANGUAGE
00675   default:
00676     // Print the top node in the default LISP format, continue with
00677     // pretty-printing for children.
00678     e.printAST(os);
00679   }
00680   return os;
00681 }
00682 
00683 //////////////////////////////////////////////////////////////////////////////
00684 //parseExprOp:
00685 //translating special Exprs to regular EXPR??
00686 ///////////////////////////////////////////////////////////////////////////////
00687 Expr
00688 TheoryArray::parseExprOp(const Expr& e) {
00689   //  TRACE("parser", "TheoryArray::parseExprOp(", e, ")");
00690   // If the expression is not a list, it must have been already
00691   // parsed, so just return it as is.
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       // Skip first element of the vector of kids in 'e'.
00712       // The first element is the operator.
00713       ++i; 
00714       // Parse the kids of e and push them into the vector 'k'
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: { // (ARRAY (v tp1) body)
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       // Build the resulting Expr as (LAMBDA (vars) body)
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 } // end of namespace CVC3

Generated on Tue Jul 3 14:33:40 2007 for CVC3 by  doxygen 1.5.1