theory_datatype2.cpp

Go to the documentation of this file.
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  * Copyright (C) 2003 by the Board of Trustees of Leland Stanford
00011  * Junior University and by New York University. 
00012  *
00013  * License to use, copy, modify, sell and/or distribute this software
00014  * and its documentation for any purpose is hereby granted without
00015  * royalty, subject to the terms and conditions defined in the \ref
00016  * LICENSE file provided with this distribution.  In particular:
00017  *
00018  * - The above copyright notice and this permission notice must appear
00019  * in all copies of the software and related documentation.
00020  *
00021  * - THE SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY WARRANTIES,
00022  * EXPRESSED OR IMPLIED.  USE IT AT YOUR OWN RISK.
00023  * 
00024  * <hr>
00025  * 
00026  */
00027 /*****************************************************************************/
00028 
00029 
00030 #include "theory_datatype.h"
00031 #include "datatype_proof_rules.h"
00032 #include "typecheck_exception.h"
00033 #include "parser_exception.h"
00034 #include "smtlib_exception.h"
00035 #include "theory_core.h"
00036 
00037 
00038 using namespace std;
00039 using namespace CVCL;
00040 
00041 
00042 ///////////////////////////////////////////////////////////////////////////////
00043 // TheoryDatatype Public Methods                                             //
00044 ///////////////////////////////////////////////////////////////////////////////
00045 
00046 
00047 TheoryDatatype::TheoryDatatype(TheoryCore* core)
00048   : Theory(core, "Datatypes"),
00049     d_facts(core->getCM()->getCurrentContext())
00050 {
00051   d_rules = createProofRules();
00052 
00053   // Register new local kinds with ExprManager
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);
00061   kinds.push_back(TESTER);
00062   kinds.push_back(CONSTRUCTOR);
00063   kinds.push_back(SELECTOR);
00064 
00065   registerTheory(this, kinds);
00066 }
00067 
00068 
00069 TheoryDatatype::~TheoryDatatype() {
00070   delete d_rules;
00071 }
00072 
00073 
00074 void TheoryDatatype::instantiate(const Expr& e, const bigunsigned& u)
00075 {
00076   DebugAssert(e.hasFind() && findExpr(e) == e,
00077               "datatype: instantiate: Expected find(e)=e");
00078   if (isConstructor(e)) return;
00079   DebugAssert(u != 0 && (u & (u-1)) == 0,
00080               "datatype: instantiate: Expected single label in u");
00081   DebugAssert(d_datatypes.find(e.getType().getExpr()) != d_datatypes.end(),
00082               "datatype: instantiate: Unexpected type: "+e.getType().toString()
00083               +"\n\n for expression: "+e.toString());
00084   ExprMap<unsigned>& c = d_datatypes[e.getType().getExpr()];
00085   ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end();
00086   for (; c_it != c_end; ++c_it) {
00087     if (u & (1 << bigunsigned((*c_it).second))) break;
00088   }
00089   DebugAssert(c_it != c_end,
00090               "datatype: instantiate: couldn't find constructor");
00091   Expr cons = (*c_it).first;
00092 
00093   Type consType = cons.getType();
00094   if (consType.arity() == 1) {
00095     enqueueFact(d_rules->dummyTheorem(d_facts, e.eqExpr(cons)));
00096     return;
00097   }
00098   // create vars
00099   vector<Expr> vars;
00100   for (int i = 0; i < consType.arity()-1; ++i) {
00101     vars.push_back(getEM()->newBoundVarExpr(consType[i]));
00102   }
00103   Expr e2 = getEM()->newClosureExpr(EXISTS, vars,
00104                                     e.eqExpr(Expr(cons.mkOp(), vars)));
00105   enqueueFact(d_rules->dummyTheorem(d_facts, e2));
00106 }
00107 
00108 
00109 void TheoryDatatype::initializeLabels(const Expr& e, const Type& t)
00110 {
00111   DebugAssert(findExpr(e) == e,
00112               "datatype: initializeLabels: Expected find(e)=e");
00113   DebugAssert(d_datatypes.find(t.getExpr()) != d_datatypes.end(),
00114               "Unknown datatype: "+t.getExpr().toString());
00115   ExprMap<unsigned>& c = d_datatypes[t.getExpr()];
00116   DebugAssert(d_labels.find(e) == d_labels.end(),
00117               "datatype: initializeLabels: expected unlabeled expr");
00118   if (isConstructor(e)) {
00119     Expr cons = getConstructor(e);
00120     DebugAssert(c.find(cons) != c.end(),
00121                 "datatype: initializeLabels: Couldn't find constructor "
00122                 +cons.toString());
00123     bigunsigned position = c[cons];
00124     d_labels[e] =
00125       SmartCDO<bigunsigned>(theoryCore()->getCM()->getCurrentContext(),
00126                             1 << position, 0);
00127   }
00128   else {
00129     DebugAssert(c.size() > 0, "No constructors?");
00130     bigunsigned value = (1 << bigunsigned(c.size())) - 1;
00131     d_labels[e] =
00132       SmartCDO<bigunsigned>(theoryCore()->getCM()->getCurrentContext(),
00133                             value, 0);
00134     if (value == 1) instantiate(e, 1);
00135   }
00136 }
00137 
00138 
00139 void TheoryDatatype::mergeLabels(const Expr& e1, const Expr& e2)
00140 {
00141   DebugAssert(e2.hasFind() && findExpr(e2) == e2,
00142               "datatype: mergeLabels: Expected find(e2)=e2");
00143   DebugAssert(d_labels.find(e1) != d_labels.end() &&
00144               d_labels.find(e2) != d_labels.end(),
00145               "mergeLabels: expr is not labeled");
00146   DebugAssert(e1.getType() == e2.getType(), "Expected same type");
00147   bigunsigned u = d_labels[e2].get();
00148   bigunsigned uNew = u & d_labels[e1].get();
00149   if (u != uNew) {
00150     d_labels[e2].set(uNew);
00151     if (uNew == 0)
00152       setInconsistent(d_rules->dummyTheorem(d_facts, falseExpr()));
00153     else if (((uNew - 1) & uNew) == 0) {
00154       instantiate(e2, uNew);
00155     }
00156   }
00157 }
00158 
00159 
00160 void TheoryDatatype::mergeLabels(const Expr& e, unsigned position, bool positive)
00161 {
00162   DebugAssert(e.hasFind() && findExpr(e) == e,
00163               "datatype: mergeLabels2: Expected find(e)=e");
00164   DebugAssert(d_labels.find(e) != d_labels.end(),
00165               "mergeLabels2: expr is not labeled");
00166   bigunsigned u = d_labels[e].get();
00167   bigunsigned uNew = 1 << bigunsigned(position);
00168   if (positive) {
00169     uNew = u & uNew;
00170     if (u == uNew) return;
00171   } else if (u & uNew) uNew = u - uNew;
00172   else return;
00173   d_labels[e].set(uNew);
00174   if (uNew == 0)
00175     setInconsistent(d_rules->dummyTheorem(d_facts, falseExpr()));
00176   else if (((uNew - 1) & uNew) == 0) {
00177     instantiate(e, uNew);
00178   }
00179 }
00180 
00181 
00182 void TheoryDatatype::addSharedTerm(const Expr& e)
00183 {
00184   if (e.getType().getExpr().getKind() == DATATYPE &&
00185       d_labels.find(e) == d_labels.end()) {
00186     initializeLabels(e, e.getType());
00187     e.addToNotify(this, Expr());
00188   }
00189 }
00190 
00191 
00192 void TheoryDatatype::assertFact(const Theorem& e)
00193 {
00194   if (!e.isRewrite()) {
00195     const Expr& expr = e.getExpr();
00196     if (expr.getOpKind() == TESTER) {
00197       d_facts.push_back(e);
00198       mergeLabels(expr[0],
00199                   getConsPos(getConsForTester(expr.getOpExpr())),
00200                   true);
00201     }
00202     else if (expr.isNot() && expr[0].getOpKind() == TESTER) {
00203       d_facts.push_back(e);
00204       mergeLabels(expr[0][0],
00205                   getConsPos(getConsForTester(expr[0].getOpExpr())),
00206                   false);
00207     }
00208   }
00209 }
00210 
00211 
00212 void TheoryDatatype::checkSat(bool fullEffort)
00213 {
00214 }
00215 
00216 
00217 Theorem TheoryDatatype::rewrite(const Expr& e)
00218 {
00219   Theorem thm;
00220   if (isSelector(e)) {
00221     if (isConstructor(e[0])) {
00222       thm = d_rules->rewriteSelCons(e);
00223       return transitivityRule(thm, simplify(thm.getRHS()));
00224     }
00225   }
00226   else if (isTester(e)) {
00227     if (isConstructor(e[0])) {
00228       return d_rules->rewriteTestCons(e);
00229     }
00230   }
00231   return reflexivityRule(e);
00232 }
00233 
00234 
00235 void TheoryDatatype::setup(const Expr& e)
00236 {
00237   if (e.getType().getExpr().getKind() == DATATYPE &&
00238       d_labels.find(e) == d_labels.end()) {
00239     initializeLabels(e, e.getType());
00240     e.addToNotify(this, Expr());
00241   }
00242   if (e.getKind() != APPLY) return;
00243   setupCC(e);
00244 }
00245 
00246 
00247 void TheoryDatatype::update(const Theorem& e, const Expr& d)
00248 {
00249   if (d.isNull()) {
00250     d_facts.push_back(e);
00251     mergeLabels(e.getLHS(), e.getRHS());
00252   }
00253   else {
00254     const Theorem& dEQdsig = d.getSig();
00255     if (!dEQdsig.isNull()) {
00256       const Expr& dsig = dEQdsig.getRHS();
00257       Theorem thm = updateHelper(d);
00258       const Expr& sigNew = thm.getRHS();
00259       if (sigNew == dsig) return;
00260       dsig.setRep(Theorem());
00261       if (isSelector(sigNew) && isConstructor(sigNew[0])) {
00262         d.setSig(Theorem());
00263         enqueueFact(transitivityRule(thm, d_rules->rewriteSelCons(sigNew)));
00264       }
00265       else if (isTester(sigNew) && isConstructor(sigNew[0])) {
00266         d.setSig(Theorem());
00267         enqueueFact(transitivityRule(thm, d_rules->rewriteTestCons(sigNew)));
00268       }
00269       else {
00270         const Theorem& repEQsigNew = sigNew.getRep();
00271         if (!repEQsigNew.isNull()) {
00272           d.setSig(Theorem());
00273           enqueueFact(transitivityRule(repEQsigNew, symmetryRule(thm)));
00274         }
00275         else {
00276           int k, ar(d.arity());
00277           for (k = 0; k < ar; ++k) {
00278             if (sigNew[k] != dsig[k]) {
00279               sigNew[k].addToNotify(this, d);
00280             }
00281           }
00282           d.setSig(thm);
00283           sigNew.setRep(thm);
00284         }
00285       }
00286     }
00287   }
00288 }
00289 
00290 
00291 Theorem TheoryDatatype::solve(const Theorem& e)
00292 {
00293   DebugAssert(e.isRewrite() && e.getLHS().isTerm(), "Expected equality");
00294   const Expr& lhs = e.getLHS();
00295   if (isConstructor(lhs) && !isConstructor(e.getRHS())) {
00296     return symmetryRule(e);
00297   }
00298   return e;
00299 }
00300 
00301 
00302 void TheoryDatatype::checkType(const Expr& e)
00303 {
00304   switch (e.getKind()) {
00305     case DATATYPE: {
00306       if (e.arity() != 1 || !e[0].isString())
00307         throw Exception("Ill-formed datatype"+e.toString());
00308       if (resolveID(e[0].getString()) != e)
00309         throw Exception("Unknown datatype"+e.toString());
00310       break;
00311     }
00312     case CONSTRUCTOR:
00313     case SELECTOR:
00314     case TESTER:
00315       throw Exception("Non-type: "+e.toString());
00316     default:
00317       DebugAssert(false, "Unexpected kind in TheoryDatatype::checkType"
00318                   +getEM()->getKindName(e.getKind()));
00319   }
00320 }
00321 
00322 
00323 void TheoryDatatype::computeType(const Expr& e)
00324 {
00325   switch (e.getOpKind()) {
00326     case CONSTRUCTOR:
00327     case SELECTOR:
00328     case TESTER: {
00329       DebugAssert(e.isApply(), "Expected application");
00330       Expr op = e.getOp().getExpr();
00331       Type t = op.lookupType();
00332       DebugAssert(!t.isNull(), "Expected operator to be well-typed");
00333       if (t.getExpr().getKind() == DATATYPE) {
00334         if (e.arity() != 0)
00335           throw TypecheckException("Expected no children: "+e.toString());
00336         e.setType(t);
00337         break;
00338       }
00339       else {
00340         DebugAssert(t.getExpr().getKind() == ARROW, "Expected function type");
00341         if (e.arity() != t.getExpr().arity()-1)
00342           throw TypecheckException("Wrong number of children:\n"+e.toString());
00343         Expr::iterator i = e.begin(), iend = e.end();
00344         Expr::iterator j = t.getExpr().begin();
00345         Expr arg;
00346         for (; i != iend; ++i, ++j) {
00347           arg = getBaseType(*i).getExpr();
00348           if (arg != getBaseType(*j)) {
00349             throw TypecheckException("Type mismatch for expression:\n\n  "
00350                                      + (*i).toString()
00351                                      + "\n\nhas the following type:\n\n  "
00352                                      + (*i).getType().getExpr().toString()
00353                                      + "\n\nbut the expected type is:\n\n  "
00354                                      + (*j).toString()
00355                                      + "\n\nin datatype function application:\n\n  "
00356                                      + e.toString());
00357           }
00358         }
00359         e.setType(*j);
00360       }
00361       break;
00362     }
00363     default:
00364       DebugAssert(false, "Unexpected kind in datatype::computeType: "
00365                   +e.toString());
00366   }
00367 }
00368 
00369 
00370 void TheoryDatatype::computeModelTerm(const Expr& e, std::vector<Expr>& v) {
00371 }
00372 
00373 
00374 
00375 Expr TheoryDatatype::computeTCC(const Expr& e)
00376 {
00377   return trueExpr();
00378 }
00379 
00380 ///////////////////////////////////////////////////////////////////////////////
00381 // Pretty-printing                                                           //
00382 ///////////////////////////////////////////////////////////////////////////////
00383 
00384 
00385 ExprStream& TheoryDatatype::print(ExprStream& os, const Expr& e) {
00386   switch (os.lang()) {
00387     case PRESENTATION_LANG:
00388       switch (e.getKind()) {
00389         case DATATYPE:
00390           if (e.arity() == 1 && e[0].isString()) {
00391             os << e[0].getString();
00392           }
00393           else e.printAST(os);
00394           break;
00395         case APPLY:
00396           os << e.getOpExpr();
00397           if(e.arity() > 0) {
00398             os << "(" << push;
00399             bool first(true);
00400             for (Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) {
00401               if(first) first = false;
00402               else os << "," << space;
00403               os << *i;
00404             }
00405             os << push << ")";
00406           }
00407           break;
00408         case CONSTRUCTOR:
00409         case SELECTOR:
00410         case TESTER:
00411           DebugAssert(e.isSymbol(), "Expected symbol");
00412           os << e.getName();
00413           break;
00414         default:
00415           DebugAssert(false, "TheoryDatatype::print: Unexpected kind: "
00416                       +getEM()->getKindName(e.getKind()));
00417       }
00418       break;
00419     case SMTLIB_LANG:
00420       FatalAssert(false, "Not Implemented Yet");
00421       break;
00422     case LISP_LANG:
00423       FatalAssert(false, "Not Implemented Yet");
00424       break;
00425     default:
00426       e.printAST(os);
00427       break;
00428   }
00429   return os;
00430 }
00431 
00432 //////////////////////////////////////////////////////////////////////////////
00433 //parseExprOp:
00434 //translating special Exprs to regular EXPR??
00435 ///////////////////////////////////////////////////////////////////////////////
00436 Expr TheoryDatatype::parseExprOp(const Expr& e)
00437 {
00438   // If the expression is not a list, it must have been already
00439   // parsed, so just return it as is.
00440   if(RAW_LIST != e.getKind()) return e;
00441 
00442   DebugAssert(e.arity() > 0,
00443               "TheoryDatatype::parseExprOp:\n e = "+e.toString());
00444   
00445   DebugAssert(e[0].getKind() == ID,
00446               "Expected ID kind for first elem in list expr");
00447 
00448   const Expr& c1 = e[0][0];
00449   int kind = getEM()->getKind(c1.getString());
00450   switch(kind) {
00451     case DATATYPE: {
00452       DebugAssert(e.arity() > 1,
00453                   "Empty DATATYPE expression\n"
00454                   " (expected at least one datatype): "+e.toString());
00455 
00456       vector<string> names;
00457       vector<vector<string> > allConstructorNames(e.arity()-1);
00458       vector<vector<vector<string> > > allSelectorNames(e.arity()-1);
00459       vector<vector<vector<Expr> > > allTypes(e.arity()-1);
00460       int i,j,k;
00461       Expr dt, constructor, selectors, selector;
00462 
00463       // Get names of datatypes
00464       ExprMap<bool> namesMap;
00465       for (i = 0; i < e.arity()-1; ++i) {
00466         dt = e[i+1];
00467         DebugAssert(dt.getKind() == RAW_LIST && dt.arity() == 2,
00468                     "Bad formed datatype expression"
00469                     +dt.toString());
00470         DebugAssert(dt[0].getKind() == ID,
00471                     "Expected ID kind for datatype name"
00472                     +dt.toString());
00473         names.push_back(dt[0][0].getString());
00474         if (namesMap.count(dt[0][0]) != 0) {
00475           throw ParserException("Datatype name used more than once"+names.back());
00476         }
00477         namesMap.insert(dt[0][0], true);
00478       }
00479 
00480       // Loop through datatypes
00481       for (i = 0; i < e.arity()-1; ++i) {
00482         dt = e[i+1];
00483         DebugAssert(dt[1].getKind() == RAW_LIST && dt[1].arity() > 0,
00484                     "Expected non-empty list for datatype constructors"
00485                     +dt.toString());
00486         dt = dt[1];
00487         vector<string>& constructorNames = allConstructorNames[i];
00488         vector<vector<string> >& selectorNames = allSelectorNames[i];
00489         selectorNames.resize(dt.arity());
00490         vector<vector<Expr> >& types = allTypes[i];
00491         types.resize(dt.arity());
00492         
00493         // Loop through constructors for this datatype
00494         for(j = 0; j < dt.arity(); ++j) {
00495           constructor = dt[j];
00496           DebugAssert(constructor.getKind() == RAW_LIST &&
00497                       (constructor.arity() == 1 || constructor.arity() == 2),
00498                     "Unexpected constructor"+constructor.toString());
00499           DebugAssert(constructor[0].getKind() == ID,
00500                       "Expected ID kind for constructor name"
00501                       +constructor.toString());
00502           constructorNames.push_back(constructor[0][0].getString());
00503 
00504           if (constructor.arity() == 2) {
00505             selectors = constructor[1];
00506             DebugAssert(selectors.getKind() == RAW_LIST && selectors.arity() > 0,
00507                         "Non-empty list expected as second argument of constructor:\n"
00508                         +constructor.toString());
00509 
00510             // Loop through selectors for this constructor
00511             for (k = 0; k < selectors.arity(); ++k) {
00512               selector = selectors[k];
00513               DebugAssert(selector.getKind() == RAW_LIST && selector.arity() == 2,
00514                           "Expected list of arity 2 for selector"
00515                           +selector.toString());
00516               DebugAssert(selector[0].getKind() == ID,
00517                           "Expected ID kind for selector name"
00518                           +selector.toString());
00519               selectorNames[j].push_back(selector[0][0].getString());
00520               DebugAssert(selector[1].getKind() == ID,
00521                           "Expected ID kind for selector type"
00522                           +selector.toString());
00523               if (namesMap.count(selector[1][0]) > 0) {
00524                 types[j].push_back(selector[1][0]);
00525               }
00526               else {              
00527                 types[j].push_back(parseExpr(selector[1]));
00528               }
00529             }
00530           }
00531         }
00532       }
00533 
00534       vector<Type> returnTypes;
00535       dataType(names, allConstructorNames, allSelectorNames, allTypes,
00536                returnTypes);
00537       return returnTypes[0].getExpr();
00538     }
00539 
00540     default: {
00541       throw ParserException("Unexpected datatype expression: "+e.toString());
00542     }
00543   }
00544   return e;
00545 }
00546 
00547 
00548 Type TheoryDatatype::dataType(const string& name,
00549                               const vector<string>& constructors,
00550                               const vector<vector<string> >& selectors,
00551                               const vector<vector<Expr> >& types)
00552 {
00553   vector<string> names;
00554   vector<vector<string> > constructors2;
00555   vector<vector<vector<string> > > selectors2;
00556   vector<vector<vector<Expr> > > types2;
00557   vector<Type> returnTypes;
00558   names.push_back(name);
00559   constructors2.push_back(constructors);
00560   selectors2.push_back(selectors);
00561   types2.push_back(types);
00562   dataType(names, constructors2, selectors2, types2, returnTypes);
00563   return returnTypes[0];
00564 }
00565  
00566 
00567 // Elements of types are either the expr from an existing type or a string
00568 // naming one of the datatypes being defined
00569 void TheoryDatatype::dataType(const vector<string>& names,
00570                               const vector<vector<string> >& allConstructors,
00571                               const vector<vector<vector<string> > >& allSelectors,
00572                               const vector<vector<vector<Expr> > >& allTypes,
00573                               vector<Type>& returnTypes)
00574 {
00575   //  bool wellFounded = false, infinite = false, 
00576   bool thisWellFounded;
00577 
00578   if (names.size() != allConstructors.size() ||
00579       allConstructors.size() != allSelectors.size() ||
00580       allSelectors.size() != allTypes.size()) {
00581     throw TypecheckException
00582       ("dataType: vector sizes don't match");
00583   }
00584 
00585   unsigned i, j, k;
00586   Expr e;
00587 
00588   for (i = 0; i < names.size(); ++i) {
00589     e = resolveID(names[i]);
00590     if (!e.isNull()) {
00591       throw TypecheckException
00592         ("Attempt to define datatype "+names[i]+":\n "
00593          "This variable is already defined.");
00594     }
00595     e = Expr(DATATYPE, getEM()->newStringExpr(names[i]));
00596     installID(names[i], e);
00597     returnTypes.push_back(Type(e));
00598   }
00599 
00600   for (i = 0; i < names.size(); ++i) {
00601 
00602     const vector<string>& constructors = allConstructors[i];
00603     const vector<vector<string> >& selectors = allSelectors[i];
00604     const vector<vector<Expr> >& types = allTypes[i];
00605 
00606     if (constructors.size() == 0) {
00607       throw TypecheckException
00608         ("datatype: "+names[i]+": must have at least one constructor");
00609     }
00610     if (constructors.size() != selectors.size() ||
00611         selectors.size() != types.size()) {
00612       throw TypecheckException
00613         ("dataType: vector sizes at index "+int2string(i)+" don't match");
00614     }
00615 
00616     ExprMap<unsigned>& constMap = d_datatypes[returnTypes[i].getExpr()];
00617 
00618     for (j = 0; j < constructors.size(); ++j) {
00619       Expr c = resolveID(constructors[j]);
00620       if (!c.isNull()) {
00621         throw TypecheckException
00622           ("Attempt to define datatype constructor "+constructors[j]+":\n "
00623            "This variable is already defined.");
00624       }
00625       c = getEM()->newSymbolExpr(constructors[j], CONSTRUCTOR);
00626 
00627       if (selectors[j].size() != types[j].size()) {
00628         throw TypecheckException
00629           ("dataType: constructor at index "+int2string(i)+", "+int2string(j)+
00630            ": number of selectors does not match number of types");
00631       }
00632       thisWellFounded = true;
00633       const vector<string>& sels = selectors[j];
00634       const vector<Expr>& tps = types[j];
00635 
00636       vector<Type> selTypes;
00637       Type t;
00638       Expr s;
00639       for (k = 0; k < sels.size(); ++k) {
00640         s = resolveID(sels[k]);
00641         if (!s.isNull()) {
00642           throw TypecheckException
00643             ("Attempt to define datatype selector "+sels[k]+":\n "
00644              "This variable is already defined.");
00645         }
00646         s = getEM()->newSymbolExpr(sels[k], SELECTOR);
00647         if (tps[k].isString()) {
00648           t = Type(resolveID(tps[k].getString()));
00649           if (t.isNull()) {
00650             throw TypecheckException
00651               ("Unable to resolve type identifier: "+tps[k].getString());
00652           }
00653         } else t = Type(tps[k]);
00654         if (t.isBool()) {
00655           throw TypecheckException
00656             ("Cannot have BOOLEAN inside of datatype");
00657         }
00658         else if (t.isFunction()) {
00659           throw TypecheckException
00660             ("Cannot have function inside of datatype");
00661         }
00662         
00663         selTypes.push_back(Type(t));
00664         s.setType(returnTypes[i].funType(Type(t)));
00665         if (isDatatype(Type(t)) && !t.getExpr().isWellFounded()) {
00666           thisWellFounded = false;
00667         }
00668         d_selectorMap[s] = pair<Expr,unsigned>(c,k);
00669         installID(sels[k], s);
00670       }
00671       if (thisWellFounded) c.setWellFounded();
00672       if (selTypes.size() == 0) c.setType(returnTypes[i]);
00673       else c.setType(Type::funType(selTypes, returnTypes[i]));
00674       installID(constructors[j], c);
00675       constMap[c] = j;
00676 
00677       string testerString = "is_"+constructors[j];
00678       e = resolveID(testerString);
00679       if (!e.isNull()) {
00680         throw TypecheckException
00681           ("Attempt to define datatype tester "+testerString+":\n "
00682            "This variable is already defined.");
00683       }
00684       e = getEM()->newSymbolExpr(testerString, TESTER);
00685       e.setType(returnTypes[i].funType(boolType()));
00686       d_testerMap[e] = c;
00687       installID(testerString, e);
00688     }
00689   }
00690 
00691   // Compute fixed point for wellfoundedness check
00692 
00693   bool changed;
00694   int firstNotWellFounded;
00695   do {
00696     changed = false;
00697     firstNotWellFounded = -1;
00698     for (i = 0; i < names.size(); ++i) {
00699       ExprMap<unsigned>& c = d_datatypes[returnTypes[i].getExpr()];
00700       ExprMap<unsigned>::iterator c_it = c.begin(), c_end = c.end();
00701       thisWellFounded = false;
00702       for (; c_it != c_end; ++c_it) {
00703         const Expr& cons = (*c_it).first;
00704         if (cons.isWellFounded()) {
00705           thisWellFounded = true;
00706           continue;
00707         }
00708         Expr funType = cons.getType().getExpr();
00709         int j = 0;
00710         for (; j < funType.arity()-1; ++j) {
00711           if (isDatatype(funType[j]) && !funType[j].isWellFounded())
00712             break;
00713         }
00714         if (j == funType.arity()-1) {
00715           changed = true;
00716           cons.setWellFounded();
00717           thisWellFounded = true;
00718         }
00719       }
00720       if (!thisWellFounded) {
00721         if (firstNotWellFounded == -1) firstNotWellFounded = i;
00722       }
00723       else {
00724         if (!returnTypes[i].getExpr().isWellFounded()) {
00725           changed = true;
00726           returnTypes[i].getExpr().setWellFounded();
00727         }
00728       }
00729     }
00730   } while (changed);
00731 
00732   if (firstNotWellFounded >= 0) {
00733     // TODO: uninstall all ID's
00734     throw TypecheckException
00735       ("Datatype "+names[firstNotWellFounded]+" has no finite terms");
00736   }
00737 
00738 }
00739 
00740 Expr TheoryDatatype::datatypeConsExpr(const string& constructor,
00741                                       const vector<Expr>& args)
00742 {
00743   Expr e = resolveID(constructor);
00744   if (e.isNull())
00745     throw Exception("datatype: unknown constructor: "+constructor);
00746   if (!(e.isSymbol() && e.getKind() == CONSTRUCTOR))
00747     throw Exception("datatype: "+constructor+" resolves to: "+e.toString()+
00748                     "\nwhich is not a constructor");
00749   if (args.size() == 0) return e;
00750   return Expr(e.mkOp(), args);
00751 }
00752 
00753 
00754 Expr TheoryDatatype::datatypeSelExpr(const string& selector, const Expr& arg)
00755 {
00756   Expr e = resolveID(selector);
00757   if (e.isNull())
00758     throw Exception("datatype: unknown selector: "+selector);
00759   if (!(e.isSymbol() && e.getKind() == SELECTOR))
00760     throw Exception("datatype: "+selector+" resolves to: "+e.toString()+
00761                     "\nwhich is not a selector");
00762   return Expr(e.mkOp(), arg);
00763 }
00764 
00765 
00766 Expr TheoryDatatype::datatypeTestExpr(const string& constructor, const Expr& arg)
00767 {
00768   Expr e = resolveID("is_"+constructor);
00769   if (e.isNull())
00770     throw Exception("datatype: unknown tester: id_"+constructor);
00771   if (!(e.isSymbol() && e.getKind() == TESTER))
00772     throw Exception("datatype: is_"+constructor+" resolves to: "+e.toString()+
00773                     "\nwhich is not a tester");
00774   return Expr(e.mkOp(), arg);
00775 }
00776 
00777 
00778 const pair<Expr,unsigned>& TheoryDatatype::getSelectorInfo(const Expr& e)
00779 {
00780   DebugAssert(e.getKind() == SELECTOR, "getSelectorInfo called on non-selector: "
00781               +e.toString());
00782   DebugAssert(d_selectorMap.find(e) != d_selectorMap.end(),
00783               "Unknown selector: "+e.toString());
00784   return d_selectorMap[e];
00785 }
00786 
00787 
00788 Expr TheoryDatatype::getConsForTester(const Expr& e)
00789 {
00790   DebugAssert(e.getKind() == TESTER,
00791               "getConsForTester called on non-tester"
00792               +e.toString());
00793   DebugAssert(d_testerMap.find(e) != d_testerMap.end(),
00794               "Unknown tester: "+e.toString());
00795   return d_testerMap[e];
00796 }
00797 
00798 
00799 unsigned TheoryDatatype::getConsPos(const Expr& e)
00800 {
00801   DebugAssert(e.getKind() == CONSTRUCTOR,
00802               "getConsPos called on non-constructor");
00803   Type t = e.getType();
00804   if (t.isFunction()) t = t[t.arity()-1];
00805   DebugAssert(isDatatype(t), "Expected datatype");
00806   DebugAssert(d_datatypes.find(t.getExpr()) != d_datatypes.end(),
00807               "Could not find datatype: "+t.toString());
00808   ExprMap<unsigned>& constMap = d_datatypes[t.getExpr()];
00809   DebugAssert(constMap.find(e) != constMap.end(),
00810               "Could not find constructor: "+e.toString());
00811   return constMap[e];
00812 }
00813 
00814 
00815 Expr TheoryDatatype::getConstant(const Type& t)
00816 {
00817   if (isDatatype(t)) {
00818    DebugAssert(d_datatypes.find(t.getExpr()) != d_datatypes.end(),
00819                "Unknown datatype: "+t.getExpr().toString());
00820    ExprMap<unsigned>& c = d_datatypes[t.getExpr()];
00821    ExprMap<unsigned>::iterator i = c.begin(), iend = c.end();
00822    for (; i != iend; ++i) {
00823      const Expr& cons = (*i).first;
00824      if (!cons.isWellFounded()) continue;
00825      if (!cons.getType().isFunction()) return cons;
00826      Expr funType = cons.getType().getExpr();
00827      vector<Expr> args;
00828      for (int j = 0; j < funType.arity()-1; ++j) {
00829        Type t_j = Type(funType[j]);
00830        args.push_back(getConstant(t_j));
00831      }
00832      return Expr(cons.mkOp(), args);
00833    }
00834    DebugAssert(false, "Couldn't find well-founded constructor for"
00835                +t.toString());
00836   }
00837   DebugAssert(!t.isBool() && !t.isFunction(),
00838               "Expected non-bool, non-function type");
00839   string name = "datatype_"+t.getExpr().toString();
00840   Expr e = resolveID(name);
00841   if (e.isNull()) return newVar(name, t);
00842   return e;
00843 }

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