relStatement.h

Go to the documentation of this file.
00001 /*
00002  * CrocoPat is a tool for relational programming.
00003  * This file is part of CrocoPat. 
00004  *
00005  * Copyright (C) 2002-2008  Dirk Beyer
00006  *
00007  * CrocoPat is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * CrocoPat is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with CrocoPat; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  * Please find the GNU Lesser General Public License in file
00022  * License_LGPL.txt or at http://www.gnu.org/licenses/lgpl.txt
00023  *
00024  * Author:
00025  * Dirk Beyer (firstname.lastname@sfu.ca)
00026  * Simon Fraser University
00027  *
00028  * With contributions of: Andreas Noack, Michael Vogel
00029  */
00030 
00031 #include "relPrintExpr.h"
00032 
00034 class relStatement : public relObject
00035 {
00036 public:
00037   virtual void
00038   interpret(bddSymTab* pSymTab) = 0;
00039 };
00040 
00042 class relStmtSeq : public relStatement
00043 {
00044 private:
00045   relStatement* mStmt1;
00046   relStatement* mStmt2;
00047 
00048 public:
00049   relStmtSeq(relStatement* pStmt1, relStatement* pStmt2)
00050     : mStmt1(pStmt1),
00051       mStmt2(pStmt2)
00052   {}
00053 
00054   ~relStmtSeq()
00055   {
00056     delete mStmt1;
00057     delete mStmt2;
00058   }
00059 
00060   virtual void
00061   interpret(bddSymTab* pSymTab)
00062   {
00063     mStmt1->interpret(pSymTab);
00064     mStmt2->interpret(pSymTab);
00065   }
00066 };
00067 
00069 class relStmtAssign : public relStatement
00070 {
00071 private:
00073   string*           mRelVar;
00074   // LHS.
00075   vector<relTerm*>* mTermList;
00076   // RHS.
00077   relExpression*    mExpr;
00078 
00079 public:
00080   relStmtAssign(string* pRelVar, 
00081                 vector<relTerm*>* pTermList, 
00082                 relExpression* pExpr)
00083     : mRelVar(pRelVar),
00084       mTermList(pTermList),
00085       mExpr(pExpr)
00086   {}
00087 
00088   ~relStmtAssign()
00089   {
00090     delete mRelVar;
00091     for( vector<relTerm*>::iterator 
00092          lIt = mTermList->begin();
00093          lIt != mTermList->end();
00094          ++lIt)
00095     {
00096       delete *lIt;
00097     }
00098     delete mTermList;
00099     delete mExpr;
00100   }
00101 
00102   virtual void
00103   interpret(bddSymTab* pSymTab)
00104   {
00105     { // Check if the free attributes in the expression match
00106       //   the attributes on the left hand side.
00107       set<string> lFreeAttrs   = mExpr->collectFreeAttrs();
00108       
00109       // For all attributes on the left hand side ...
00110       for( vector<relTerm*>::const_iterator lIt = mTermList->begin();
00111            lIt != mTermList->end();
00112            ++lIt)
00113       {
00114         if (dynamic_cast<relTermAttribute*>(*lIt) != NULL) {
00115           // (*lIt) is an attribute.
00116           string lAttr = (*lIt)->interpret(pSymTab);
00117           set<string>::iterator found = lFreeAttrs.find(lAttr);
00118           if ( found == lFreeAttrs.end()) {
00119             cerr << "Error: Attribute '" << lAttr 
00120                  << "' occurs on the left hand side of an assignment," << endl
00121                  << "but does not occur free in the expression on the right hand side." << endl;
00122             exit(EXIT_FAILURE);
00123           }
00124           lFreeAttrs.erase(found);
00125         }
00126       }
00127       if (lFreeAttrs.size() > 0) {
00128         cerr << "Error: The following attributes occur free in the expression" << endl
00129              << "on the right hand side of an assignment, but do not occur on the left side: ";
00130         copy(lFreeAttrs.begin(), 
00131              lFreeAttrs.end(), 
00132              ostream_iterator<string>(cerr, " "));
00133         cerr << endl;
00134         exit(EXIT_FAILURE);
00135       }
00136     }
00137     
00138     bddRelation lExprResult  = mExpr->interpret(pSymTab);
00139     
00140     // Relation for elimination of the (one) cofactor specified 
00141     //   by the constants.
00142     bddRelation lEliminateCofactor(pSymTab, true);
00143 
00144     // Rename user attributes to the internal attributes.
00145     //   Ordering: From top to bottom, for efficiency.
00146     for(unsigned i = 0; i < mTermList->size(); ++i)
00147     {
00148       const string lTerm = (*mTermList)[i]->interpret(pSymTab);
00149       if ( dynamic_cast<relTermAttribute*>( (*mTermList)[i] ) != NULL )
00150       {
00151         // lTerm is an attribute.
00152         // Add internal attribute to SymTab, if new.
00153         pSymTab->addAttribute(gAttributePrefix + unsigned2string(i)); 
00154 
00155         // Rename.
00156         lExprResult.rename(lTerm,
00157                            gAttributePrefix + unsigned2string(i));
00158       }
00159       else if (dynamic_cast<relTermStrExpr*>((*mTermList)[i]) != NULL)
00160       {
00161         // lTerm is a string constant.
00162         //   We have to eliminate the old cofactor for the given constant.
00163         // Remember the cofactor of constant 'lTerm' 
00164         //   for elimination from old relation.
00165         lEliminateCofactor.intersect(bddRelation::mkAttributeValue(
00166                                          pSymTab, 
00167                                          gAttributePrefix + unsigned2string(i), 
00168                                          lTerm)
00169                                      );
00170 
00171         // Restrict new relation to cofactor of constant.
00172         lExprResult.intersect(bddRelation::mkAttributeValue(
00173                                  pSymTab, 
00174                                  gAttributePrefix + unsigned2string(i), 
00175                                  lTerm)
00176                               );
00177       }
00178       else
00179       {
00180         // Everything else is invalid term expression.
00181         assert(false);
00182       }
00183     }
00184     lEliminateCofactor.complement();
00185 
00186     // Fetch old value.
00187     map<string, relDataType*>::const_iterator lVarIt = gVariables.find(*mRelVar);
00188     assert(lVarIt != gVariables.end());  // Must be declared.
00189     assert(lVarIt->second != NULL);
00190     if (dynamic_cast<bddRelationConst*>(lVarIt->second) != NULL) {
00191       // For constant relations TRUE and FALSE.
00192       cerr << "Error: Constant relation '" << *mRelVar << "'" << endl
00193            << "must not appear on the left hand side of an assignment." << endl;
00194       exit(EXIT_FAILURE);
00195     }
00196     bddRelation* lResult = dynamic_cast<bddRelation*>(lVarIt->second);
00197     assert(lResult != NULL);             // Must be a REL variable.
00198     // Change value.
00199     lResult->intersect(lEliminateCofactor);
00200     lResult->unite(lExprResult);
00201 
00202     // Some type checking: Track arity.
00203     lResult->mArity = mTermList->size();
00204 
00205     pSymTab->removeUserAttributes(gAttributePrefix);
00206   } // end interpret.
00207 };
00208 
00210 class relStmtAssignNum : public relStatement
00211 {
00212 private:
00213   string* mVar;
00214   relNumExpr* mExpr;
00215 
00216 public:
00217   relStmtAssignNum(string* pVar, 
00218                    relNumExpr* pExpr)
00219     : mVar(pVar),
00220       mExpr(pExpr)
00221   {}
00222 
00223   ~relStmtAssignNum()
00224   {
00225     delete mVar;
00226     delete mExpr;
00227   }
00228 
00229   virtual void
00230   interpret(bddSymTab* pSymTab)
00231   {
00232     relNumber lExprResult = mExpr->interpret(pSymTab);
00233 
00234     // Fetch old value.
00235     map<string, relDataType*>::const_iterator lVarIt = gVariables.find(*mVar);
00236     assert(lVarIt != gVariables.end());  // Must be declared.
00237     assert(lVarIt->second != NULL);
00238     relNumber* lResult = dynamic_cast<relNumber*>(lVarIt->second);
00239     assert(lResult != NULL);             // Must be a INT variable.
00240     // Change value.
00241     *lResult = lExprResult;
00242 
00243     pSymTab->removeUserAttributes(gAttributePrefix);
00244   } // end interpret.
00245 };
00246 
00248 class relStmtAssignStr : public relStatement
00249 {
00250 private:
00251   string* mVar;
00252   relStrExpr* mExpr;
00253 
00254 public:
00255   relStmtAssignStr(string* pVar, 
00256                    relStrExpr* pExpr)
00257     : mVar(pVar),
00258       mExpr(pExpr)
00259   {}
00260 
00261   ~relStmtAssignStr()
00262   {
00263     delete mVar;
00264     delete mExpr;
00265   }
00266 
00267   virtual void
00268   interpret(bddSymTab* pSymTab)
00269   {
00270     relString lExprResult = mExpr->interpret(pSymTab);
00271 
00272     // Fetch old value.
00273     map<string, relDataType*>::const_iterator lVarIt = gVariables.find(*mVar);
00274     assert(lVarIt != gVariables.end());  // Must be declared.
00275     assert(lVarIt->second != NULL);
00276     relString* lResult = dynamic_cast<relString*>(lVarIt->second);
00277     assert(lResult != NULL);             // Must be a STRING variable.
00278     // Change value.
00279     *lResult = lExprResult;
00280 
00281     pSymTab->removeUserAttributes(gAttributePrefix);
00282   } // end interpret.
00283 };
00284 
00286 class relStmtPrint : public relStatement
00287 {
00288 private:
00289   relPrintExpr* mPrintExpr;
00290   ostream*      mOut;
00291   relStrExpr*   mFilename;
00292 
00293 public:
00294   relStmtPrint(relPrintExpr* pPrintExpr, ostream* pOut, relStrExpr* pFilename)
00295     : mPrintExpr(pPrintExpr),
00296       mOut(pOut),
00297       mFilename(pFilename)
00298   {}
00299 
00300   ~relStmtPrint()
00301   {
00302     delete mPrintExpr;
00303     delete mFilename;
00304   }
00305 
00306   virtual void
00307   interpret(bddSymTab* pSymTab)
00308   {
00309     // Set the current output stream.
00310     if (mOut == NULL) {  // Use not stdout or stderr.
00311       const string lFileName = mFilename->interpret(pSymTab).getValue();
00312       if(lFileName == "") {
00313             cerr << "Error: Empty filename given." << endl;
00314             exit(EXIT_FAILURE);
00315       }
00316       // Open extra file with the given name, append then to that file.
00317       ofstream lStream;
00318       lStream.open(lFileName.c_str(), ofstream::out | ofstream::app);
00319       mPrintExpr->interpret(pSymTab, &lStream);
00320       lStream.close();
00321     } else {
00322       mPrintExpr->interpret(pSymTab, mOut);
00323     }
00324     pSymTab->removeUserAttributes(gAttributePrefix);
00325   }
00326 };
00327 
00329 class relStmtExec : public relStatement
00330 {
00331 private:
00332 relStrExpr* mExpr;
00333 
00334 public:
00335   relStmtExec(relStrExpr* pExpr)
00336     : mExpr(pExpr)
00337   {}
00338 
00339   ~relStmtExec()
00340   {
00341     delete mExpr;
00342   }
00343 
00344   virtual void
00345   interpret(bddSymTab* pSymTab)
00346   {
00347     int lExitCode = system(mExpr->interpret(pSymTab).getValue().c_str());
00348     if (lExitCode == -1) {
00349       perror("\nExternal program execution error");
00350       exit(128);
00351     }
00352     // Fetch old value.
00353     map<string, relDataType*>::const_iterator lVarIt = gVariables.find("exitStatus");
00354     assert(lVarIt != gVariables.end());  // Must be declared.
00355     assert(lVarIt->second != NULL);
00356     relNumber* lResult = dynamic_cast<relNumber*>(lVarIt->second);
00357     assert(lResult != NULL);             // Must be a NUM variable.
00358     // Change value.
00359     lResult->setValue(lExitCode);
00360   }
00361 };
00362 
00364 class relStmtIf : public relStatement
00365 {
00366 private:
00367   relExpression*   mExpr;
00368   relStatement*    mStmtThen;
00369   relStatement*    mStmtElse;
00370 public:
00371   relStmtIf(relExpression* pExpr, 
00372                         relStatement* pStmtThen,
00373                         relStatement* pStmtElse)
00374     : mExpr(pExpr),
00375       mStmtThen(pStmtThen),
00376       mStmtElse(pStmtElse)
00377   {}
00378 
00379   ~relStmtIf()
00380   {
00381     delete mExpr;
00382     delete mStmtThen;
00383     delete mStmtElse;
00384   }
00385 
00386   virtual void
00387   interpret(bddSymTab* pSymTab)
00388   {
00389     bddRelation lCondition = mExpr->interpret(pSymTab);
00390     pSymTab->removeUserAttributes(gAttributePrefix);
00391     if ( ! lCondition.setEqual(bddRelation(pSymTab, true)) &&
00392          ! lCondition.setEqual(bddRelation(pSymTab, false))   ) {
00393       if (gPrintWarnings) {
00394             cerr << "Warning: Boolean expression expected after IF. "
00395                  << "Quantify free attributes." << endl;        
00396       }
00397     }
00398     if ( lCondition.setEqual(bddRelation(pSymTab, true)) ) {
00399       mStmtThen->interpret(pSymTab);
00400     } else {
00401       mStmtElse->interpret(pSymTab);
00402     }   
00403   }
00404 };
00405 
00407 class relStmtWhile : public relStatement
00408 {
00409 private:
00410   relExpression*  mExpr;
00411   relStatement*    mStmt;
00412 public:
00413   relStmtWhile(relExpression* pExpr, 
00414                            relStatement* pStmt)
00415     : mExpr(pExpr),
00416       mStmt(pStmt)
00417   {}
00418 
00419   ~relStmtWhile()
00420   {
00421     delete mExpr;
00422     delete mStmt;
00423   }
00424 
00425   virtual void
00426   interpret(bddSymTab* pSymTab)
00427   {
00428     bddRelation lCondition = mExpr->interpret(pSymTab);
00429     pSymTab->removeUserAttributes(gAttributePrefix);
00430     if ( ! lCondition.setEqual(bddRelation(pSymTab, true)) &&
00431          ! lCondition.setEqual(bddRelation(pSymTab, false))   ) {
00432       if (gPrintWarnings) {
00433         cerr << "Warning: Boolean expression expected after WHILE. "
00434              << "Quantify free attributes." << endl;            
00435       }
00436     }
00437     while( lCondition.setEqual(bddRelation(pSymTab, true)) )
00438     {
00439       mStmt->interpret(pSymTab);
00440       
00441       lCondition = mExpr->interpret(pSymTab);
00442       pSymTab->removeUserAttributes(gAttributePrefix);
00443     } 
00444   }
00445 };
00446 
00448 class relStmtFor : public relStatement
00449 {
00450 private:
00451   string*        mStrVar;
00452   relExpression* mExpr;
00453   relStatement*  mStmt;
00454 
00455 public:
00456   relStmtFor(string*        pStrVar,
00457              relExpression* pExpr, 
00458              relStatement*  pStmt)
00459     : mStrVar(pStrVar),
00460       mExpr(pExpr),
00461       mStmt(pStmt)
00462   {}
00463 
00464   ~relStmtFor()
00465   {
00466     delete mStrVar;
00467     delete mExpr;
00468     delete mStmt;
00469   }
00470 
00471   virtual void
00472   interpret(bddSymTab* pSymTab)
00473   {
00474     // First evaluate, to set variables in the variable ordering.
00475     bddRelation lRel = mExpr->interpret(pSymTab);
00476     const set<string> lFree = mExpr->collectFreeAttrs();
00477 
00478     if(lFree.size() != 1) {
00479       cerr << "Error: FOR statement requires one free attribute (i.e. a set)." 
00480            << endl;
00481           exit(EXIT_FAILURE);
00482     }
00483     const unsigned lVarId = pSymTab->getAttributePos(*lFree.begin());
00484 
00485     // Enable free usage of all attributes within the body.
00486     pSymTab->removeUserAttributes(gAttributePrefix);
00487 
00488     // Fetch string value.
00489     map<string, relDataType*>::const_iterator lVarIt = gVariables.find(*mStrVar);
00490     assert(lVarIt != gVariables.end());  // Must be declared.
00491     assert(lVarIt->second != NULL);
00492     relString* lResult = dynamic_cast<relString*>(lVarIt->second);
00493     assert(lResult != NULL);             // Must be a STRING variable.
00494 
00495     // For all elements of the set (all values for attribute at pos lVarId).
00496     while (!lRel.isEmpty()) {
00497       // Get next value of the attribute.
00498       string lValue = lRel.getElement(lVarId);
00499 
00500       // Change value of string variable.
00501       lResult->setValue(lValue);
00502 
00503       // Delete current element from set.
00504       bddRelation lCurrentValue( bddRelation::mkEqual(pSymTab, 
00505                                  lVarId, 
00506                                  pSymTab->getValueNum(lValue)) );
00507       lCurrentValue.complement();  
00508       lRel.intersect(lCurrentValue);
00509 
00510       // Execute body of FOR loop.
00511       mStmt->interpret(pSymTab);
00512     }
00513   }  // method
00514 };
00515 
00517 class relStmtExit : public relStatement
00518 {
00519 private:
00520   relNumExpr* mExitCode;
00521 
00522 public:
00523   relStmtExit(relNumExpr* pExitCode)
00524         : mExitCode(pExitCode)
00525   {}
00526 
00527   ~relStmtExit()
00528   {
00529     delete mExitCode;
00530   }
00531 
00532   virtual void
00533   interpret(bddSymTab* pSymTab)
00534   {
00535         exit((int) mExitCode->interpret(pSymTab).getValue());
00536   }
00537 };
00538 
00541 class relStmtEmpty : public relStatement
00542 {
00543 public:
00544   relStmtEmpty()
00545   {}
00546 
00547   ~relStmtEmpty()
00548   {}
00549 
00550   virtual void
00551   interpret(bddSymTab* pSymTab)
00552   {}
00553 };
00554 

Generated on Fri Jun 6 22:21:09 2008 for CrocoPat by  doxygen 1.5.1