00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #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
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
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
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
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);
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
00503 if (e.isTerm()) {
00504 switch(e.getOpKind()) {
00505 case RECORD:
00506 case TUPLE:
00507 setupCC(e);
00508 break;
00509 default: {
00510 for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i)
00511 i->addToNotify(this, e);
00512
00513 Type tp(getBaseType(e));
00514 Theorem thm;
00515 if(isRecordType(tp))
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
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
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
00562 updateCC(e, d);
00563 break;
00564 default:
00565
00566
00567 if (find(d).getRHS() == d) {
00568
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: {
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: {
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
00869
00870
00871 Expr
00872 TheoryRecords::parseExprOp(const Expr& e) {
00873 TRACE("parser", "TheoryRecords::parseExprOp(", e, ")");
00874
00875
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:
00886 case RECORD: {
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: {
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: {
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: {
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: {
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
00935
00936 ++i;
00937
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
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
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
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
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
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
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
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
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
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
01049 Expr
01050 TheoryRecords::tupleExpr(const std::vector<Expr>& kids) {
01051 return Expr(TUPLE, kids, getEM());
01052 }
01053
01054
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
01065 Type
01066 TheoryRecords::tupleType(const std::vector<Expr>& types) {
01067 return Expr(TUPLE_TYPE, types, getEM());
01068 }
01069
01070
01071 Expr
01072 TheoryRecords::tupleSelect(const Expr& tup, int i) {
01073 return Expr(Expr(TUPLE_SELECT, getEM()->newRatExpr(i)).mkOp(), tup);
01074 }
01075
01076
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
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 }