theory_records.cpp

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file theory_records.cpp
00004  * 
00005  * Author: Daniel Wichs
00006  * 
00007  * Created: 7/21/03
00008  *
00009  * <hr>
00010  * Copyright (C) 2003 by the Board of Tustees of Leland Stanford
00011  * Junior University and by New York University. 
00012  *
00013  * License to use, copy, modify, sell and/or distribute this software
00014  * and its documentation for any purpose is hereby granted without
00015  * royalty, subject to the terms and conditions defined in the \ref
00016  * LICENSE file provided with this distribution.  In particular:
00017  *
00018  * - The above copyright notice and this permission notice must appear
00019  * in all copies of the software and related documentation.
00020  *
00021  * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
00022  * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
00023  * 
00024  * <hr>
00025  * 
00026  */
00027 /*****************************************************************************/
00028 #include "theory_records.h"
00029 #include "typecheck_exception.h"
00030 #include "parser_exception.h"
00031 #include "smtlib_exception.h"
00032 #include "records_proof_rules.h"
00033 
00034 
00035 using namespace std;
00036 using namespace CVCL;
00037 
00038 /*!
00039  * When a record/tuple (dis)equality is expanded into the
00040  * (dis)equalities of fields, we have to perform rewrites on the
00041  * resulting record terms before the simplifier kicks in.  
00042  *
00043  * Otherwise, if we have r1.f = r2.f, but r1=r2 was asserted before,
00044  * for some complex record expressions r1 and r2, then the simplifier
00045  * will substitute r2 for r1, and we get r2.f=r2.f at the end, which
00046  * is not a useful fact to have.
00047  *
00048  * However, r1.f and/or r2.f may rewrite to something interesting, and
00049  * the equality may yield new important facts.
00050  */
00051 Theorem 
00052 TheoryRecords::rewriteAux(const Expr& e) {
00053   Theorem res;
00054   switch(e.getKind()) {
00055   case EQ:
00056   case IFF:
00057   case AND:
00058   case OR: {
00059     vector<unsigned> changed;
00060     vector<Theorem> thms;
00061     for(int i=0, iend=e.arity(); i<iend; ++i) {
00062       Theorem t(rewriteAux(e[i]));
00063       if(t.getLHS() != t.getRHS()) {
00064         changed.push_back(i);
00065         thms.push_back(t);
00066       }
00067     }
00068     if(thms.size() > 0) {
00069       res = substitutivityRule(e, changed, thms);
00070       // Need to guarantee that new expressions are fully simplified
00071       if(res.getRHS().hasFind())
00072         res = transitivityRule(res, res.getRHS().getFind());
00073     } else
00074       res = reflexivityRule(e);
00075     break;
00076   }
00077   case NOT: {
00078     vector<Theorem> thms;
00079     thms.push_back(rewriteAux(e[0]));
00080     if(thms[0].getLHS() != thms[0].getRHS()) {
00081       res = substitutivityRule(NOT, thms);
00082       // Need to guarantee that new expressions are fully simplified
00083       if(res.getRHS().hasFind())
00084         res = transitivityRule(res, res.getRHS().getFind());
00085     } else
00086       res = reflexivityRule(e);
00087     break;
00088   }
00089   default:
00090     res = rewrite(e);
00091     break;
00092   }
00093   return res;
00094 }
00095 
00096 
00097 Theorem 
00098 TheoryRecords::rewriteAux(const Theorem& thm) {
00099   return iffMP(thm, rewriteAux(thm.getExpr()));
00100 }
00101 
00102 
00103 TheoryRecords::TheoryRecords(TheoryCore* core)
00104   : Theory(core, "Records")
00105 {
00106 
00107   getEM()->newKind(RECORD_TYPE, "RECORD_TYPE", true);
00108   getEM()->newKind(TUPLE_TYPE, "TUPLE_TYPE", true);
00109 
00110   getEM()->newKind(RECORD, "RECORD");
00111   getEM()->newKind(RECORD_SELECT, "RECORD_SELECT");
00112   getEM()->newKind(RECORD_UPDATE, "RECORD_UPDATE");
00113   getEM()->newKind(TUPLE, "TUPLE");
00114   getEM()->newKind(TUPLE_SELECT, "TUPLE_SELECT");
00115   getEM()->newKind(TUPLE_UPDATE, "TUPLE_UPDATE");
00116 
00117   d_rules = createProofRules();
00118   vector<int> kinds;
00119 
00120   kinds.push_back(RECORD);
00121   kinds.push_back(RECORD_SELECT);
00122   kinds.push_back(RECORD_UPDATE);
00123   kinds.push_back(RECORD_TYPE);
00124   kinds.push_back(TUPLE_TYPE);
00125   kinds.push_back(TUPLE);
00126   kinds.push_back(TUPLE_SELECT);
00127   kinds.push_back(TUPLE_UPDATE);
00128 
00129   registerTheory(this, kinds);
00130 }
00131 
00132 TheoryRecords::~TheoryRecords() {
00133   delete d_rules;
00134 }
00135 
00136 void TheoryRecords::assertFact(const Theorem& e)
00137 {
00138   TRACE("records", "assertFact => ", e.toString(), "");
00139   const Expr& expr = e.getExpr();
00140   Theorem expanded;
00141   switch(expr.getKind()) {
00142   case IFF:
00143   case EQ: {
00144     int lhsKind = getBaseType(expr[0]).getExpr().getOpKind();
00145     if(lhsKind == RECORD_TYPE || lhsKind== TUPLE_TYPE)
00146       {
00147         expanded = rewriteAux(d_rules->expandEq(e));
00148         TRACE("records", "assertFact: enqueuing: ", expanded.toString(), "");
00149         enqueueFact(expanded);
00150       }
00151     return;
00152   }
00153   case NOT:
00154     DebugAssert(expr[0].getKind() == EQ || expr[0].getKind() == IFF,
00155                 "expecting a disequality or boolean field extraction: "
00156                 +expr.toString());
00157     break;
00158   default:
00159     DebugAssert(false, "TheoryRecords::assertFact expected an equation"
00160                 " or negation of equation expression. Instead it got"
00161                 + e.toString());
00162     
00163   }
00164       
00165 }
00166 
00167 
00168 Theorem TheoryRecords::rewrite(const Expr& e) {
00169   Theorem rw;
00170   TRACE("records", "rewrite(", e, ") {");
00171   bool needRecursion=false;
00172   switch(e.getOpKind()) {
00173   case TUPLE_SELECT:
00174   case RECORD_SELECT: {
00175     switch(e[0].getOpKind()){
00176     case RECORD:{
00177       rw = d_rules->rewriteLitSelect(e);
00178       break;
00179     }
00180     case TUPLE: {
00181       rw =   d_rules->rewriteLitSelect(e);
00182       break;
00183     }
00184     case RECORD_UPDATE: {
00185       rw = d_rules->rewriteUpdateSelect(e);
00186       needRecursion=true;
00187       break;
00188     }
00189     case TUPLE_UPDATE: {
00190       rw = d_rules->rewriteUpdateSelect(e);
00191       needRecursion=true;
00192       break;
00193     }
00194     default:{
00195       rw =  reflexivityRule(e);
00196       break;
00197     }
00198     }
00199     break;
00200   } 
00201   case RECORD_UPDATE: {
00202     DebugAssert(e.arity() == 2, 
00203                 "TheoryRecords::rewrite(RECORD_UPDATE): e="+e.toString());
00204     if(e[0].getOpKind() == RECORD)
00205       rw= d_rules->rewriteLitUpdate(e);
00206     else
00207       rw =  reflexivityRule(e);
00208     break;
00209   }
00210   case TUPLE_UPDATE: {
00211     if(e[0].getOpKind() == TUPLE)
00212       rw = d_rules->rewriteLitUpdate(e);
00213     else
00214       rw =  reflexivityRule(e);
00215     break;
00216   }
00217   case RECORD:
00218   case TUPLE:
00219     rw = rewriteCC(e); // Congruence closure rewrites
00220     break;
00221   default: {
00222     rw = reflexivityRule(e);
00223     break;
00224   }   
00225   }
00226   Theorem res;
00227   if(needRecursion==true) res = transitivityRule(rw, rewrite(rw.getRHS()));
00228   else
00229     res = rw;
00230   TRACE("records", "rewrite => ", res.getRHS(), " }");
00231   return res;
00232 }
00233 
00234 
00235 Expr TheoryRecords::computeTCC(const Expr& e)
00236 {
00237   TRACE("records", "computeTCC( ", e, ")   {");
00238   Expr tcc(Theory::computeTCC(e));
00239   switch (e.getOpKind()) {
00240   case RECORD:
00241   case RECORD_SELECT:
00242   case TUPLE:
00243   case TUPLE_SELECT:
00244     break;
00245   case RECORD_UPDATE: {
00246     Expr tExpr = e.getType().getExpr();
00247     const std::string field(getField(e));
00248     int index = getFieldIndex(tExpr, field);
00249     Expr pred = getTypePred(e.getType()[index], e[1]);
00250     tcc = rewriteAnd(tcc.andExpr(pred)).getRHS();
00251     break;
00252   }
00253   case TUPLE_UPDATE: {
00254     Expr tExpr = e.getType().getExpr();
00255     int index = getIndex(e);
00256     Expr pred = getTypePred(e.getType()[index], e[1]);
00257     tcc = rewriteAnd(tcc.andExpr(pred)).getRHS();
00258     break;
00259   }
00260   default: {
00261     DebugAssert (false, "Theory records cannot calculate this tcc");
00262   }
00263   }
00264   TRACE("records", "computeTCC => ", tcc, "}");
00265   return tcc;
00266 }
00267 
00268 void TheoryRecords::computeModelTerm(const Expr& e, std::vector<Expr>& v) {
00269   Type t = e.getType();
00270   Expr tExpr  = t.getExpr();
00271   if(tExpr.getOpKind() == RECORD_TYPE) {
00272     const vector<Expr>& fields = getFields(tExpr);
00273     for(unsigned int i = 0; i < fields.size() ; i++) {
00274       Expr term(recordSelect(e, fields[i].getString()));
00275       term = rewrite(term).getRHS();
00276       v.push_back(term);
00277     }
00278   }
00279   else if(tExpr.getOpKind() == TUPLE_TYPE) {
00280     for(int i=0; i<tExpr.arity(); i++) {
00281       Expr term(tupleSelect(e, i));
00282       term = rewrite(term).getRHS();
00283       v.push_back(term);
00284     }
00285   }
00286 }
00287 
00288 void TheoryRecords::computeModel(const Expr& e, std::vector<Expr>& v) {
00289   Type t = getBaseType(e);
00290   Expr tExpr  = t.getExpr();
00291   vector<Theorem> thms;
00292   vector<unsigned> changed;
00293   Theorem asst;
00294   if(tExpr.getOpKind() == RECORD_TYPE)
00295     asst = d_rules->expandRecord(e);
00296   else if(tExpr.getOpKind() == TUPLE_TYPE)
00297     asst = d_rules->expandTuple(e);
00298   else {
00299     DebugAssert(false, "TheoryRecords::computeModel("+e.toString()+")");
00300     return;
00301   }
00302 
00303   const Expr& lit = asst.getRHS();
00304   int size(lit.arity());
00305   for(int i = 0; i < size ; i++) {
00306     Theorem thm(getModelValue(lit[i]));
00307     if(thm.getLHS() != thm.getRHS()) {
00308       thms.push_back(thm);
00309       changed.push_back(i);
00310     }
00311   }
00312   if(changed.size()>0)
00313     asst = transitivityRule(asst, substitutivityRule(lit, changed, thms));
00314   assignValue(asst);
00315   v.push_back(e);
00316 }
00317 
00318 
00319 Expr TheoryRecords::computeTypePred(const Type& t, const Expr& e)
00320 {
00321   TRACE("typePred", "ComputeTypePred[Records]", e, "");
00322   Expr tExpr = t.getExpr();
00323   switch(tExpr.getOpKind()) {
00324   case RECORD_TYPE: {
00325     const vector<Expr>& fields = getFields(tExpr);
00326     vector<Expr> fieldPreds;
00327     for(unsigned int i = 0; i<fields.size(); i++) {
00328       Expr sel(recordSelect(e, fields[i].getString()));
00329       fieldPreds.push_back(getTypePred(tExpr[i], sel));
00330     }
00331       Expr pred = andExpr(fieldPreds);
00332       TRACE("typePred", "Computed predicate ", pred, "");
00333       return pred;
00334   }
00335   case TUPLE_TYPE: {
00336     std::vector<Expr> fieldPreds;
00337     for(int i = 0; i<tExpr.arity(); i++) {
00338       fieldPreds.push_back(getTypePred(tExpr[i], tupleSelect(e, i)));
00339     }
00340     Expr pred = andExpr(fieldPreds);
00341     TRACE("typePred", "Computed predicate ", pred, "");
00342     return pred;    
00343   }
00344   default:
00345    DebugAssert(false, "computeTypePred[TheoryRecords] called with wrong type");
00346    return Expr();
00347   }
00348 }
00349 
00350 
00351 void TheoryRecords::checkType(const Expr& e)
00352 {
00353   switch (e.getOpKind()) {
00354     case RECORD_TYPE: {
00355       Expr::iterator i = e.begin(), iend = e.end();
00356       for (; i != iend; ) {
00357         Type t(*i);
00358         ++i;
00359         if (t.isFunction()) throw Exception
00360             ("Records cannot contain functions");
00361       }
00362       break;
00363     }
00364     case TUPLE_TYPE: {
00365       Expr::iterator i = e.begin(), iend = e.end();
00366       for (; i != iend; ) {
00367         Type t(*i);
00368         ++i;
00369         if (t.isFunction()) throw Exception
00370             ("Tuples cannot contain functions");
00371       }
00372       break;
00373     }
00374     default:
00375       DebugAssert(false, "Unexpected kind in TheoryRecords::checkType"
00376                   +getEM()->getKindName(e.getOpKind()));
00377   }
00378 }
00379 
00380 
00381 void TheoryRecords::computeType(const Expr& e)
00382 {
00383   switch (e.getOpKind()) {
00384   case RECORD:{
00385     DebugAssert(e.arity() > 0, "wrong arity of RECORD" + e.toString());
00386     vector<Expr> fieldTypes;
00387     const vector<Expr>& fields = getFields(e);
00388     string previous;
00389     DebugAssert((unsigned int)e.arity() == fields.size(),
00390                 "size of fields does not match size of values");
00391     for(int i = 0; i<e.arity(); ++i) {
00392       DebugAssert(fields[i].getString() != previous, 
00393                   "a record cannot not contain repeated fields"
00394                   + e.toString());
00395       fieldTypes.push_back(e[i].getType().getExpr());
00396       previous=fields[i].getString();
00397     }
00398     e.setType(Type(recordType(fields, fieldTypes)));
00399     return;
00400   }
00401   case RECORD_SELECT: {
00402     DebugAssert(e.arity() == 1, "wrong arity of RECORD_SELECT" + e.toString());
00403     Expr t = e[0].getType().getExpr();
00404     const string& field = getField(e);
00405     DebugAssert(t.getOpKind() == RECORD_TYPE, "incorrect RECORD_SELECT expression"
00406                 "first child not a RECORD_TYPE" + e.toString());
00407     int index = getFieldIndex(t, field);
00408     if(index==-1)
00409       throw TypecheckException("record selection does not match any field "
00410                                "in record" + e.toString());
00411     e.setType(Type(t[index]));
00412     return;
00413   }
00414   case RECORD_UPDATE: {
00415     DebugAssert(e.arity() == 2, "wrong arity of RECORD_UPDATE" + e.toString());
00416     Expr t = e[0].getType().getExpr();
00417     const string& field = getField(e);
00418     DebugAssert(t.getOpKind() == RECORD_TYPE, "incorrect RECORD_SELECT expression"
00419                 "first child not a RECORD_TYPE" + e.toString());
00420     int index = getFieldIndex(t, field);
00421     if(index==-1)
00422       throw TypecheckException
00423         ("record update field \""+field
00424          +"\" does not match any in record type:\n"
00425          +t.toString()+"\n\nThe complete expression is:\n\n"
00426          + e.toString());
00427     if(getBaseType(Type(t[index])) != getBaseType(e[1]))
00428       throw TypecheckException("Type checking error: \n"+ e.toString());
00429     e.setType(e[0].getType());
00430     return;
00431   }
00432   case TUPLE: {
00433     DebugAssert(e.arity() > 0, "wrong arity of TUPLE"+ e.toString());
00434     std::vector<Expr> types;
00435     for(Expr::iterator it = e.begin(), end=e.end(); it!=end; ++it)
00436       {
00437         types.push_back((*it).getType().getExpr());
00438       }
00439     e.setType(Type(Expr(TUPLE_TYPE, types, getEM())));
00440     return;
00441   }
00442   case TUPLE_SELECT: {
00443     DebugAssert(e.arity() == 1, "wrong arity of TUPLE_SELECT" + e.toString());
00444     Expr t = e[0].getType().getExpr();
00445     int index = getIndex(e);
00446     DebugAssert(t.getOpKind() == TUPLE_TYPE,
00447                 "incorrect TUPLE_SELECT expression: "
00448                 "first child is not a TUPLE_TYPE:\n\n" + e.toString());
00449     if(index >= t.arity())
00450       throw TypecheckException("tuple index exceeds number of fields: \n"
00451                                + e.toString());
00452     e.setType(Type(t[index]));
00453     return;
00454   }
00455   case TUPLE_UPDATE: {
00456     DebugAssert(e.arity() == 2, "wrong arity of TUPLE_UPDATE" + e.toString());
00457     Expr t = e[0].getType().getExpr();
00458     int index = getIndex(e);
00459     DebugAssert(t.getOpKind() == TUPLE_TYPE, "incorrect TUPLE_SELECT expression: "
00460                 "first child not a TUPLE_TYPE:\n\n" + e.toString());
00461     if(index >= t.arity())
00462       throw TypecheckException("tuple index exceeds number of fields: \n"
00463                                + e.toString());
00464     if(getBaseType(Type(t[index])) != getBaseType(e[1]))
00465       throw TypecheckException("tuple update type mismatch: \n"+ e.toString());
00466     e.setType(e[0].getType());
00467     return;
00468   }
00469   default:
00470     DebugAssert(false,"Unexpected type: "+e.toString());
00471     break;
00472   }
00473 }
00474 
00475 
00476 Type
00477 TheoryRecords::computeBaseType(const Type& t) {
00478   const Expr& e = t.getExpr();
00479   Type res;
00480   switch(e.getOpKind()) {
00481   case TUPLE_TYPE:
00482   case RECORD_TYPE: {
00483     DebugAssert(e.arity() > 0, "Expected non-empty type");
00484     vector<Expr> kids;
00485     for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
00486       kids.push_back(getBaseType(Type(*i)).getExpr());
00487     }
00488     res = Type(Expr(e.getOp(), kids));
00489     break;
00490   }
00491   default:
00492     DebugAssert(false,
00493                 "TheoryRecords::computeBaseType("+t.toString()+")");
00494     res = t;
00495   }
00496   return res;
00497 }
00498 
00499 
00500 void
00501 TheoryRecords::setup(const Expr& e) {
00502   // Only set up terms
00503   if (e.isTerm()) {
00504     switch(e.getOpKind()) {
00505     case RECORD:
00506     case TUPLE: // Setup for congruence closure
00507       setupCC(e);
00508       break;
00509     default: { // Everything else
00510       for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
00511         i->addToNotify(this, e);
00512       // Check if we have a tuple of record type, and set up those for CC
00513       Type tp(getBaseType(e));
00514       Theorem thm;
00515       if(isRecordType(tp)) // Expand e into its literal, and it setup for CC
00516         thm = d_rules->expandRecord(e);
00517       else if(isTupleType(tp))
00518         thm = d_rules->expandTuple(e);
00519       if(!thm.isNull()) {
00520         Expr lit(thm.getRHS());
00521         TRACE("records", "setup: lit = ", lit, "");
00522         // Simplify the kids
00523         vector<Theorem> thms;
00524         vector<unsigned> changed;
00525         for(int i=0,iend=lit.arity(); i<iend; ++i) {
00526           TRACE("records", "setup: rewriting lit["+int2string(i)+"] = ",
00527                 lit[i], "");
00528           Theorem t = rewrite(lit[i]);
00529           t = transitivityRule(t, find(t.getRHS()));
00530           if(lit[i] != t.getRHS()) {
00531             thms.push_back(t);
00532             changed.push_back(i);
00533           }
00534         }
00535         if(changed.size()>0) {
00536           thm = transitivityRule(thm, substitutivityRule(lit, changed, thms));
00537           lit = thm.getRHS();
00538         }
00539         // Check if lit has already been setup
00540         if(lit.hasFind()) {
00541           enqueueFact(transitivityRule(thm, find(lit)));
00542         } else {
00543           setup(lit);
00544           lit.setFind(symmetryRule(thm));
00545         }
00546       }
00547     }
00548     }
00549   }
00550 }
00551  
00552 
00553 void
00554 TheoryRecords::update(const Theorem& e, const Expr& d) {
00555   if (inconsistent()) return;
00556   DebugAssert(d.hasFind(), "Expected d to have find");
00557 
00558   switch(d.getOpKind()) {
00559   case RECORD:
00560   case TUPLE:
00561     // Record and tuple literals are handled by congruence closure updates
00562     updateCC(e, d);
00563     break;
00564   default: // Everything else
00565     // If d is not its own representative, don't do anything; the
00566     // representative will be sent to us eventually.
00567     if (find(d).getRHS() == d) {
00568       // Substitute e[1] for e[0] in d and assert the result equal to d
00569       Theorem thm = updateHelper(d);
00570       thm = transitivityRule(thm, rewrite(thm.getRHS()));
00571       enqueueEquality(transitivityRule(thm, find(thm.getRHS())));
00572     }
00573   }
00574 }
00575 
00576 
00577 ExprStream& TheoryRecords::print(ExprStream& os, const Expr& e)
00578 {
00579    switch(os.lang()) {
00580    case PRESENTATION_LANG: {
00581      switch(e.getOpKind()){
00582      case TUPLE:{
00583        int i=0, iend=e.arity();
00584        os << "(" << push;
00585        if(i!=iend) os << e[i];
00586        ++i;
00587        for(; i!=iend; ++i) os << push << "," << pop << space << e[i];
00588        os << push << ")";
00589        break;
00590      }
00591      case TUPLE_TYPE: {
00592        int i=0, iend=e.arity();
00593        os << "[" << push;
00594        if(i!=iend) os << e[i];
00595        ++i;
00596        for(; i!=iend; ++i) os << push << "," << pop << space << e[i];
00597        os << push << "]";
00598        break;
00599      }
00600      case RECORD: {
00601        size_t i=0, iend=e.arity();
00602        if(!isRecord(e)) {
00603          e.printAST(os);
00604          break;
00605        }
00606        const vector<Expr>& fields = getFields(e);
00607        if(iend != fields.size()) {
00608          e.printAST(os); 
00609          break;
00610        }
00611        os << "(# " << push;
00612        if(i!=iend) {
00613          os <<  fields[i] << space 
00614             << ":="<< space << push << e[i] << pop;
00615          ++i;
00616        }
00617        for(; i!=iend; ++i)
00618          os << push << "," << pop << space <<  fields[i] 
00619             << space 
00620             << ":="<< space << push << e[i] << pop;
00621        os << push << space << "#)";
00622        break;
00623      }
00624      case RECORD_TYPE: {
00625        size_t i=0, iend=e.arity();
00626        if(!isRecordType(e)) {
00627          e.printAST(os);
00628          break;
00629        }
00630        const vector<Expr>& fields = getFields(e);
00631        if(iend != fields.size()) {
00632          e.printAST(os); 
00633          break;
00634        }
00635        os << "[# " << push;
00636        if(i!=iend) {
00637          os <<  fields[i] << ":"<< space << push << e[i] << pop;
00638          ++i;
00639        }
00640        for(; i!=iend; ++i)
00641          os << push << "," << pop << space <<  fields[i] 
00642             << ":"<< space << push << e[i] << pop;
00643        os << push << space << "#]";
00644        break;
00645      }
00646      case RECORD_SELECT:
00647        if(isRecordAccess(e) && e.arity() == 1)
00648          os << "(" << push <<  e[0] << push << ")" << "." << push 
00649             << getField(e);
00650        else
00651          e.printAST(os);
00652        break;
00653      case TUPLE_SELECT:
00654        if(isTupleAccess(e) && e.arity() == 1)
00655          os << "(" << push << e[0]  << push << ")" <<   "." << push 
00656             << getIndex(e);
00657        else
00658          e.printAST(os);
00659        break;
00660      case RECORD_UPDATE:
00661        if(isRecordAccess(e) && e.arity() == 2)
00662          os << "(" << push <<  e[0] << space << "WITH ."
00663             << push << getField(e)
00664             << space << ":=" << space << push << e[1] << push << ")";
00665        else
00666          e.printAST(os);
00667        break;
00668      case TUPLE_UPDATE:
00669        if(isTupleAccess(e) && e.arity() == 2)
00670          os << "(" << push <<  e[0] << space << "WITH ."
00671             << push << getIndex(e) 
00672             << space << ":=" << space << push << e[1] << push << ")";
00673        else
00674          e.printAST(os);
00675        break;
00676      default:
00677        e.printAST(os);
00678        break;
00679      }
00680      break;
00681    }
00682    case SMTLIB_LANG: {
00683      d_theoryUsed = true;
00684      throw SmtlibException("TheoryRecords::print: SMTLIB not supported");
00685      switch(e.getOpKind()){
00686      case TUPLE:{
00687        int i=0, iend=e.arity();
00688        os << "(" << push << "TUPLE";
00689        for(; i<iend; ++i) os << space << e[i];
00690        os << push << ")";
00691        break;
00692      }
00693      case TUPLE_TYPE: { // FIXME: change to TUPLE_TYPE
00694        int i=0, iend=e.arity();
00695        os << "(" << push << "TUPLE_TYPE";
00696        for(; i!=iend; ++i) os << space << e[i];
00697        os << push << ")";
00698        break;
00699      }
00700      case RECORD: {
00701        size_t i=0, iend=e.arity();
00702        if(!isRecord(e)) {
00703          e.printAST(os);
00704          break;
00705        }
00706        const vector<Expr>& fields = getFields(e);
00707        if(iend != fields.size()) {
00708          e.printAST(os); 
00709          break;
00710        }
00711        os << "(" << push << "RECORD";
00712        for(; i!=iend; ++i)
00713          os <<  space << "(" << push << fields[i] << space 
00714             << e[i] << push << ")" << pop << pop;
00715        os << push << ")";
00716        break;
00717      }
00718      case RECORD_TYPE: {
00719        size_t i=0, iend=e.arity();
00720        if(!isRecord(e)) {
00721          e.printAST(os);
00722          break;
00723        }
00724        const vector<Expr>& fields = getFields(e);
00725        if(iend != fields.size()) {
00726          e.printAST(os); 
00727          break;
00728        }
00729        os << "(" << push << "RECORD_TYPE";
00730        for(; i!=iend; ++i)
00731          os << space << "(" << push <<  fields[i] 
00732             << space << e[i] << push << ")" << pop << pop;
00733        os << push << space << ")";
00734        break;
00735      }
00736      case RECORD_SELECT:
00737        if(isRecordAccess(e))
00738          os << "(" << push << "RECORD_SELECT" << space 
00739             << e[0] << space << getField(e) << push << ")";
00740        else
00741          e.printAST(os);
00742        break;
00743      case TUPLE_SELECT:
00744        if(isTupleAccess(e))
00745          os << "(" << push << "TUPLE_SELECT" << space
00746             << e[0] << space << getIndex(e) << push << ")";
00747        else
00748          e.printAST(os);
00749        break;
00750      case RECORD_UPDATE:
00751        if(isRecordAccess(e) && e.arity() == 2)
00752          os << "(" << push << "RECORD_UPDATE" << space
00753             << e[0] << space << getField(e) 
00754             << space << e[1] << push << ")";
00755        else
00756          e.printAST(os);
00757        break;
00758      case TUPLE_UPDATE:
00759        if(isTupleAccess(e))
00760          os << "(" << push << "TUPLE_UPDATE" << space << e[0]
00761             << space << getIndex(e) 
00762             << space << e[1] << push << ")";
00763        else
00764          e.printAST(os);
00765        break;
00766      default:
00767        e.printAST(os);
00768        break;
00769      }
00770      break;
00771    }
00772    case LISP_LANG: {
00773      switch(e.getOpKind()){
00774      case TUPLE:{
00775        int i=0, iend=e.arity();
00776        os << "(" << push << "TUPLE";
00777        for(; i<iend; ++i) os << space << e[i];
00778        os << push << ")";
00779        break;
00780      }
00781      case TUPLE_TYPE: { // FIXME: change to TUPLE_TYPE
00782        int i=0, iend=e.arity();
00783        os << "(" << push << "TUPLE_TYPE";
00784        for(; i!=iend; ++i) os << space << e[i];
00785        os << push << ")";
00786        break;
00787      }
00788      case RECORD: {
00789        size_t i=0, iend=e.arity();
00790        if(!isRecord(e)) {
00791          e.printAST(os);
00792          break;
00793        }
00794        const vector<Expr>& fields = getFields(e);
00795        if(iend != fields.size()) {
00796          e.printAST(os); 
00797          break;
00798        }
00799        os << "(" << push << "RECORD";
00800        for(; i!=iend; ++i)
00801          os <<  space << "(" << push << fields[i] << space 
00802             << e[i] << push << ")" << pop << pop;
00803        os << push << ")";
00804        break;
00805      }
00806      case RECORD_TYPE: {
00807        size_t i=0, iend=e.arity();
00808        if(!isRecord(e)) {
00809          e.printAST(os);
00810          break;
00811        }
00812        const vector<Expr>& fields = getFields(e);
00813        if(iend != fields.size()) {
00814          e.printAST(os); 
00815          break;
00816        }
00817        os << "(" << push << "RECORD_TYPE";
00818        for(; i!=iend; ++i)
00819          os << space << "(" << push <<  fields[i] 
00820             << space << e[i] << push << ")" << pop << pop;
00821        os << push << space << ")";
00822        break;
00823      }
00824      case RECORD_SELECT:
00825        if(isRecordAccess(e))
00826          os << "(" << push << "RECORD_SELECT" << space 
00827             << e[0] << space << getField(e) << push << ")";
00828        else
00829          e.printAST(os);
00830        break;
00831      case TUPLE_SELECT:
00832        if(isTupleAccess(e))
00833          os << "(" << push << "TUPLE_SELECT" << space
00834             << e[0] << space << getIndex(e) << push << ")";
00835        else
00836          e.printAST(os);
00837        break;
00838      case RECORD_UPDATE:
00839        if(isRecordAccess(e) && e.arity() == 2)
00840          os << "(" << push << "RECORD_UPDATE" << space
00841             << e[0] << space << getField(e)
00842             << space << e[1] << push << ")";
00843        else
00844          e.printAST(os);
00845        break;
00846      case TUPLE_UPDATE:
00847        if(isTupleAccess(e))
00848          os << "(" << push << "TUPLE_UPDATE" << space << e[0]
00849             << space << getIndex(e)
00850             << space << e[1] << push << ")";
00851        else
00852          e.printAST(os);
00853        break;
00854      default:
00855        e.printAST(os);
00856        break;
00857      }
00858      break;
00859    }
00860    default:
00861      e.printAST(os);
00862      break;
00863    }
00864    return os;
00865 }
00866 
00867 ///////////////////////////////////////////////////////////////////////////////
00868 //parseExprOp:
00869 //translating special Exprs to regular EXPR??
00870 ///////////////////////////////////////////////////////////////////////////////
00871 Expr
00872 TheoryRecords::parseExprOp(const Expr& e) {
00873   TRACE("parser", "TheoryRecords::parseExprOp(", e, ")");
00874   // If the expression is not a list, it must have been already
00875   // parsed, so just return it as is.
00876   if(RAW_LIST != e.getKind()) return e;
00877 
00878   DebugAssert(e.arity() > 0,
00879               "TheoryRecords::parseExprOp:\n e = "+e.toString());
00880   
00881   const Expr& c1 = e[0][0];
00882   const string& kindStr = c1.getString();
00883   int kind = e.getEM()->getKind(kindStr);
00884   switch(kind) {
00885   case RECORD_TYPE: // (RECORD_TYPE (f1 e1) (f2 e2) ...)
00886   case RECORD: {    // (RECORD      (f1 e1) (f2 e2) ...)
00887     if(e.arity() < 2)
00888       throw ParserException("Empty "+kindStr+": "+e.toString());
00889     vector<Expr> fields;
00890     vector<Expr> kids; 
00891     Expr::iterator i = e.begin(), iend=e.end();
00892     ++i;
00893     for(; i!=iend; ++i) {
00894       if(i->arity() != 2 || (*i)[0].getKind() != ID)
00895         throw ParserException("Bad field declaration in "+kindStr+": "
00896                               +i->toString()+"\n in "+e.toString());
00897       fields.push_back((*i)[0][0]);
00898       kids.push_back(parseExpr((*i)[1]));
00899     }
00900     return (kind==RECORD)? recordExpr(fields, kids)
00901       : recordType(fields, kids).getExpr();
00902   }
00903   case RECORD_SELECT: { // (RECORD_SELECT e field)
00904     if(e.arity() != 3 || e[2].getKind() != ID)
00905       throw ParserException("Field must be an ID in RECORD_SELECT: "
00906                             +e.toString());
00907     return recordSelect(parseExpr(e[1]), e[2][0].getString());
00908   }
00909   case RECORD_UPDATE: { // (RECORD_UPDATE e1 field e2)
00910     if(e.arity() != 4 || e[2].getKind() != ID)
00911       throw ParserException("Field must be an ID in RECORD_UPDATE: "
00912                             +e.toString());
00913     return recordUpdate(parseExpr(e[1]), e[2][0].getString(), parseExpr(e[3]));
00914   }
00915   case TUPLE_SELECT:  { // (TUPLE_SELECT e index)
00916     if(e.arity() != 3 || !e[2].isRational() || !e[2].getRational().isInteger())
00917       throw ParserException("Index must be an integer in TUPLE_SELECT: "
00918                             +e.toString());
00919     return tupleSelect(parseExpr(e[1]), e[2].getRational().getInt());
00920   }
00921   case TUPLE_UPDATE:  { // (TUPLE_UPDATE e1 index e2)
00922     if(e.arity() != 4 || !e[2].isRational() || !e[2].getRational().isInteger())
00923       throw ParserException("Index must be an integer in TUPLE_UPDATE: "
00924                             +e.toString());
00925     return tupleUpdate(parseExpr(e[1]), e[2].getRational().getInt(),
00926                        parseExpr(e[3]));
00927   }
00928   case TUPLE_TYPE:
00929   case TUPLE: {
00930     if(e.arity() < 2)
00931       throw ParserException("Empty "+kindStr+": "+e.toString());
00932     vector<Expr> k;
00933     Expr::iterator i = e.begin(), iend=e.end();
00934     // Skip first element of the vector of kids in 'e'.
00935     // The first element is the operator.
00936     ++i; 
00937     // Parse the kids of e and push them into the vector 'k'
00938     for(; i!=iend; ++i) 
00939       k.push_back(parseExpr(*i));
00940     return (kind==TUPLE)? tupleExpr(k) : tupleType(k).getExpr();
00941   }
00942   default:
00943     DebugAssert(false,
00944                 "TheoryRecords::parseExprOp: invalid command or expression: " + e.toString());
00945     break;
00946   }
00947   return e;
00948 }
00949 
00950 
00951 //! Create a record literal
00952 Expr
00953 TheoryRecords::recordExpr(const std::vector<std::string>& fields,
00954                           const std::vector<Expr>& kids) {
00955   vector<Expr> fieldExprs;
00956   vector<string>::const_iterator i = fields.begin(), iend = fields.end();
00957   for (; i != iend; ++i) fieldExprs.push_back(getEM()->newStringExpr(*i));
00958   return recordExpr(fieldExprs, kids);
00959 }
00960 
00961 Expr
00962 TheoryRecords::recordExpr(const std::vector<Expr>& fields,
00963                           const std::vector<Expr>& kids) {
00964   return Expr(Expr(RECORD, fields).mkOp(), kids);
00965 }
00966 
00967 //! Create a record type
00968 Type
00969 TheoryRecords::recordType(const std::vector<std::string>& fields,
00970                           const std::vector<Type>& types) {
00971   vector<Expr> kids;
00972   for(vector<Type>::const_iterator i=types.begin(), iend=types.end();
00973       i!=iend; ++i)
00974     kids.push_back(i->getExpr());
00975   return recordType(fields, kids);
00976 }
00977 
00978 //! Create a record type
00979 Type
00980 TheoryRecords::recordType(const std::vector<std::string>& fields,
00981                           const std::vector<Expr>& types) {
00982   vector<Expr> fieldExprs;
00983   vector<string>::const_iterator i = fields.begin(), iend = fields.end();
00984   for (; i != iend; ++i) fieldExprs.push_back(getEM()->newStringExpr(*i));
00985   return recordType(fieldExprs, types);
00986 }
00987 
00988 Type
00989 TheoryRecords::recordType(const std::vector<Expr>& fields,
00990                           const std::vector<Expr>& types) {
00991   return Type(Expr(Expr(RECORD_TYPE, fields).mkOp(), types));
00992 }
00993 
00994 //! Create a record field selector expression
00995 Expr
00996 TheoryRecords::recordSelect(const Expr& r, const std::string& field) {
00997   return Expr(getEM()->newSymbolExpr(field, RECORD_SELECT).mkOp(), r);
00998 }
00999 
01000 //! Create a record field update expression
01001 Expr
01002 TheoryRecords::recordUpdate(const Expr& r, const std::string& field,
01003                             const Expr& val) {
01004   return Expr(getEM()->newSymbolExpr(field, RECORD_UPDATE).mkOp(), r, val);
01005 }
01006 
01007 //! Get the list of fields from a record literal
01008 const vector<Expr>&
01009 TheoryRecords::getFields(const Expr& r) {
01010   DebugAssert(r.isApply() &&
01011               (r.getOpKind() == RECORD || r.getOpKind() == RECORD_TYPE),
01012               "TheoryRecords::getFields: Not a record literal: "
01013               +r.toString(AST_LANG));
01014   return r.getOpExpr().getKids();
01015 }
01016 
01017 // Get the i-th field name from the record literal
01018 const string&
01019 TheoryRecords::getField(const Expr& r, int i) {
01020   DebugAssert(r.isApply() && 
01021               (r.getOpKind() == RECORD || r.getOpKind() == RECORD_TYPE),
01022               "TheoryRecords::getField: Not a record literal: "
01023               +r.toString());
01024   return r.getOpExpr()[i].getString();
01025 }
01026 
01027 // Get field index from the record literal
01028 int
01029 TheoryRecords::getFieldIndex(const Expr& e, const string& field) {
01030   const vector<Expr>& fields = getFields(e);
01031   for(size_t i=0, iend=fields.size(); i<iend; ++i) {
01032     if(fields[i].getString() == field) return i;
01033   }
01034   DebugAssert(false, "TheoryRecords::getFieldIndex(e="+e.toString()
01035               +", field="+field+"): field is not found");
01036   return -1;
01037 }
01038 
01039 //! Get the field name from the record select and update expressions
01040 const std::string&
01041 TheoryRecords::getField(const Expr& r) {
01042   DebugAssert(r.isApply() && (r.getOpKind() == RECORD_SELECT ||
01043                               r.getOpKind() == RECORD_UPDATE),
01044               "TheoryRecords::getField: Not a record literal: ");
01045   return r.getOpExpr().getName();
01046 }
01047 
01048 //! Create a tuple literal
01049 Expr
01050 TheoryRecords::tupleExpr(const std::vector<Expr>& kids) {
01051   return Expr(TUPLE, kids, getEM());
01052 }
01053 
01054 //! Create a tuple type
01055 Type
01056 TheoryRecords::tupleType(const std::vector<Type>& types) {
01057   vector<Expr> kids;
01058   for(vector<Type>::const_iterator i=types.begin(), iend=types.end();
01059       i!=iend; ++i)
01060     kids.push_back(i->getExpr());
01061   return Type(Expr(TUPLE_TYPE, kids, getEM()));
01062 }
01063 
01064 //! Create a tuple type
01065 Type
01066 TheoryRecords::tupleType(const std::vector<Expr>& types) {
01067   return Expr(TUPLE_TYPE, types, getEM());
01068 }
01069 
01070 //! Create a tuple index selector expression
01071 Expr
01072 TheoryRecords::tupleSelect(const Expr& tup, int i) {
01073   return Expr(Expr(TUPLE_SELECT, getEM()->newRatExpr(i)).mkOp(), tup);
01074 }
01075 
01076 //! Create a tuple index update expression
01077 Expr
01078 TheoryRecords::tupleUpdate(const Expr& tup, int i, const Expr& val) {
01079   return Expr(Expr(TUPLE_UPDATE, getEM()->newRatExpr(i)).mkOp(), tup, val);
01080 }
01081 
01082 //! Get the index from the tuple select and update expressions
01083 int
01084 TheoryRecords::getIndex(const Expr& r) {
01085   DebugAssert(r.isApply() && (r.getOpKind() == TUPLE_SELECT ||
01086                               r.getOpKind() == TUPLE_UPDATE),
01087               "TheoryRecords::getField: Not a record literal: ");
01088   return r.getOpExpr()[0].getRational().getInt();
01089 }

Generated on Thu Apr 13 16:57:35 2006 for CVC Lite by  doxygen 1.4.4