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