CVC3
|
00001 /*****************************************************************************/ 00002 /*! 00003 *\file theory_datatype.cpp 00004 * 00005 * Author: Clark Barrett 00006 * 00007 * Created: Wed Dec 1 22:32:26 2004 00008 * 00009 * <hr> 00010 * 00011 * License to use, copy, modify, sell and/or distribute this software 00012 * and its documentation for any purpose is hereby granted without 00013 * royalty, subject to the terms and conditions defined in the \ref 00014 * LICENSE file provided with this distribution. 00015 * 00016 * <hr> 00017 * 00018 */ 00019 /*****************************************************************************/ 00020 00021 00022 #include "theory_datatype.h" 00023 #include "datatype_proof_rules.h" 00024 #include "typecheck_exception.h" 00025 #include "parser_exception.h" 00026 #include "smtlib_exception.h" 00027 #include "theory_core.h" 00028 #include "theory_uf.h" 00029 #include "command_line_flags.h" 00030 00031 00032 using namespace std; 00033 using namespace CVC3; 00034 00035 00036 /////////////////////////////////////////////////////////////////////////////// 00037 // TheoryDatatype Public Methods // 00038 /////////////////////////////////////////////////////////////////////////////// 00039 00040 00041 TheoryDatatype::TheoryDatatype(TheoryCore* core) 00042 : Theory(core, "Datatypes"), 00043 d_labels(core->getCM()->getCurrentContext()), 00044 d_facts(core->getCM()->getCurrentContext()), 00045 d_splitters(core->getCM()->getCurrentContext()), 00046 d_splittersIndex(core->getCM()->getCurrentContext(), 0), 00047 d_splitterAsserted(core->getCM()->getCurrentContext(), false), 00048 d_smartSplits(core->getFlags()["dt-smartsplits"].getBool()) 00049 { 00050 d_rules = createProofRules(); 00051 00052 // Register new local kinds with ExprManager 00053 getEM()->newKind(DATATYPE_DECL, "_DATATYPE_DECL"); 00054 getEM()->newKind(DATATYPE, "_DATATYPE", true); 00055 getEM()->newKind(CONSTRUCTOR, "_CONSTRUCTOR"); 00056 getEM()->newKind(SELECTOR, "_SELECTOR"); 00057 getEM()->newKind(TESTER, "_TESTER"); 00058 00059 vector<int> kinds; 00060 kinds.push_back(DATATYPE_DECL); 00061 kinds.push_back(DATATYPE); 00062 kinds.push_back(TESTER); 00063 kinds.push_back(CONSTRUCTOR); 00064 kinds.push_back(SELECTOR); 00065 00066 registerTheory(this, kinds); 00067 } 00068 00069 00070 TheoryDatatype::~TheoryDatatype() { 00071 delete d_rules; 00072 } 00073 00074 00075 void TheoryDatatype::instantiate(const Expr& e, const Unsigned& u) 00076 { 00077 DebugAssert(!e.hasFind() || findExpr(e) == e, 00078 "datatype: instantiate: Expected find(e)=e"); 00079 if (isConstructor(e)) return; 00080 DebugAssert(u != 0 && (u & (u-1)) == 0, 00081 "datatype: instantiate: Expected single label in u"); 00082 DebugAssert(d_datatypes.find(getBaseType(e).getExpr()) != d_datatypes.end(), 00083 "datatype: instantiate: Unexpected type: "+getBaseType(e).toString() 00084 +"\n\n for expression: "+e.toString()); 00085 ExprMap<unsigned>& c = d_datatypes[getBaseType(e).getExpr()]; 00086 ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end(); 00087 for (; c_it != c_end; ++c_it) { 00088 if ((u & (Unsigned(1) << (unsigned)(*c_it).second)) != 0) break; 00089 } 00090 DebugAssert(c_it != c_end, 00091 "datatype: instantiate: couldn't find constructor"); 00092 const Expr& cons = (*c_it).first; 00093 00094 if (!cons.isFinite() && !e.isSelected()) return; 00095 00096 Type consType = getBaseType(cons); 00097 if (consType.arity() == 1) { 00098 enqueueFact(d_rules->dummyTheorem(d_facts, e.eqExpr(cons))); 00099 return; 00100 } 00101 // create vars 00102 vector<Expr> vars; 00103 for (int i = 0; i < consType.arity()-1; ++i) { 00104 vars.push_back(getEM()->newBoundVarExpr(consType[i])); 00105 } 00106 Expr e2 = getEM()->newClosureExpr(EXISTS, vars, 00107 e.eqExpr(Expr(cons.mkOp(), vars))); 00108 enqueueFact(d_rules->dummyTheorem(d_facts, e2)); 00109 } 00110 00111 00112 void TheoryDatatype::initializeLabels(const Expr& e, const Type& t) 00113 { 00114 DebugAssert(findExpr(e) == e, 00115 "datatype: initializeLabels: Expected find(e)=e"); 00116 DebugAssert(d_datatypes.find(t.getExpr()) != d_datatypes.end(), 00117 "Unknown datatype: "+t.getExpr().toString()); 00118 ExprMap<unsigned>& c = d_datatypes[t.getExpr()]; 00119 DebugAssert(d_labels.find(e) == d_labels.end(), 00120 "datatype: initializeLabels: expected unlabeled expr"); 00121 if (isConstructor(e)) { 00122 Expr cons = getConstructor(e); 00123 DebugAssert(c.find(cons) != c.end(), 00124 "datatype: initializeLabels: Couldn't find constructor " 00125 +cons.toString()); 00126 d_labels.insert(e, 00127 SmartCDO<Unsigned>(theoryCore()->getCM()->getCurrentContext(), 00128 (Unsigned)1 << c[cons], 0)); 00129 } 00130 else { 00131 DebugAssert(c.size() > 0, "No constructors?"); 00132 Unsigned value = ((Unsigned)1 << c.size()) - 1; 00133 d_labels.insert(e, 00134 SmartCDO<Unsigned>(theoryCore()->getCM()->getCurrentContext(), 00135 value, 0)); 00136 if (value == 1) instantiate(e, 1); 00137 else { 00138 if (!d_smartSplits || t.getExpr().isFinite()) d_splitters.push_back(e); 00139 } 00140 } 00141 } 00142 00143 00144 void TheoryDatatype::mergeLabels(const Theorem& thm, 00145 const Expr& e1, const Expr& e2) 00146 { 00147 DebugAssert(e2.hasFind() && findExpr(e2) == e2, 00148 "datatype: mergeLabels: Expected find(e2)=e2"); 00149 DebugAssert(d_labels.find(e1) != d_labels.end() && 00150 d_labels.find(e2) != d_labels.end(), 00151 "mergeLabels: expr is not labeled"); 00152 DebugAssert(getBaseType(e1) == getBaseType(e2), "Expected same type"); 00153 Unsigned u = d_labels[e2].get().get(); 00154 Unsigned uNew = u & d_labels[e1].get().get(); 00155 if (u != uNew) { 00156 if (!thm.isNull()) d_facts.push_back(thm); 00157 d_labels[e2].get().set(uNew); 00158 if (uNew == 0) 00159 setInconsistent(d_rules->dummyTheorem(d_facts, falseExpr())); 00160 } 00161 if (uNew != 0 && ((uNew - 1) & uNew) == 0) { 00162 instantiate(e2, uNew); 00163 } 00164 } 00165 00166 00167 void TheoryDatatype::mergeLabels(const Theorem& thm, const Expr& e, 00168 unsigned position, bool positive) 00169 { 00170 DebugAssert(e.hasFind() && findExpr(e) == e, 00171 "datatype: mergeLabels2: Expected find(e)=e"); 00172 DebugAssert(d_labels.find(e) != d_labels.end(), 00173 "mergeLabels2: expr is not labeled"); 00174 Unsigned u = d_labels[e].get().get(); 00175 Unsigned uNew = (Unsigned)1 << position; 00176 if (positive) { 00177 uNew = u & uNew; 00178 if (u == uNew) return; 00179 } else if ((u & uNew) != 0) uNew = u - uNew; 00180 else return; 00181 d_facts.push_back(thm); 00182 d_labels[e].get().set(uNew); 00183 if (uNew == 0) 00184 setInconsistent(d_rules->dummyTheorem(d_facts, falseExpr())); 00185 else if (((uNew - 1) & uNew) == 0) { 00186 instantiate(e, uNew); 00187 } 00188 } 00189 00190 00191 void TheoryDatatype::addSharedTerm(const Expr& e) 00192 { 00193 if (getBaseType(e).getExpr().getKind() == DATATYPE && 00194 d_labels.find(e) == d_labels.end()) { 00195 initializeLabels(e, getBaseType(e)); 00196 e.addToNotify(this, Expr()); 00197 } 00198 } 00199 00200 00201 void TheoryDatatype::assertFact(const Theorem& e) 00202 { 00203 if (!e.isRewrite()) { 00204 const Expr& expr = e.getExpr(); 00205 if (expr.getOpKind() == TESTER) { 00206 mergeLabels(e, expr[0], 00207 getConsPos(getConsForTester(expr.getOpExpr())), 00208 true); 00209 } 00210 else if (expr.isNot()) { 00211 if (expr[0].getOpKind() == TESTER) { 00212 mergeLabels(e, expr[0][0], 00213 getConsPos(getConsForTester(expr[0].getOpExpr())), 00214 false); 00215 } 00216 else if (expr[0].isEq() && 00217 getBaseType(expr[0][0]).getExpr().getKind() == DATATYPE) { 00218 // Propagate disequality down 00219 if (d_labels.find(expr[0][0]) == d_labels.end()) { 00220 initializeLabels(expr[0][0], getBaseType(expr[0][0])); 00221 expr[0][0].addToNotify(this, Expr()); 00222 } 00223 if (d_labels.find(expr[0][1]) == d_labels.end()) { 00224 initializeLabels(expr[0][1], getBaseType(expr[0][1])); 00225 expr[0][1].addToNotify(this, Expr()); 00226 } 00227 Unsigned u1 = d_labels[expr[0][0]].get().get(); 00228 Unsigned u2 = d_labels[expr[0][1]].get().get(); 00229 ExprMap<unsigned>& c = d_datatypes[getBaseType(expr[0][0]).getExpr()]; 00230 ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end(); 00231 Expr bigConj; 00232 for (; c_it != c_end; ++c_it) { 00233 if ((u1 & u2 & ((Unsigned)1 << unsigned((*c_it).second))) != 0) { 00234 vector<Expr>& selectors = d_constructorMap[(*c_it).first]; 00235 Expr conj; 00236 for (unsigned i = 0; i < selectors.size(); ++i) { 00237 Expr e1 = Expr(selectors[i].mkOp(), expr[0][0]); 00238 Expr e2 = e1.eqExpr(Expr(selectors[i].mkOp(), expr[0][1])); 00239 if (conj.isNull()) conj = e2; 00240 else conj = conj.andExpr(e2); 00241 } 00242 if (!conj.isNull()) { 00243 Expr e1 = datatypeTestExpr((*c_it).first.getName(), expr[0][0]); 00244 Expr e2 = datatypeTestExpr((*c_it).first.getName(), expr[0][1]); 00245 conj = (e1 && e2).impExpr(!conj); 00246 if (bigConj.isNull()) bigConj = conj; 00247 else bigConj = bigConj.andExpr(conj); 00248 } 00249 } 00250 } 00251 if (!bigConj.isNull()) { 00252 enqueueFact(d_rules->dummyTheorem(d_facts, expr.impExpr(bigConj))); 00253 } 00254 } 00255 } 00256 } 00257 } 00258 00259 00260 void TheoryDatatype::checkSat(bool fullEffort) 00261 { 00262 bool done = false; 00263 while (!done && d_splittersIndex < d_splitters.size()) { 00264 Expr e = d_splitters[d_splittersIndex]; 00265 if ((!d_smartSplits || getBaseType(e).getExpr().isFinite()) && 00266 findExpr(e) == e) { 00267 DebugAssert(d_labels.find(e) != d_labels.end(), 00268 "checkSat: expr is not labeled"); 00269 Unsigned u = d_labels[e].get().get(); 00270 if ((u & (u-1)) != 0) { 00271 done = true; 00272 DebugAssert(!d_splitterAsserted || !fullEffort, 00273 "splitter should have been resolved"); 00274 if (!d_splitterAsserted) { 00275 DebugAssert 00276 (d_datatypes.find(getBaseType(e).getExpr()) != d_datatypes.end(), 00277 "datatype: checkSat: Unexpected type: "+getBaseType(e).toString() 00278 +"\n\n for expression: "+e.toString()); 00279 ExprMap<unsigned>& c = d_datatypes[getBaseType(e).getExpr()]; 00280 ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end(); 00281 vector<Expr> vec; 00282 for (; c_it != c_end; ++c_it) { 00283 if ((u & ((Unsigned)1 << unsigned((*c_it).second))) != 0) { 00284 vec.push_back(datatypeTestExpr((*c_it).first.getName(), e)); 00285 } 00286 } 00287 DebugAssert(vec.size() > 1, "datatype: checkSat: expected 2 or more possible constructors"); 00288 enqueueFact(d_rules->dummyTheorem(d_facts, Expr(OR, vec))); 00289 d_splitterAsserted = true; 00290 } 00291 } 00292 } 00293 if (d_smartSplits && !done && isSelector(e)) { 00294 Expr f = findExpr(e[0]); 00295 DebugAssert(d_labels.find(f) != d_labels.end(), 00296 "checkSat: expr is not labeled"); 00297 Unsigned u = d_labels[f].get().get(); 00298 if ((u & (u-1)) != 0) { 00299 pair<Expr, unsigned> selectorInfo = getSelectorInfo(e.getOpExpr()); 00300 unsigned pos = getConsPos(selectorInfo.first); 00301 if ((u & ((Unsigned)1 << pos)) != 0) { 00302 done = true; 00303 DebugAssert(!d_splitterAsserted || !fullEffort, 00304 "splitter should have been resolved"); 00305 if (!d_splitterAsserted) { 00306 addSplitter(datatypeTestExpr(selectorInfo.first.getName(), f)); 00307 d_splitterAsserted = true; 00308 } 00309 } 00310 } 00311 } 00312 if (!done) { 00313 d_splitterAsserted = false; 00314 d_splittersIndex = d_splittersIndex + 1; 00315 } 00316 } 00317 } 00318 00319 00320 Theorem TheoryDatatype::rewrite(const Expr& e) 00321 { 00322 // TODO: UF rewrite? 00323 Theorem thm; 00324 if (isSelector(e)) { 00325 if (canCollapse(e)) { 00326 thm = d_rules->rewriteSelCons(d_facts, e); 00327 return transitivityRule(thm, simplify(thm.getRHS())); 00328 } 00329 } 00330 else if (isTester(e)) { 00331 if (isConstructor(e[0])) { 00332 return d_rules->rewriteTestCons(e); 00333 } 00334 } 00335 return reflexivityRule(e); 00336 } 00337 00338 00339 void TheoryDatatype::setup(const Expr& e) 00340 { 00341 if (getBaseType(e).getExpr().getKind() == DATATYPE && 00342 d_labels.find(e) == d_labels.end()) { 00343 initializeLabels(e, getBaseType(e)); 00344 e.addToNotify(this, Expr()); 00345 } 00346 if (e.getKind() != APPLY) return; 00347 if (isConstructor(e) && e.arity() > 0) { 00348 enqueueFact(d_rules->noCycle(e)); 00349 } 00350 if (isSelector(e)) { 00351 if (d_smartSplits) d_splitters.push_back(e); 00352 e[0].setSelected(); 00353 mergeLabels(Theorem(), e[0], e[0]); 00354 } 00355 setupCC(e); 00356 } 00357 00358 00359 void TheoryDatatype::update(const Theorem& e, const Expr& d) 00360 { 00361 if (d.isNull()) { 00362 const Expr& lhs = e.getLHS(); 00363 const Expr& rhs = e.getRHS(); 00364 if (isConstructor(lhs) && isConstructor(rhs) && 00365 lhs.isApply() && rhs.isApply() && 00366 lhs.getOpExpr() == rhs.getOpExpr()) { 00367 enqueueFact(d_rules->decompose(e)); 00368 } 00369 else { 00370 // Possible for rhs to never have been seen: initialize it here 00371 DebugAssert(getBaseType(rhs).getExpr().getKind() == DATATYPE, 00372 "Expected datatype"); 00373 if (d_labels.find(rhs) == d_labels.end()) { 00374 initializeLabels(rhs, getBaseType(rhs)); 00375 rhs.addToNotify(this, Expr()); 00376 } 00377 Theorem thm(e); 00378 if (lhs.isSelected() && !rhs.isSelected()) { 00379 d_facts.push_back(e); 00380 rhs.setSelected(); 00381 thm = Theorem(); 00382 } 00383 mergeLabels(thm, lhs, rhs); 00384 } 00385 } 00386 else { 00387 const Theorem& dEQdsig = d.getSig(); 00388 if (!dEQdsig.isNull()) { 00389 const Expr& dsig = dEQdsig.getRHS(); 00390 Theorem thm = updateHelper(d); 00391 const Expr& sigNew = thm.getRHS(); 00392 if (sigNew == dsig) return; 00393 dsig.setRep(Theorem()); 00394 if (isSelector(sigNew) && canCollapse(sigNew)) { 00395 d.setSig(Theorem()); 00396 enqueueFact(transitivityRule(thm, d_rules->rewriteSelCons(d_facts, sigNew))); 00397 } 00398 else if (isTester(sigNew) && isConstructor(sigNew[0])) { 00399 d.setSig(Theorem()); 00400 enqueueFact(transitivityRule(thm, d_rules->rewriteTestCons(sigNew))); 00401 } 00402 else { 00403 const Theorem& repEQsigNew = sigNew.getRep(); 00404 if (!repEQsigNew.isNull()) { 00405 d.setSig(Theorem()); 00406 enqueueFact(transitivityRule(repEQsigNew, symmetryRule(thm))); 00407 } 00408 else { 00409 int k, ar(d.arity()); 00410 for (k = 0; k < ar; ++k) { 00411 if (sigNew[k] != dsig[k]) { 00412 sigNew[k].addToNotify(this, d); 00413 } 00414 } 00415 d.setSig(thm); 00416 sigNew.setRep(thm); 00417 getEM()->invalidateSimpCache(); 00418 } 00419 } 00420 } 00421 } 00422 } 00423 00424 00425 Theorem TheoryDatatype::solve(const Theorem& e) 00426 { 00427 DebugAssert(e.isRewrite() && e.getLHS().isTerm(), "Expected equality"); 00428 const Expr& lhs = e.getLHS(); 00429 if (isConstructor(lhs) && !isConstructor(e.getRHS())) { 00430 return symmetryRule(e); 00431 } 00432 return e; 00433 } 00434 00435 00436 void TheoryDatatype::checkType(const Expr& e) 00437 { 00438 switch (e.getKind()) { 00439 case DATATYPE: { 00440 if (e.arity() != 1 || !e[0].isString()) 00441 throw Exception("Ill-formed datatype"+e.toString()); 00442 if (resolveID(e[0].getString()) != e) 00443 throw Exception("Unknown datatype"+e.toString()); 00444 break; 00445 } 00446 case CONSTRUCTOR: 00447 case SELECTOR: 00448 case TESTER: 00449 throw Exception("Non-type: "+e.toString()); 00450 default: 00451 FatalAssert(false, "Unexpected kind in TheoryDatatype::checkType" 00452 +getEM()->getKindName(e.getKind())); 00453 } 00454 } 00455 00456 00457 Cardinality TheoryDatatype::finiteTypeInfo(Expr& e, Unsigned& n, 00458 bool enumerate, bool computeSize) 00459 { 00460 DebugAssert(e.getKind() == DATATYPE, 00461 "Unexpected kind in TheoryDatatype::finiteTypeInfo"); 00462 if (d_getConstantStack.count(e) != 0) { 00463 return CARD_INFINITE; 00464 } 00465 d_getConstantStack[e] = true; 00466 00467 Expr typeExpr = e; 00468 ExprMap<unsigned>& c = d_datatypes[typeExpr]; 00469 ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end(); 00470 Cardinality card = CARD_FINITE, cardTmp; 00471 bool getSize = enumerate || computeSize; 00472 Unsigned totalSize = 0, thisSize, size; 00473 vector<Unsigned> sizes; 00474 int j; 00475 00476 // Loop through constructors, and check if each one only has a finite number 00477 // of possibilities 00478 for (; c_it != c_end; ++c_it) { 00479 const Expr& cons = (*c_it).first; 00480 Expr funType = cons.getType().getExpr(); 00481 thisSize = 1; 00482 for (j = 0; j < funType.arity()-1; ++j) { 00483 Expr e2 = funType[j]; 00484 cardTmp = theoryOf(e2)->finiteTypeInfo(e2, size, false, getSize); 00485 if (cardTmp == CARD_INFINITE) { 00486 card = CARD_INFINITE; 00487 break; 00488 } 00489 else if (cardTmp == CARD_UNKNOWN) { 00490 card = CARD_UNKNOWN; 00491 getSize = false; 00492 // Keep looking to see if we can determine it is infinite 00493 } 00494 else if (getSize) { 00495 thisSize = thisSize * size; 00496 // Give up if it gets too big 00497 if (thisSize > 1000000) thisSize = 0; 00498 if (thisSize == 0) { 00499 totalSize = 0; 00500 getSize = false; 00501 } 00502 } 00503 } 00504 if (card == CARD_INFINITE) break; 00505 if (getSize) { 00506 sizes.push_back(thisSize); 00507 totalSize = totalSize + thisSize; 00508 } 00509 } 00510 00511 if (card == CARD_FINITE) { 00512 00513 if (enumerate) { 00514 c_it = c.begin(); 00515 unsigned i = 0; 00516 for (; i < sizes.size(); ++i, ++c_it) { 00517 if (n < sizes[i]) { 00518 break; 00519 } 00520 else n = n - sizes[i]; 00521 } 00522 if (i == sizes.size() && n != 0) { 00523 e = Expr(); 00524 } 00525 else { 00526 const Expr& cons = (*c_it).first; 00527 Expr funType = cons.getType().getExpr(); 00528 if (funType.arity() == 1) { 00529 e = cons; 00530 } 00531 else { 00532 vector<Expr> kids(funType.arity()-1); 00533 Unsigned thisSize; 00534 Unsigned elem; 00535 for (int j = funType.arity()-2; j >= 0; --j) { 00536 if (n == 0) { 00537 elem = 0; 00538 } 00539 else { 00540 thisSize = funType[j].typeSizeFinite(); 00541 elem = n % thisSize; 00542 n = n - elem; 00543 n = n / thisSize; 00544 } 00545 kids[j] = funType[j].typeEnumerateFinite(elem); 00546 } 00547 e = Expr(cons.mkOp(), kids); 00548 } 00549 } 00550 } 00551 00552 if (computeSize) { 00553 n = totalSize; 00554 } 00555 00556 } 00557 d_getConstantStack.erase(typeExpr); 00558 return card; 00559 } 00560 00561 00562 void TheoryDatatype::computeType(const Expr& e) 00563 { 00564 switch (e.getOpKind()) { 00565 case CONSTRUCTOR: 00566 case SELECTOR: 00567 case TESTER: { 00568 DebugAssert(e.isApply(), "Expected application"); 00569 Expr op = e.getOp().getExpr(); 00570 Type t = op.lookupType(); 00571 DebugAssert(!t.isNull(), "Expected operator to be well-typed"); 00572 if (t.getExpr().getKind() == DATATYPE) { 00573 if (e.arity() != 0) 00574 throw TypecheckException("Expected no children: "+e.toString()); 00575 e.setType(t); 00576 break; 00577 } 00578 else { 00579 DebugAssert(t.getExpr().getKind() == ARROW, "Expected function type"); 00580 if (e.arity() != t.getExpr().arity()-1) 00581 throw TypecheckException("Wrong number of children:\n"+e.toString()); 00582 Expr::iterator i = e.begin(), iend = e.end(); 00583 Expr::iterator j = t.getExpr().begin(); 00584 for (; i != iend; ++i, ++j) { 00585 if (getBaseType(*i) != getBaseType(Type(*j))) { 00586 throw TypecheckException("Type mismatch for expression:\n\n " 00587 + (*i).toString() 00588 + "\n\nhas the following type:\n\n " 00589 + (*i).getType().getExpr().toString() 00590 + "\n\nbut the expected type is:\n\n " 00591 + (*j).toString() 00592 + "\n\nin datatype function application:\n\n " 00593 + e.toString()); 00594 } 00595 } 00596 e.setType(*j); 00597 } 00598 break; 00599 } 00600 default: 00601 DebugAssert(false, "Unexpected kind in datatype::computeType: " 00602 +e.toString()); 00603 } 00604 } 00605 00606 00607 void TheoryDatatype::computeModelTerm(const Expr& e, std::vector<Expr>& v) { 00608 } 00609 00610 00611 00612 Expr TheoryDatatype::computeTCC(const Expr& e) 00613 { 00614 Expr tcc(Theory::computeTCC(e)); 00615 switch (e.getKind()) { 00616 case CONSTRUCTOR: 00617 DebugAssert(e.arity() == 0, "Expected leaf constructor"); 00618 return trueExpr(); 00619 case APPLY: { 00620 DebugAssert(e.isApply(), "Should be application"); 00621 Expr op(e.getOpExpr()); 00622 if (op.getKind() != SELECTOR) return tcc; 00623 DebugAssert(e.arity() == 1, "Expected single argument"); 00624 const std::pair<Expr,unsigned>& p = getSelectorInfo(op); 00625 Expr tester = datatypeTestExpr(p.first.getName(), e[0]); 00626 return tcc.andExpr(tester); 00627 } 00628 default: 00629 DebugAssert(false,"Unexpected type: "+e.toString()); 00630 return trueExpr(); 00631 } 00632 } 00633 00634 /////////////////////////////////////////////////////////////////////////////// 00635 // Pretty-printing // 00636 /////////////////////////////////////////////////////////////////////////////// 00637 00638 00639 ExprStream& TheoryDatatype::print(ExprStream& os, const Expr& e) { 00640 switch (os.lang()) { 00641 case PRESENTATION_LANG: 00642 switch (e.getKind()) { 00643 case DATATYPE_DECL: { 00644 os << "DATATYPE" << endl; 00645 bool first(true); 00646 for (Expr::iterator i = e.begin(), iend = e.end(); i != iend; ++i) { 00647 if (first) first = false; 00648 else os << "," << endl; 00649 os << " " << push << *i << space << "= " << push; 00650 DebugAssert(d_datatypes.find(*i) != d_datatypes.end(), 00651 "Unknown datatype: "+(*i).toString()); 00652 ExprMap<unsigned>& c = d_datatypes[*i]; 00653 ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end(); 00654 bool firstCons(true); 00655 for (; c_it != c_end; ++c_it) { 00656 if (!firstCons) { 00657 os << space << "| "; 00658 } 00659 else firstCons = false; 00660 const Expr& cons = (*c_it).first; 00661 os << cons; 00662 vector<Expr>& sels = d_constructorMap[cons]; 00663 bool firstSel(true); 00664 for (unsigned j = 0; j < sels.size(); ++j) { 00665 if (firstSel) { 00666 firstSel = false; 00667 os << "("; 00668 } else { 00669 os << ", "; 00670 } 00671 os << sels[j] << space << ": "; 00672 os << sels[j].getType().getExpr()[1]; 00673 } 00674 if (!firstSel) { 00675 os << ")"; 00676 } 00677 } 00678 os << pop; 00679 } 00680 os << pop << endl; 00681 os << "END;"; 00682 break; 00683 } 00684 case DATATYPE: 00685 if (e.arity() == 1 && e[0].isString()) { 00686 os << e[0].getString(); 00687 } 00688 else e.printAST(os); 00689 break; 00690 case APPLY: 00691 os << e.getOpExpr(); 00692 if(e.arity() > 0) { 00693 os << "(" << push; 00694 bool first(true); 00695 for (Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) { 00696 if(first) first = false; 00697 else os << "," << space; 00698 os << *i; 00699 } 00700 os << push << ")"; 00701 } 00702 break; 00703 case CONSTRUCTOR: 00704 case SELECTOR: 00705 case TESTER: 00706 DebugAssert(e.isSymbol(), "Expected symbol"); 00707 os << e.getName(); 00708 break; 00709 default: 00710 DebugAssert(false, "TheoryDatatype::print: Unexpected kind: " 00711 +getEM()->getKindName(e.getKind())); 00712 } 00713 break; 00714 case SMTLIB_LANG: 00715 FatalAssert(false, "Not Implemented Yet"); 00716 break; 00717 case LISP_LANG: 00718 FatalAssert(false, "Not Implemented Yet"); 00719 break; 00720 default: 00721 e.printAST(os); 00722 break; 00723 } 00724 return os; 00725 } 00726 00727 ////////////////////////////////////////////////////////////////////////////// 00728 //parseExprOp: 00729 //translating special Exprs to regular EXPR?? 00730 /////////////////////////////////////////////////////////////////////////////// 00731 Expr TheoryDatatype::parseExprOp(const Expr& e) 00732 { 00733 // If the expression is not a list, it must have been already 00734 // parsed, so just return it as is. 00735 if(RAW_LIST != e.getKind()) return e; 00736 00737 DebugAssert(e.arity() > 0, 00738 "TheoryDatatype::parseExprOp:\n e = "+e.toString()); 00739 00740 DebugAssert(e[0].getKind() == ID, 00741 "Expected ID kind for first elem in list expr"); 00742 00743 const Expr& c1 = e[0][0]; 00744 int kind = getEM()->getKind(c1.getString()); 00745 switch(kind) { 00746 case DATATYPE: { 00747 DebugAssert(e.arity() > 1, 00748 "Empty DATATYPE expression\n" 00749 " (expected at least one datatype): "+e.toString()); 00750 00751 vector<Expr> names; 00752 00753 vector<Expr> allConstructorNames; 00754 vector<Expr> constructorNames; 00755 00756 vector<Expr> allSelectorNames; 00757 vector<Expr> selectorNames; 00758 vector<Expr> selectorNamesKids; 00759 00760 vector<Expr> allTypes; 00761 vector<Expr> types; 00762 vector<Expr> typesKids; 00763 00764 int i,j,k; 00765 Expr dt, constructor, selectors, selector; 00766 00767 // Get names of datatypes 00768 ExprMap<bool> namesMap; 00769 for (i = 0; i < e.arity()-1; ++i) { 00770 dt = e[i+1]; 00771 DebugAssert(dt.getKind() == RAW_LIST && dt.arity() == 2, 00772 "Bad formed datatype expression" 00773 +dt.toString()); 00774 DebugAssert(dt[0].getKind() == ID, 00775 "Expected ID kind for datatype name" 00776 +dt.toString()); 00777 names.push_back(dt[0][0]); 00778 if (namesMap.count(dt[0][0]) != 0) { 00779 throw ParserException("Datatype name used more than once"+dt[0][0].getString()); 00780 } 00781 namesMap.insert(dt[0][0], true); 00782 } 00783 00784 // Loop through datatypes 00785 for (i = 0; i < e.arity()-1; ++i) { 00786 dt = e[i+1]; 00787 DebugAssert(dt[1].getKind() == RAW_LIST && dt[1].arity() > 0, 00788 "Expected non-empty list for datatype constructors" 00789 +dt.toString()); 00790 dt = dt[1]; 00791 00792 // Loop through constructors for this datatype 00793 for(j = 0; j < dt.arity(); ++j) { 00794 constructor = dt[j]; 00795 DebugAssert(constructor.getKind() == RAW_LIST && 00796 (constructor.arity() == 1 || constructor.arity() == 2), 00797 "Unexpected constructor"+constructor.toString()); 00798 DebugAssert(constructor[0].getKind() == ID, 00799 "Expected ID kind for constructor name" 00800 +constructor.toString()); 00801 constructorNames.push_back(constructor[0][0]); 00802 00803 if (constructor.arity() == 2) { 00804 selectors = constructor[1]; 00805 DebugAssert(selectors.getKind() == RAW_LIST && selectors.arity() > 0, 00806 "Non-empty list expected as second argument of constructor:\n" 00807 +constructor.toString()); 00808 00809 // Loop through selectors for this constructor 00810 for (k = 0; k < selectors.arity(); ++k) { 00811 selector = selectors[k]; 00812 DebugAssert(selector.getKind() == RAW_LIST && selector.arity() == 2, 00813 "Expected list of arity 2 for selector" 00814 +selector.toString()); 00815 DebugAssert(selector[0].getKind() == ID, 00816 "Expected ID kind for selector name" 00817 +selector.toString()); 00818 selectorNamesKids.push_back(selector[0][0]); 00819 if (selector[1].getKind() == ID && namesMap.count(selector[1][0]) > 0) { 00820 typesKids.push_back(selector[1][0]); 00821 } 00822 else { 00823 typesKids.push_back(parseExpr(selector[1])); 00824 } 00825 } 00826 selectorNames.push_back(Expr(RAW_LIST, selectorNamesKids)); 00827 selectorNamesKids.clear(); 00828 types.push_back(Expr(RAW_LIST, typesKids)); 00829 typesKids.clear(); 00830 } 00831 else { 00832 selectorNames.push_back(Expr(RAW_LIST, selectorNamesKids, getEM())); 00833 types.push_back(Expr(RAW_LIST, typesKids, getEM())); 00834 } 00835 } 00836 allConstructorNames.push_back(Expr(RAW_LIST, constructorNames)); 00837 constructorNames.clear(); 00838 allSelectorNames.push_back(Expr(RAW_LIST, selectorNames)); 00839 selectorNames.clear(); 00840 allTypes.push_back(Expr(RAW_LIST, types)); 00841 types.clear(); 00842 } 00843 00844 return Expr(DATATYPE, 00845 Expr(RAW_LIST, names), 00846 Expr(RAW_LIST, allConstructorNames), 00847 Expr(RAW_LIST, allSelectorNames), 00848 Expr(RAW_LIST, allTypes)); 00849 } 00850 00851 default: { 00852 throw ParserException("Unexpected datatype expression: "+e.toString()); 00853 } 00854 } 00855 return e; 00856 } 00857 00858 00859 Expr TheoryDatatype::dataType(const string& name, 00860 const vector<string>& constructors, 00861 const vector<vector<string> >& selectors, 00862 const vector<vector<Expr> >& types) 00863 { 00864 vector<string> names; 00865 vector<vector<string> > constructors2; 00866 vector<vector<vector<string> > > selectors2; 00867 vector<vector<vector<Expr> > > types2; 00868 names.push_back(name); 00869 constructors2.push_back(constructors); 00870 selectors2.push_back(selectors); 00871 types2.push_back(types); 00872 return dataType(names, constructors2, selectors2, types2); 00873 } 00874 00875 00876 // Elements of types are either the expr from an existing type or a string 00877 // naming one of the datatypes being defined 00878 Expr TheoryDatatype::dataType(const vector<string>& names, 00879 const vector<vector<string> >& allConstructors, 00880 const vector<vector<vector<string> > >& allSelectors, 00881 const vector<vector<vector<Expr> > >& allTypes) 00882 { 00883 vector<Expr> returnTypes; 00884 00885 // bool wellFounded = false, infinite = false, 00886 bool thisWellFounded; 00887 00888 if (names.size() != allConstructors.size() || 00889 allConstructors.size() != allSelectors.size() || 00890 allSelectors.size() != allTypes.size()) { 00891 throw TypecheckException 00892 ("dataType: vector sizes don't match"); 00893 } 00894 00895 unsigned i, j, k; 00896 Expr e; 00897 00898 // Create reachability predicate for constructor cycle detection 00899 vector<Type> funTypeArgs; 00900 funTypeArgs.push_back(Type::anyType(getEM())); 00901 funTypeArgs.push_back(Type::anyType(getEM())); 00902 Op op = newFunction("_reach_"+names[0], 00903 Type::funType(funTypeArgs, boolType()), 00904 true /* compute trans closure */); 00905 Op reach = getEM()->newSymbolExpr(op.getExpr().getName(), 00906 TRANS_CLOSURE).mkOp(); 00907 00908 for (i = 0; i < names.size(); ++i) { 00909 e = resolveID(names[i]); 00910 if (!e.isNull()) { 00911 throw TypecheckException 00912 ("Attempt to define datatype "+names[i]+":\n " 00913 "This variable is already defined."); 00914 } 00915 e = Expr(DATATYPE, getEM()->newStringExpr(names[i])); 00916 installID(names[i], e); 00917 returnTypes.push_back(e); 00918 d_reach[e] = reach; 00919 } 00920 00921 vector<Expr> selectorVec; 00922 00923 for (i = 0; i < names.size(); ++i) { 00924 00925 const vector<string>& constructors = allConstructors[i]; 00926 const vector<vector<string> >& selectors = allSelectors[i]; 00927 const vector<vector<Expr> >& types = allTypes[i]; 00928 00929 if (constructors.size() == 0) { 00930 throw TypecheckException 00931 ("datatype: "+names[i]+": must have at least one constructor"); 00932 } 00933 if (constructors.size() != selectors.size() || 00934 selectors.size() != types.size()) { 00935 throw TypecheckException 00936 ("dataType: vector sizes at index "+int2string(i)+" don't match"); 00937 } 00938 00939 ExprMap<unsigned>& constMap = d_datatypes[returnTypes[i]]; 00940 00941 for (j = 0; j < constructors.size(); ++j) { 00942 Expr c = resolveID(constructors[j]); 00943 if (!c.isNull()) { 00944 throw TypecheckException 00945 ("Attempt to define datatype constructor "+constructors[j]+":\n " 00946 "This variable is already defined."); 00947 } 00948 c = getEM()->newSymbolExpr(constructors[j], CONSTRUCTOR); 00949 00950 if (selectors[j].size() != types[j].size()) { 00951 throw TypecheckException 00952 ("dataType: constructor at index "+int2string(i)+", "+int2string(j)+ 00953 ": number of selectors does not match number of types"); 00954 } 00955 thisWellFounded = true; 00956 const vector<string>& sels = selectors[j]; 00957 const vector<Expr>& tps = types[j]; 00958 00959 vector<Type> selTypes; 00960 Type t; 00961 Expr s; 00962 for (k = 0; k < sels.size(); ++k) { 00963 s = resolveID(sels[k]); 00964 if (!s.isNull()) { 00965 throw TypecheckException 00966 ("Attempt to define datatype selector "+sels[k]+":\n " 00967 "This variable is already defined."); 00968 } 00969 s = getEM()->newSymbolExpr(sels[k], SELECTOR); 00970 if (tps[k].isString()) { 00971 t = Type(resolveID(tps[k].getString())); 00972 if (t.isNull()) { 00973 throw TypecheckException 00974 ("Unable to resolve type identifier: "+tps[k].getString()); 00975 } 00976 } else t = Type(tps[k]); 00977 if (t.isBool()) { 00978 throw TypecheckException 00979 ("Cannot have BOOLEAN inside of datatype"); 00980 } 00981 else if (t.isFunction()) { 00982 throw TypecheckException 00983 ("Cannot have function inside of datatype"); 00984 } 00985 00986 selTypes.push_back(Type(t)); 00987 s.setType(Type(returnTypes[i]).funType(Type(t))); 00988 if (isDatatype(Type(t)) && !t.getExpr().isWellFounded()) { 00989 thisWellFounded = false; 00990 } 00991 d_selectorMap[s] = pair<Expr,unsigned>(c,k); 00992 installID(sels[k], s); 00993 selectorVec.push_back(s); 00994 } 00995 if (thisWellFounded) c.setWellFounded(); 00996 if (selTypes.size() == 0) { 00997 c.setType(Type(returnTypes[i])); 00998 c.setFinite(); 00999 } 01000 else c.setType(Type::funType(selTypes, Type(returnTypes[i]))); 01001 installID(constructors[j], c); 01002 constMap[c] = j; 01003 d_constructorMap[c] = selectorVec; 01004 selectorVec.clear(); 01005 01006 string testerString = "is_"+constructors[j]; 01007 e = resolveID(testerString); 01008 if (!e.isNull()) { 01009 throw TypecheckException 01010 ("Attempt to define datatype tester "+testerString+":\n " 01011 "This variable is already defined."); 01012 } 01013 e = getEM()->newSymbolExpr(testerString, TESTER); 01014 e.setType(Type(returnTypes[i]).funType(boolType())); 01015 d_testerMap[e] = c; 01016 installID(testerString, e); 01017 } 01018 } 01019 01020 // Compute fixed point for wellfoundedness check 01021 01022 bool changed, thisFinite; 01023 int firstNotWellFounded; 01024 do { 01025 changed = false; 01026 firstNotWellFounded = -1; 01027 for (i = 0; i < names.size(); ++i) { 01028 ExprMap<unsigned>& c = d_datatypes[returnTypes[i]]; 01029 ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end(); 01030 thisWellFounded = false; 01031 thisFinite = true; 01032 for (; c_it != c_end; ++c_it) { 01033 const Expr& cons = (*c_it).first; 01034 Expr funType = getBaseType(cons).getExpr(); 01035 int j; 01036 if (!cons.isFinite()) { 01037 for (j = 0; j < funType.arity()-1; ++j) { 01038 if (!isDatatype(funType[j]) || !funType[j].isFinite()) 01039 break; 01040 } 01041 if (j == funType.arity()-1) { 01042 changed = true; 01043 cons.setFinite(); 01044 } 01045 else thisFinite = false; 01046 } 01047 if (cons.isWellFounded()) { 01048 thisWellFounded = true; 01049 continue; 01050 } 01051 for (j = 0; j < funType.arity()-1; ++j) { 01052 if (isDatatype(funType[j]) && !funType[j].isWellFounded()) 01053 break; 01054 } 01055 if (j == funType.arity()-1) { 01056 changed = true; 01057 cons.setWellFounded(); 01058 thisWellFounded = true; 01059 } 01060 } 01061 if (!thisWellFounded) { 01062 if (firstNotWellFounded == -1) firstNotWellFounded = i; 01063 } 01064 else { 01065 if (!returnTypes[i].isWellFounded()) { 01066 changed = true; 01067 returnTypes[i].setWellFounded(); 01068 } 01069 } 01070 if (thisFinite && !returnTypes[i].isFinite()) { 01071 changed = true; 01072 returnTypes[i].setFinite(); 01073 } 01074 } 01075 } while (changed); 01076 01077 if (firstNotWellFounded >= 0) { 01078 // TODO: uninstall all ID's 01079 throw TypecheckException 01080 ("Datatype "+names[firstNotWellFounded]+" has no finite terms"); 01081 } 01082 01083 return Expr(DATATYPE_DECL, returnTypes); 01084 } 01085 01086 Expr TheoryDatatype::datatypeConsExpr(const string& constructor, 01087 const vector<Expr>& args) 01088 { 01089 Expr e = resolveID(constructor); 01090 if (e.isNull()) 01091 throw Exception("datatype: unknown constructor: "+constructor); 01092 if (!(e.isSymbol() && e.getKind() == CONSTRUCTOR)) 01093 throw Exception("datatype: "+constructor+" resolves to: "+e.toString()+ 01094 "\nwhich is not a constructor"); 01095 if (args.size() == 0) return e; 01096 return Expr(e.mkOp(), args); 01097 } 01098 01099 01100 Expr TheoryDatatype::datatypeSelExpr(const string& selector, const Expr& arg) 01101 { 01102 Expr e = resolveID(selector); 01103 if (e.isNull()) 01104 throw Exception("datatype: unknown selector: "+selector); 01105 if (!(e.isSymbol() && e.getKind() == SELECTOR)) 01106 throw Exception("datatype: "+selector+" resolves to: "+e.toString()+ 01107 "\nwhich is not a selector"); 01108 return Expr(e.mkOp(), arg); 01109 } 01110 01111 01112 Expr TheoryDatatype::datatypeTestExpr(const string& constructor, const Expr& arg) 01113 { 01114 Expr e = resolveID("is_"+constructor); 01115 if (e.isNull()) 01116 throw Exception("datatype: unknown tester: is_"+constructor); 01117 if (!(e.isSymbol() && e.getKind() == TESTER)) 01118 throw Exception("datatype: is_"+constructor+" resolves to: "+e.toString()+ 01119 "\nwhich is not a tester"); 01120 return Expr(e.mkOp(), arg); 01121 } 01122 01123 01124 const pair<Expr,unsigned>& TheoryDatatype::getSelectorInfo(const Expr& e) 01125 { 01126 DebugAssert(e.getKind() == SELECTOR, "getSelectorInfo called on non-selector: " 01127 +e.toString()); 01128 DebugAssert(d_selectorMap.find(e) != d_selectorMap.end(), 01129 "Unknown selector: "+e.toString()); 01130 return d_selectorMap[e]; 01131 } 01132 01133 01134 Expr TheoryDatatype::getConsForTester(const Expr& e) 01135 { 01136 DebugAssert(e.getKind() == TESTER, 01137 "getConsForTester called on non-tester" 01138 +e.toString()); 01139 DebugAssert(d_testerMap.find(e) != d_testerMap.end(), 01140 "Unknown tester: "+e.toString()); 01141 return d_testerMap[e]; 01142 } 01143 01144 01145 unsigned TheoryDatatype::getConsPos(const Expr& e) 01146 { 01147 DebugAssert(e.getKind() == CONSTRUCTOR, 01148 "getConsPos called on non-constructor"); 01149 Type t = getBaseType(e); 01150 if (t.isFunction()) t = t[t.arity()-1]; 01151 DebugAssert(isDatatype(t), "Expected datatype"); 01152 DebugAssert(d_datatypes.find(t.getExpr()) != d_datatypes.end(), 01153 "Could not find datatype: "+t.toString()); 01154 ExprMap<unsigned>& constMap = d_datatypes[t.getExpr()]; 01155 DebugAssert(constMap.find(e) != constMap.end(), 01156 "Could not find constructor: "+e.toString()); 01157 return constMap[e]; 01158 } 01159 01160 01161 Expr TheoryDatatype::getConstant(const Type& t) 01162 { 01163 // if a cycle is detected, backtrack from this branch 01164 if (d_getConstantStack.count(t.getExpr()) != 0) { 01165 return Expr(); 01166 } 01167 DebugAssert(d_getConstantStack.size() < 1000, 01168 "TheoryDatatype::getconstant: too deep recursion depth"); 01169 d_getConstantStack[t.getExpr()] = true; 01170 if (isDatatype(t)) { 01171 DebugAssert(d_datatypes.find(t.getExpr()) != d_datatypes.end(), 01172 "Unknown datatype: "+t.getExpr().toString()); 01173 ExprMap<unsigned>& c = d_datatypes[t.getExpr()]; 01174 ExprMap<unsigned>::iterator i = c.begin(), iend = c.end(); 01175 for (; i != iend; ++i) { 01176 const Expr& cons = (*i).first; 01177 if (!getBaseType(cons).isFunction()) { 01178 d_getConstantStack.erase(t.getExpr()); 01179 return cons; 01180 } 01181 } 01182 for (i = c.begin(), iend = c.end(); i != iend; ++i) { 01183 const Expr& cons = (*i).first; 01184 Expr funType = getBaseType(cons).getExpr(); 01185 vector<Expr> args; 01186 int j = 0; 01187 for (; j < funType.arity()-1; ++j) { 01188 Type t_j = Type(funType[j]); 01189 if (t_j == t || isDatatype(t_j)) break; 01190 args.push_back(getConstant(t_j)); 01191 DebugAssert(!args.back().isNull(), "Expected non-null"); 01192 } 01193 if (j == funType.arity()-1) { 01194 d_getConstantStack.erase(t.getExpr()); 01195 return Expr(cons.mkOp(), args); 01196 } 01197 } 01198 for (i = c.begin(), iend = c.end(); i != iend; ++i) { 01199 const Expr& cons = (*i).first; 01200 Expr funType = getBaseType(cons).getExpr(); 01201 vector<Expr> args; 01202 int j = 0; 01203 for (; j < funType.arity()-1; ++j) { 01204 Type t_j = Type(funType[j]); 01205 if (t_j == t) break; 01206 args.push_back(getConstant(t_j)); 01207 if (args.back().isNull()) break; 01208 } 01209 if (j == funType.arity()-1) { 01210 d_getConstantStack.erase(t.getExpr()); 01211 return Expr(cons.mkOp(), args); 01212 } 01213 } 01214 FatalAssert(false, "Couldn't find constant for" 01215 +t.toString()); 01216 } 01217 DebugAssert(!t.isBool() && !t.isFunction(), 01218 "Expected non-bool, non-function type"); 01219 //TODO: this name could be an illegal identifier (i.e. could include spaces) 01220 string name = "datatype_"+t.getExpr().toString(); 01221 Expr e = resolveID(name); 01222 d_getConstantStack.erase(t.getExpr()); 01223 if (e.isNull()) return newVar(name, t); 01224 return e; 01225 } 01226 01227 01228 const Op& TheoryDatatype::getReachablePredicate(const Type& t) 01229 { 01230 DebugAssert(isDatatype(t), "Expected datatype"); 01231 DebugAssert(d_reach.find(t.getExpr()) != d_reach.end(), 01232 "Couldn't find reachable predicate"); 01233 return d_reach[t.getExpr()]; 01234 } 01235 01236 01237 bool TheoryDatatype::canCollapse(const Expr& e) 01238 { 01239 DebugAssert(isSelector(e), "canCollapse: Selector expression expected"); 01240 DebugAssert(e.arity() == 1, "expected arity 1"); 01241 if (isConstructor(e[0])) return true; 01242 if (d_labels.find(e[0]) == d_labels.end()) return false; 01243 DebugAssert(e[0].hasFind() && findExpr(e[0]) == e[0], 01244 "canCollapse: Expected find(e[0])=e[0]"); 01245 Unsigned u = d_labels[e[0]].get().get(); 01246 Expr cons = getSelectorInfo(e.getOpExpr()).first; 01247 Unsigned uCons = (Unsigned)1 << unsigned(getConsPos(cons)); 01248 if ((u & uCons) == 0) return true; 01249 return false; 01250 }