about summary refs log tree commit diff homepage
path: root/stp/AST/AST.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'stp/AST/AST.cpp')
-rw-r--r--stp/AST/AST.cpp1587
1 files changed, 1587 insertions, 0 deletions
diff --git a/stp/AST/AST.cpp b/stp/AST/AST.cpp
new file mode 100644
index 00000000..ab290395
--- /dev/null
+++ b/stp/AST/AST.cpp
@@ -0,0 +1,1587 @@
+/********************************************************************
+ * AUTHORS: Vijay Ganesh, David L. Dill
+ *
+ * BEGIN DATE: November, 2005
+ *
+ * LICENSE: Please view LICENSE file in the home dir of this Program
+ ********************************************************************/
+// -*- c++ -*-
+
+#include "AST.h"
+namespace BEEV {
+  //some global variables that are set through commandline options. it
+  //is best that these variables remain global. Default values set
+  //here
+  //
+  //collect statistics on certain functions
+  bool stats = false;
+  //print DAG nodes
+  bool print_nodes = false;
+  //tentative global var to allow for variable activity optimization
+  //in the SAT solver. deprecated.
+  bool variable_activity_optimize = false;
+  //run STP in optimized mode
+  bool optimize = true;
+  //do sat refinement, i.e. underconstraint the problem, and feed to
+  //SAT. if this works, great. else, add a set of suitable constraints
+  //to re-constraint the problem correctly, and call SAT again, until
+  //all constraints have been added.
+  bool arrayread_refinement = true;
+  //flag to control write refinement
+  bool arraywrite_refinement = true;
+  //check the counterexample against the original input to STP
+  bool check_counterexample = false;
+  //construct the counterexample in terms of original variable based
+  //on the counterexample returned by SAT solver
+  bool construct_counterexample = true;
+  bool print_counterexample = false;
+  //if this option is true then print the way dawson wants using a
+  //different printer. do not use this printer.
+  bool print_arrayval_declaredorder = false;
+  //flag to decide whether to print "valid/invalid" or not
+  bool print_output = false;
+  //do linear search in the array values of an input array. experimental
+  bool linear_search = false;
+  //print the variable order chosen by the sat solver while it is
+  //solving.
+  bool print_sat_varorder = false; 
+  //turn on word level bitvector solver
+  bool wordlevel_solve = true;
+  //turn off XOR flattening
+  bool xor_flatten = false;
+
+  //the smtlib parser has been turned on
+  bool smtlib_parser_enable = false;
+  //print the input back
+  bool print_STPinput_back = false;
+  
+  //global BEEVMGR for the parser
+  BeevMgr * globalBeevMgr_for_parser;
+
+  void (*vc_error_hdlr)(const char* err_msg) = NULL;
+  /** This is reusable empty vector, for representing empty children arrays */
+  ASTVec _empty_ASTVec;  
+  ////////////////////////////////////////////////////////////////
+  //  ASTInternal members
+  ////////////////////////////////////////////////////////////////  
+  /** Trivial but virtual destructor */
+  ASTInternal::~ASTInternal() { }
+
+  ////////////////////////////////////////////////////////////////
+  //  ASTInterior members
+  ////////////////////////////////////////////////////////////////
+  /** Copy constructor */
+  // ASTInterior::ASTInterior(const ASTInterior &int_node)
+  // {
+  //   _kind = int_node._kind;
+  //   _children = int_node._children;
+  // }
+  
+  /** Trivial but virtual destructor */
+  ASTInterior::~ASTInterior() { }
+  
+  // FIXME: Darn it! I think this ends up copying the children twice!
+  /** Either return an old node or create it if it doesn't exist. 
+      Note that nodes are physically allocated in the hash table. */
+  
+  // There is  an inelegance here that  I don't know how  to solve.  I'd
+  // like to heap allocate and do some other initialization on keys only
+  // if  they aren't  in  the hash  table.   It would  be  great if  the
+  // "insert"  method took a  "creator" class  so that  I could  do that
+  // between  when it  notices that  the key  is not  there and  when it
+  // inserts it.  Alternatively, it would be great if I could insert the
+  // temporary key and replace it  if it actually got inserted.  But STL
+  // hash_set  doesn't have  the creator  feature  and paternalistically
+  // declares that keys are immutable, even though (it seems to me) that
+  // they  could be  mutated if  the hash  value and  eq values  did not
+  // change.
+  
+  ASTInterior *BeevMgr::LookupOrCreateInterior(ASTInterior *n_ptr) {
+    ASTInteriorSet::iterator it;
+    
+    if ((it = _interior_unique_table.find(n_ptr)) == _interior_unique_table.end()) {
+      // Make a new ASTInterior node
+      // We want (NOT alpha) always to have alpha.nodenum + 1.
+      if (n_ptr->GetKind() == NOT) {
+	n_ptr->SetNodeNum(n_ptr->GetChildren()[0].GetNodeNum()+1);
+      }
+      else {
+	n_ptr->SetNodeNum(NewNodeNum());
+      }
+      pair<ASTInteriorSet::const_iterator, bool> p = _interior_unique_table.insert(n_ptr);
+      return *(p.first);
+    }
+    else
+      // Delete the temporary node, and return the found node.
+      delete n_ptr;
+      return *it;
+  }
+  
+  size_t ASTInterior::ASTInteriorHasher::operator() (const ASTInterior *int_node_ptr) const {
+    //size_t hashval = 0;
+    size_t hashval = ((size_t) int_node_ptr->GetKind());
+    const ASTVec &ch = int_node_ptr->GetChildren();
+    ASTVec::const_iterator iend = ch.end();
+    for (ASTVec::const_iterator i = ch.begin(); i != iend; i++) {
+      //Using "One at a time hash" by Bob Jenkins
+      hashval += i->Hash();
+      hashval += (hashval << 10);
+      hashval ^= (hashval >> 6);
+    }
+
+    hashval += (hashval << 3);
+    hashval ^= (hashval >> 11);
+    hashval += (hashval << 15);
+    return hashval;
+    //return hashval += ((size_t) int_node_ptr->GetKind());
+  }
+  
+
+  void ASTInterior::CleanUp() {
+    // cout << "Deleting node " << this->GetNodeNum() << endl;
+    _bm._interior_unique_table.erase(this);
+    delete this;
+  }
+
+  ////////////////////////////////////////////////////////////////
+  //  ASTNode members
+  ////////////////////////////////////////////////////////////////
+  //ASTNode constructors are inlined in AST.h
+  bool ASTNode::IsAlreadyPrinted() const {
+    BeevMgr &bm = GetBeevMgr();
+    return (bm.AlreadyPrintedSet.find(*this) != bm.AlreadyPrintedSet.end());
+  }
+
+  void ASTNode::MarkAlreadyPrinted() const {
+    // FIXME: Fetching BeevMgr is annoying.  Can we put this in lispprinter class?
+    BeevMgr &bm = GetBeevMgr();
+    bm.AlreadyPrintedSet.insert(*this);
+  }
+
+  // Get the name from a symbol (char *).  It's an error if kind != SYMBOL
+  const char * const ASTNode::GetName() const {
+    if (GetKind() != SYMBOL)
+      FatalError("GetName: Called GetName on a non-symbol: ", *this);
+    return ((ASTSymbol *) _int_node_ptr)->GetName();    
+  }
+  
+  // Print in lisp format
+  ostream &ASTNode::LispPrint(ostream &os, int indentation) const {
+    // Clear the PrintMap
+    BeevMgr& bm = GetBeevMgr(); 
+    bm.AlreadyPrintedSet.clear();
+    return LispPrint_indent(os, indentation);
+  }
+
+  // Print newline and indentation, then print the thing.
+  ostream &ASTNode::LispPrint_indent(ostream &os,
+				     int indentation) const
+  {
+    os << endl << spaces(indentation);
+    LispPrint1(os, indentation);
+    return os;
+  }
+  
+  /** Internal function to print in lisp format.  Assume newline
+      and indentation printed already before first line.  Recursive
+      calls will have newline & indent, though */
+  ostream &ASTNode::LispPrint1(ostream &os, int indentation) const {
+    if (!IsDefined()) {
+      os << "<undefined>";
+      return os;
+    }
+    Kind kind = GetKind();
+    // FIXME: figure out how to avoid symbols with same names as kinds.
+//    if (kind == READ) {
+//      const ASTVec &children = GetChildren();
+//      children[0].LispPrint1(os, indentation);
+//	os << "[" << children[1] << "]";
+//    } else 
+    if(kind == BVGETBIT) {
+      const ASTVec &children = GetChildren();
+      // child 0 is a symbol.  Print without the NodeNum.
+      os << GetNodeNum() << ":";
+
+
+
+      children[0]._int_node_ptr->nodeprint(os);
+      //os << "{" << children[1].GetBVConst() << "}";
+      os << "{";
+      children[1]._int_node_ptr->nodeprint(os);
+      os << "}";
+    } else if (kind == NOT) {
+      const ASTVec &children = GetChildren();
+      os << GetNodeNum() << ":";	
+      os << "(NOT ";
+      children[0].LispPrint1(os, indentation);
+      os << ")";
+    }
+    else if (Degree() == 0) {
+      // Symbol or a kind with no children print as index:NAME if shared,
+      // even if they have been printed before.	
+      os << GetNodeNum() << ":";
+      _int_node_ptr->nodeprint(os); 
+      // os << "(" << _int_node_ptr->_ref_count << ")";
+      // os << "{" << GetValueWidth() << "}";
+    }
+    else if (IsAlreadyPrinted()) {
+      // print non-symbols as "[index]" if seen before.
+      os << "[" << GetNodeNum() << "]";
+      //	   << "(" << _int_node_ptr->_ref_count << ")";
+    }
+    else {
+      MarkAlreadyPrinted();
+      const ASTVec &children = GetChildren();
+      os << GetNodeNum() << ":"
+	//<< "(" << _int_node_ptr->_ref_count << ")" 
+	 << "(" << kind << " ";
+      // os << "{" << GetValueWidth() << "}";
+      ASTVec::const_iterator iend = children.end();
+      for (ASTVec::const_iterator i = children.begin(); i != iend; i++) {
+	i->LispPrint_indent(os, indentation+2);
+	}
+      os << ")";	
+    }
+    return os;
+  }
+
+  //print in PRESENTATION LANGUAGE
+  //
+  //two pass algorithm: 
+  //
+  //1. In the first pass, letize this Node, N: i.e. if a node
+  //1. appears more than once in N, then record this fact.
+  //
+  //2. In the second pass print a "global let" and then print N
+  //2. as follows: Every occurence of a node occuring more than
+  //2. once is replaced with the corresponding let variable.
+  ostream& ASTNode::PL_Print(ostream &os,
+			     int indentation) const {
+    // Clear the PrintMap
+    BeevMgr& bm = GetBeevMgr(); 
+    bm.PLPrintNodeSet.clear();
+    bm.NodeLetVarMap.clear();
+    bm.NodeLetVarVec.clear();
+    bm.NodeLetVarMap1.clear();
+
+    //pass 1: letize the node
+    LetizeNode();
+
+    //pass 2: 
+    //
+    //2. print all the let variables and their counterpart expressions
+    //2. as follows (LET var1 = expr1, var2 = expr2, ...
+    //
+    //3. Then print the Node itself, replacing every occurence of
+    //3. expr1 with var1, expr2 with var2, ...
+    //os << "(";
+    if(0 < bm.NodeLetVarMap.size()) {
+      //ASTNodeMap::iterator it=bm.NodeLetVarMap.begin();
+      //ASTNodeMap::iterator itend=bm.NodeLetVarMap.end();
+      std::vector<pair<ASTNode,ASTNode> >::iterator it = bm.NodeLetVarVec.begin();
+      std::vector<pair<ASTNode,ASTNode> >::iterator itend = bm.NodeLetVarVec.end();
+
+      os << "(LET ";      
+      //print the let var first
+      it->first.PL_Print1(os,indentation,false);
+      os << " = ";
+      //print the expr
+      it->second.PL_Print1(os,indentation,false);
+
+      //update the second map for proper printing of LET
+      bm.NodeLetVarMap1[it->second] = it->first;
+
+      for(it++;it!=itend;it++) {
+        os << "," << endl;
+	//print the let var first
+	it->first.PL_Print1(os,indentation,false);
+	os << " = ";
+	//print the expr
+	it->second.PL_Print1(os,indentation,false);
+
+        //update the second map for proper printing of LET
+        bm.NodeLetVarMap1[it->second] = it->first;
+      }
+    
+      os << " IN " << endl;      
+      PL_Print1(os,indentation, true);
+      os << ") ";
+    }
+    else
+      PL_Print1(os,indentation, false);
+    //os << " )";
+    os << " ";
+    return os;
+  } //end of PL_Print()
+
+  //traverse "*this", and construct "let variables" for terms that
+  //occur more than once in "*this".
+  void ASTNode::LetizeNode(void) const {
+    Kind kind = this->GetKind();
+
+    if(kind == SYMBOL  || 
+       kind == BVCONST ||
+       kind == FALSE   ||
+       kind == TRUE)
+      return;
+
+    //FIXME: this is ugly.
+    BeevMgr& bm = GetBeevMgr();     
+    const ASTVec &c = this->GetChildren();
+    for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++){
+      ASTNode ccc = *it;
+      if(bm.PLPrintNodeSet.find(ccc) == bm.PLPrintNodeSet.end()){
+	//If branch: if *it is not in NodeSet then,
+	//
+	//1. add it to NodeSet
+	//
+	//2. Letize its childNodes
+
+	//FIXME: Fetching BeevMgr is annoying.  Can we put this in
+	//some kind of a printer class
+	bm.PLPrintNodeSet.insert(ccc);
+	//debugging
+	//cerr << ccc;
+	ccc.LetizeNode();
+      } 
+      else{
+	Kind k = ccc.GetKind();
+	if(k == SYMBOL  || 
+	   k == BVCONST ||
+	   k == FALSE   ||
+	   k == TRUE)
+	  continue;
+	
+	//0. Else branch: Node has been seen before
+	//
+	//1. Check if the node has a corresponding letvar in the
+	//1. NodeLetVarMap.
+	//
+	//2. if no, then create a new var and add it to the
+	//2. NodeLetVarMap
+	if(bm.NodeLetVarMap.find(ccc) == bm.NodeLetVarMap.end()) {
+	  //Create a new symbol. Get some name. if it conflicts with a
+	  //declared name, too bad. 
+	  int sz = bm.NodeLetVarMap.size();
+	  ostringstream oss;
+	  oss << "let_k_" << sz;
+
+	  ASTNode CurrentSymbol = bm.CreateSymbol(oss.str().c_str());
+	  CurrentSymbol.SetValueWidth(this->GetValueWidth());
+	  CurrentSymbol.SetIndexWidth(this->GetIndexWidth());	  
+	  /* If for some reason the variable being created here is
+	   * already declared by the user then the printed output will
+	   * not be a legal input to the system. too bad. I refuse to
+	   * check for this.  [Vijay is the author of this comment.]
+	   */
+	  
+	  bm.NodeLetVarMap[ccc] = CurrentSymbol;
+	  std::pair<ASTNode,ASTNode> node_letvar_pair(CurrentSymbol,ccc);
+	  bm.NodeLetVarVec.push_back(node_letvar_pair);
+	}
+      }    
+    }
+  } //end of LetizeNode()
+
+  void ASTNode::PL_Print1(ostream& os,
+			  int indentation, 
+			  bool letize) const {
+    //os << spaces(indentation);
+    //os << endl << spaces(indentation);
+    if (!IsDefined()) {
+      os << "<undefined>";
+      return;
+    }
+    
+    //if this node is present in the letvar Map, then print the letvar
+    BeevMgr &bm = GetBeevMgr();
+
+    //this is to print letvars for shared subterms inside the printing
+    //of "(LET v0 = term1, v1=term1@term2,...
+    if((bm.NodeLetVarMap1.find(*this) != bm.NodeLetVarMap1.end()) && !letize) {
+      (bm.NodeLetVarMap1[*this]).PL_Print1(os,indentation,letize);
+      return;
+    }
+
+    //this is to print letvars for shared subterms inside the actual
+    //term to be printed
+    if((bm.NodeLetVarMap.find(*this) != bm.NodeLetVarMap.end()) && letize) {
+      (bm.NodeLetVarMap[*this]).PL_Print1(os,indentation,letize);
+      return;
+    }
+    
+    //otherwise print it normally
+    Kind kind = GetKind();
+    const ASTVec &c = GetChildren();     
+    switch(kind) {
+    case BVGETBIT:
+      c[0].PL_Print1(os,indentation,letize);
+      os << "{";
+      c[1].PL_Print1(os,indentation,letize);
+      os << "}";
+      break;
+    case BITVECTOR:
+      os << "BITVECTOR(";
+      unsigned char * str;
+      str = CONSTANTBV::BitVector_to_Hex(c[0].GetBVConst());
+      os << str << ")";
+      CONSTANTBV::BitVector_Dispose(str);
+      break;
+    case BOOLEAN:
+      os << "BOOLEAN";
+      break;
+    case FALSE:
+    case TRUE:
+      os << kind;
+      break;
+    case BVCONST:
+    case SYMBOL:
+      _int_node_ptr->nodeprint(os); 
+      break;
+    case READ:
+      c[0].PL_Print1(os, indentation,letize);
+      os << "[";
+      c[1].PL_Print1(os,indentation,letize);
+      os << "]";
+      break;
+    case WRITE:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " WITH [";
+      c[1].PL_Print1(os,indentation,letize);
+      os << "] := ";
+      c[2].PL_Print1(os,indentation,letize);
+      os << ")";
+      os << endl;
+      break;
+    case BVUMINUS:
+      os << kind << "( ";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ")";
+      break;
+    case NOT:
+      os << "NOT(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ") " << endl;
+      break;
+    case BVNEG:
+      os << " ~(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ")";
+      break;
+    case BVCONCAT:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " @ ";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case BVOR:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " | ";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")";
+      break;
+    case BVAND:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " & ";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")";
+      break;
+    case BVEXTRACT:
+      c[0].PL_Print1(os,indentation,letize);
+      os << "[";
+      os << GetUnsignedConst(c[1]);
+      os << ":";
+      os << GetUnsignedConst(c[2]);
+      os << "]";
+      break;
+    case BVLEFTSHIFT:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " << ";
+      os << GetUnsignedConst(c[1]);
+      os << ")";
+      break;
+    case BVRIGHTSHIFT:
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << " >> ";
+      os << GetUnsignedConst(c[1]);
+      os << ")";
+      break;
+    case BVMULT:
+    case BVSUB:
+    case BVPLUS:
+    case SBVDIV:      
+    case SBVMOD:
+    case BVDIV:      
+    case BVMOD:
+      os << kind << "(";
+      os << this->GetValueWidth();
+      for(ASTVec::const_iterator it=c.begin(),itend=c.end();it!=itend;it++) {
+	os << ", " << endl;
+	it->PL_Print1(os,indentation,letize);	
+      }
+      os << ")" << endl;
+      break;    
+    case ITE:
+      os << "IF(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      os << "THEN ";
+      c[1].PL_Print1(os,indentation,letize);
+      os << endl << "ELSE ";
+      c[2].PL_Print1(os,indentation,letize);
+      os << endl << "ENDIF";
+      break;
+    case BVLT:
+    case BVLE:
+    case BVGT:
+    case BVGE:
+    case BVXOR:
+    case BVNAND:
+    case BVNOR:
+    case BVXNOR:
+      os << kind << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case BVSLT:
+      os << "SBVLT" << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case BVSLE:
+      os << "SBVLE" << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case BVSGT:
+      os << "SBVGT" << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case BVSGE:
+      os << "SBVGE" << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")" << endl;
+      break;
+    case EQ:
+      c[0].PL_Print1(os,indentation,letize);
+      os << " = ";
+      c[1].PL_Print1(os,indentation,letize);      
+      os << endl;
+      break;
+    case NEQ:
+      c[0].PL_Print1(os,indentation,letize);
+      os << " /= ";
+      c[1].PL_Print1(os,indentation,letize);      
+      os << endl;
+      break;
+    case AND:
+    case OR:
+    case NAND:
+    case NOR:
+    case XOR: {
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      ASTVec::const_iterator it=c.begin();
+      ASTVec::const_iterator itend=c.end();
+
+      it++;
+      for(;it!=itend;it++) {
+	os << " " << kind << " ";
+	it->PL_Print1(os,indentation,letize);
+	os << endl;
+      }
+      os << ")";
+      break;
+    }
+    case IFF:
+      os << "(";
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ")";
+      os << " <=> ";
+      os << "(";
+      c[1].PL_Print1(os,indentation,letize);      
+      os << ")";
+      os << ")";
+      os << endl;
+      break;
+    case IMPLIES:
+      os << "(";
+      os << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ")";
+      os << " => ";
+      os << "(";
+      c[1].PL_Print1(os,indentation,letize);
+      os << ")";
+      os << ")";
+      os << endl;
+      break;
+    case BVSX:
+      os << kind << "(";
+      c[0].PL_Print1(os,indentation,letize);
+      os << ",";
+      os << this->GetValueWidth();
+      os << ")" << endl;
+      break;
+    default:
+      //remember to use LispPrinter here. Otherwise this function will
+      //go into an infinite loop. Recall that "<<" is overloaded to
+      //the lisp printer. FatalError uses lispprinter
+      FatalError("PL_Print1: printing not implemented for this kind: ",*this);
+      break;
+    }
+  } //end of PL_Print1()
+
+  ////////////////////////////////////////////////////////////////
+  //  BeevMgr members
+  ////////////////////////////////////////////////////////////////
+  ASTNode BeevMgr::CreateNode(Kind kind, const ASTVec & back_children) {
+    // create a new node.  Children will be modified.
+    ASTInterior *n_ptr = new ASTInterior(kind, *this);
+
+    // insert all of children at end of new_children.
+    ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
+    return n;
+  }
+  
+  ASTNode BeevMgr::CreateNode(Kind kind,
+			      const ASTNode& child0,
+			      const ASTVec & back_children) {
+
+    ASTInterior *n_ptr = new ASTInterior(kind, *this);
+    ASTVec &front_children = n_ptr->_children;
+    front_children.push_back(child0);
+    ASTNode n(CreateInteriorNode(kind, n_ptr,  back_children));
+    return n;
+  }
+  
+  ASTNode BeevMgr::CreateNode(Kind kind,
+			      const ASTNode& child0,
+			      const ASTNode& child1,
+			      const ASTVec & back_children) {
+
+    ASTInterior *n_ptr = new ASTInterior(kind, *this);
+    ASTVec &front_children = n_ptr->_children;
+    front_children.push_back(child0);
+    front_children.push_back(child1);
+    ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
+    return n;
+  }
+  
+  
+  ASTNode BeevMgr::CreateNode(Kind kind,
+			      const ASTNode& child0,
+			      const ASTNode& child1,
+			      const ASTNode& child2,
+			      const ASTVec & back_children) {
+    ASTInterior *n_ptr = new ASTInterior(kind, *this);
+    ASTVec &front_children = n_ptr->_children;
+    front_children.push_back(child0);
+    front_children.push_back(child1);
+    front_children.push_back(child2);
+    ASTNode n(CreateInteriorNode(kind, n_ptr, back_children));
+    return n;
+  }
+  
+  
+  ASTInterior *BeevMgr::CreateInteriorNode(Kind kind,
+					   // children array of this node will be modified.
+					   ASTInterior *n_ptr,
+					   const ASTVec & back_children) {
+
+    // insert back_children at end of front_children
+    ASTVec &front_children = n_ptr->_children;
+
+    front_children.insert(front_children.end(), back_children.begin(), back_children.end());
+
+    // check for undefined nodes.
+    ASTVec::const_iterator it_end = front_children.end();
+    for (ASTVec::const_iterator it = front_children.begin(); it != it_end; it++) {
+      if (it->IsNull())
+	FatalError("CreateInteriorNode: Undefined childnode in CreateInteriorNode: ", ASTUndefined);      
+    }
+
+    return LookupOrCreateInterior(n_ptr);
+  }
+    
+  /** Trivial but virtual destructor */
+  ASTSymbol::~ASTSymbol() {}
+  
+  ostream &operator<<(ostream &os, const ASTNodeMap &nmap)
+  {
+    ASTNodeMap::const_iterator iend = nmap.end();
+    for (ASTNodeMap::const_iterator i = nmap.begin(); i!=iend; i++) {
+      os << "Key: " << i->first << endl;
+      os << "Value: " << i->second << endl;
+    }
+    return os;
+  }
+  
+  ////////////////////////////////////////////////////////////////
+  // BeevMgr member functions to create ASTSymbol and ASTBVConst
+  ////////////////////////////////////////////////////////////////
+  ASTNode BeevMgr::CreateSymbol(const char * const name) 
+  { 
+    ASTSymbol temp_sym(name, *this);
+    ASTNode n(LookupOrCreateSymbol(temp_sym));
+    return n;
+  }
+
+#ifndef NATIVE_C_ARITH
+  //Create a ASTBVConst node
+  ASTNode BeevMgr::CreateBVConst(unsigned int width, 
+				 unsigned long long int bvconst){ 
+    if(width > (sizeof(unsigned long long int)<<3) || width <= 0)
+      FatalError("CreateBVConst: trying to create a bvconst of width: ", ASTUndefined, width);
+    
+
+    CBV bv = CONSTANTBV::BitVector_Create(width, true);
+    unsigned long c_val = (0x00000000ffffffffLL) & bvconst;
+    unsigned int copied = 0;
+
+    // sizeof(unsigned long) returns the number of bytes in unsigned
+    // long. In order to convert it to bits, we need to shift left by
+    // 3. Hence, sizeof(unsigned long) << 3
+
+    //The algo below works as follows: It starts by copying the
+    //lower-order bits of the input "bvconst" in chunks of size =
+    //number of bits in unsigned long. The variable "copied" keeps
+    //track of the number of chunks copied so far
+
+    while(copied + (sizeof(unsigned long)<<3) < width){
+      CONSTANTBV::BitVector_Chunk_Store(bv, sizeof(unsigned long)<<3,copied,c_val);
+      bvconst = bvconst >> (sizeof(unsigned long) << 3);
+      c_val = (0x00000000ffffffffLL) & bvconst;
+      copied += sizeof(unsigned long) << 3;
+    }
+    CONSTANTBV::BitVector_Chunk_Store(bv,width - copied,copied,c_val);
+    return CreateBVConst(bv,width);
+  }
+
+  //Create a ASTBVConst node from std::string
+  ASTNode BeevMgr::CreateBVConst(const char* const strval, int base) {
+    size_t width = strlen((const char *)strval);    
+    if(!(2 == base || 10 == base || 16 == base)){
+      FatalError("CreateBVConst: unsupported base: ",ASTUndefined,base);
+    }
+    //FIXME Tim: Earlier versions of the code assume that the length of
+    //binary strings is 32 bits.
+    if(10 == base) width = 32;
+    if(16 == base) width = width * 4;
+
+    //checking if the input is in the correct format
+    CBV bv = CONSTANTBV::BitVector_Create(width,true);
+    CONSTANTBV::ErrCode e;
+    if(2 == base){
+      e = CONSTANTBV::BitVector_from_Bin(bv, (unsigned char*)strval);
+    }else if(10 == base){
+      e = CONSTANTBV::BitVector_from_Dec(bv, (unsigned char*)strval);
+    }else if(16 == base){
+      e = CONSTANTBV::BitVector_from_Hex(bv, (unsigned char*)strval);
+    }else{
+      e = CONSTANTBV::ErrCode_Pars;
+    }
+
+    if(0 != e) {
+      cerr << "CreateBVConst: " << BitVector_Error(e);
+      FatalError("",ASTUndefined);
+    }
+
+    //FIXME 
+    return CreateBVConst(bv, width);
+  }
+  
+
+  //FIXME Code currently assumes that it will destroy the bitvector passed to it
+  ASTNode BeevMgr::CreateBVConst(CBV bv, unsigned width){
+     ASTBVConst temp_bvconst(bv, width, *this);
+     ASTNode n(LookupOrCreateBVConst(temp_bvconst));
+     
+     CONSTANTBV::BitVector_Destroy(bv);
+     
+     return n;
+  }
+
+  ASTNode BeevMgr::CreateZeroConst(unsigned width) {
+    CBV z = CONSTANTBV::BitVector_Create(width, true);
+    return CreateBVConst(z, width);
+  }
+  
+  ASTNode BeevMgr::CreateOneConst(unsigned width) {
+    CBV o = CONSTANTBV::BitVector_Create(width, true);
+    CONSTANTBV::BitVector_increment(o);
+    
+    return CreateBVConst(o,width);
+  }
+
+  ASTNode BeevMgr::CreateTwoConst(unsigned width) {
+    CBV two = CONSTANTBV::BitVector_Create(width, true);
+    CONSTANTBV::BitVector_increment(two);
+    CONSTANTBV::BitVector_increment(two);
+
+    return CreateBVConst(two,width);
+  }
+
+  ASTNode BeevMgr::CreateMaxConst(unsigned width) {
+    CBV max = CONSTANTBV::BitVector_Create(width, false);
+    CONSTANTBV::BitVector_Fill(max);
+
+    return CreateBVConst(max,width);
+  }
+
+  //To ensure unique BVConst nodes, lookup the node in unique-table
+  //before creating a new one.
+  ASTBVConst *BeevMgr::LookupOrCreateBVConst(ASTBVConst &s) {
+    ASTBVConst *s_ptr = &s;  // it's a temporary key.
+    
+    // Do an explicit lookup to see if we need to create a copy of the string.    
+    ASTBVConstSet::const_iterator it;
+    if ((it = _bvconst_unique_table.find(s_ptr)) == _bvconst_unique_table.end()) {
+      // Make a new ASTBVConst with duplicated string (can't assign
+      // _name because it's const).  Can cast the iterator to
+      // non-const -- carefully.
+
+      ASTBVConst * s_copy = new ASTBVConst(s);      
+      s_copy->SetNodeNum(NewNodeNum());
+      
+      pair<ASTBVConstSet::const_iterator, bool> p = _bvconst_unique_table.insert(s_copy);
+      return *p.first;
+    }
+    else{
+      // return symbol found in table.
+      return *it;
+    }
+  }
+
+  // Inline because we need to wait until unique_table is defined
+  void ASTBVConst::CleanUp() {
+    //  cout << "Deleting node " << this->GetNodeNum() << endl;
+    _bm._bvconst_unique_table.erase(this);
+    delete this;
+  }
+
+  // Get the value of bvconst from a bvconst.  It's an error if kind != BVCONST
+  CBV const ASTNode::GetBVConst() const {
+    if(GetKind() != BVCONST)
+      FatalError("GetBVConst: non bitvector-constant: ",*this);
+    return ((ASTBVConst *) _int_node_ptr)->GetBVConst();      
+  }
+#else
+  //Create a ASTBVConst node
+  ASTNode BeevMgr::CreateBVConst(const unsigned int width, 
+				 const unsigned long long int bvconst) { 
+    if(width > 64 || width <= 0)
+      FatalError("Fatal Error: CreateBVConst: trying to create a bvconst of width:", ASTUndefined, width);
+    
+    //64 bit mask
+    unsigned long long int mask = 0xffffffffffffffffLL;
+    mask = mask >> (64 - width);
+
+    unsigned long long int bv = bvconst;
+    bv = bv & mask;
+
+    ASTBVConst temp_bvconst(bv, *this);
+    temp_bvconst._value_width = width;    
+    ASTNode n(LookupOrCreateBVConst(temp_bvconst));
+    n.SetValueWidth(width);
+    n.SetIndexWidth(0);
+    return n;
+  }
+  //Create a ASTBVConst node from std::string
+  ASTNode BeevMgr::CreateBVConst(const char* strval, int base) {    
+    if(!(base == 2 || base == 16 || base == 10))
+      FatalError("CreateBVConst: This base is not supported: ", ASTUndefined, base);
+
+    if(10 != base) {
+      unsigned int width = (base == 2) ? strlen(strval) : strlen(strval)*4;
+      unsigned long long int val =  strtoull(strval, NULL, base);
+      ASTNode bvcon = CreateBVConst(width, val);
+      return bvcon;
+    }
+    else {
+      //this is an ugly hack to accomodate SMTLIB format
+      //restrictions. SMTLIB format represents bitvector constants in
+      //base 10 (what a terrible idea, but i have no choice but to
+      //support it), and make an implicit assumption that the length
+      //is 32 (another terrible idea).
+      unsigned width = 32;
+      unsigned long long int val = strtoull(strval, NULL, base);
+      ASTNode bvcon = CreateBVConst(width, val);
+      return bvcon;
+    }
+  }
+  
+  //To ensure unique BVConst nodes, lookup the node in unique-table
+  //before creating a new one.
+  ASTBVConst *BeevMgr::LookupOrCreateBVConst(ASTBVConst &s) {
+    ASTBVConst *s_ptr = &s;	// it's a temporary key.
+
+    // Do an explicit lookup to see if we need to create a copy of the
+    // string.
+    ASTBVConstSet::const_iterator it;
+    if ((it = _bvconst_unique_table.find(s_ptr)) == _bvconst_unique_table.end()) {
+      // Make a new ASTBVConst. Can cast the iterator to non-const --
+      // carefully.
+      unsigned int width = s_ptr->_value_width;
+      ASTBVConst * s_ptr1 = new ASTBVConst(s_ptr->GetBVConst(), *this);
+      s_ptr1->SetNodeNum(NewNodeNum());
+      s_ptr1->_value_width = width;
+      pair<ASTBVConstSet::const_iterator, bool> p = _bvconst_unique_table.insert(s_ptr1);
+      return *p.first;
+    }
+    else
+      // return BVConst found in table.
+      return *it;
+  }
+
+  // Inline because we need to wait until unique_table is defined
+  void ASTBVConst::CleanUp() {
+    //  cout << "Deleting node " << this->GetNodeNum() << endl;
+    _bm._bvconst_unique_table.erase(this);
+    delete this;
+  }
+
+  // Get the value of bvconst from a bvconst.  It's an error if kind
+  // != BVCONST
+  unsigned long long int ASTNode::GetBVConst() const {
+    if(GetKind() != BVCONST)
+      FatalError("GetBVConst: non bitvector-constant: ", *this);
+    return ((ASTBVConstTmp *) _int_node_ptr)->GetBVConst();
+  }
+
+  ASTNode BeevMgr::CreateZeroConst(unsigned width) {
+    return CreateBVConst(width,0);
+  }
+  
+  ASTNode BeevMgr::CreateOneConst(unsigned width) {
+    return CreateBVConst(width,1);
+  }
+
+  ASTNode BeevMgr::CreateTwoConst(unsigned width) {
+    return CreateBVConst(width,2);
+  }
+
+  ASTNode BeevMgr::CreateMaxConst(unsigned width) {
+    std::string s;
+    s.insert(s.end(),width,'1');
+    return CreateBVConst(s.c_str(),2);
+  }
+
+#endif  
+
+  // FIXME: _name is now a constant field, and this assigns to it
+  // because it tries not to copy the string unless it needs to.  How
+  // do I avoid copying children in ASTInterior?  Perhaps I don't!
+  
+  // Note: There seems to be a limitation of hash_set, in that insert
+  // returns a const iterator to the value.  That prevents us from
+  // modifying the name (in a hash-preserving way) after the symbol is
+  // inserted.  FIXME: Is there a way to do this with insert?  Need a
+  // function to make a new object in the middle of insert.  Read STL
+  // documentation.
+  
+  ASTSymbol *BeevMgr::LookupOrCreateSymbol(ASTSymbol& s) {
+    ASTSymbol *s_ptr = &s;  // it's a temporary key.
+    
+    // Do an explicit lookup to see if we need to create a copy of the string.    
+    ASTSymbolSet::const_iterator it;
+    if ((it = _symbol_unique_table.find(s_ptr)) == _symbol_unique_table.end()) {
+      // Make a new ASTSymbol with duplicated string (can't assign
+      // _name because it's const).  Can cast the iterator to
+      // non-const -- carefully.
+      //std::string strname(s_ptr->GetName());
+      ASTSymbol * s_ptr1 = new ASTSymbol(strdup(s_ptr->GetName()), *this);
+      s_ptr1->SetNodeNum(NewNodeNum());
+      s_ptr1->_value_width = s_ptr->_value_width;
+      pair<ASTSymbolSet::const_iterator, bool> p = _symbol_unique_table.insert(s_ptr1);
+      return *p.first;
+    }
+    else
+      // return symbol found in table.
+      return *it;    
+  }
+
+  bool BeevMgr::LookupSymbol(ASTSymbol& s) {
+    ASTSymbol* s_ptr = &s;  // it's a temporary key.
+
+    if(_symbol_unique_table.find(s_ptr) == _symbol_unique_table.end()) 
+      return false;
+    else
+      return true;
+  }
+
+  // Inline because we need to wait until unique_table is defined
+  void ASTSymbol::CleanUp() {
+    //  cout << "Deleting node " << this->GetNodeNum() << endl;
+    _bm._symbol_unique_table.erase(this);
+    //FIXME This is a HUGE free to invoke.
+    //TEST IT!
+    free((char*) this->_name);
+    delete this;
+  }
+  
+  ////////////////////////////////////////////////////////////////
+  //
+  //  IO manipulators for Lisp format printing of AST.
+  //
+  ////////////////////////////////////////////////////////////////
+  
+  // FIXME: Additional controls
+  //   * Print node numbers  (addresses/nums)
+  //   * Printlength limit
+  //   * Printdepth limit
+  
+  /** Print a vector of ASTNodes in lisp format */
+  ostream &LispPrintVec(ostream &os, const ASTVec &v, int indentation)
+  {
+    // Print the children
+    ASTVec::const_iterator iend = v.end();
+    for (ASTVec::const_iterator i = v.begin(); i != iend; i++) {
+      i->LispPrint_indent(os, indentation);
+    }
+    return os;
+  }
+
+  // FIXME: Made non-ref in the hope that it would work better.
+  void lp(ASTNode node)
+  {
+    cout << lisp(node) << endl;
+  }
+
+  void lpvec(const ASTVec &vec)
+  {
+    vec[0].GetBeevMgr().AlreadyPrintedSet.clear();
+    LispPrintVec(cout, vec, 0);
+    cout << endl;
+  }
+
+  // Copy constructor.  Maintain _ref_count
+  ASTNode::ASTNode(const ASTNode &n) : _int_node_ptr(n._int_node_ptr) {
+#ifndef SMTLIB    
+    if (n._int_node_ptr) {
+      n._int_node_ptr->IncRef();
+    }
+#endif
+  }
+  
+
+  /* FUNCTION: Typechecker for terms and formulas
+   * 
+   * TypeChecker: Assumes that the immediate Children of the input
+   * ASTNode have been typechecked. This function is suitable in
+   * scenarios like where you are building the ASTNode Tree, and you
+   * typecheck as you go along. It is not suitable as a general
+   * typechecker      
+   */
+  void BeevMgr::BVTypeCheck(const ASTNode& n) {
+    Kind k = n.GetKind();
+    //The children of bitvector terms are in turn bitvectors.
+    ASTVec v = n.GetChildren();
+    if(is_Term_kind(k)) {
+      switch(k) {
+      case BVCONST:
+	if(BITVECTOR_TYPE != n.GetType())
+	  FatalError("BVTypeCheck: The term t does not typecheck, where t = \n",n);
+	break;
+      case SYMBOL:
+	return;
+      case ITE:     
+	if(BOOLEAN_TYPE != n[0].GetType() && 
+	   BITVECTOR_TYPE != n[1].GetType() &&
+	   BITVECTOR_TYPE != n[2].GetType())
+	  FatalError("BVTypeCheck: The term t does not typecheck, where t = \n",n);
+	if(n[1].GetValueWidth() != n[2].GetValueWidth())
+	  FatalError("BVTypeCheck: length of THENbranch != length of ELSEbranch in the term t = \n",n);
+	if(n[1].GetIndexWidth() != n[2].GetIndexWidth())
+	  FatalError("BVTypeCheck: length of THENbranch != length of ELSEbranch in the term t = \n",n);
+	break;
+      case READ:
+	if(n[0].GetIndexWidth() != n[1].GetValueWidth()) {
+	  cerr << "Length of indexwidth of array: " << n[0] << " is : " << n[0].GetIndexWidth() << endl;
+	  cerr << "Length of the actual index is: " << n[1] << " is : " << n[1].GetValueWidth() << endl;
+	  FatalError("BVTypeCheck: length of indexwidth of array != length of actual index in the term t = \n",n);
+	}
+	break;      
+      case WRITE:
+	if(n[0].GetIndexWidth() != n[1].GetValueWidth())
+	  FatalError("BVTypeCheck: length of indexwidth of array != length of actual index in the term t = \n",n);
+	if(n[0].GetValueWidth() != n[2].GetValueWidth())
+	  FatalError("BVTypeCheck: valuewidth of array != length of actual value in the term t = \n",n);
+	break;      
+      case BVOR:
+      case BVAND:
+      case BVXOR:
+      case BVNOR:
+      case BVNAND:
+      case BVXNOR: 
+      case BVPLUS: 
+      case BVMULT:
+      case BVDIV:
+      case BVMOD:
+      case BVSUB: {
+	if(!(v.size() >= 2))
+	  FatalError("BVTypeCheck:bitwise Booleans and BV arith operators must have atleast two arguments\n",n);
+	unsigned int width = n.GetValueWidth();
+	for(ASTVec::iterator it=v.begin(),itend=v.end();it!=itend;it++){
+	  if(width != it->GetValueWidth()) {
+	    cerr << "BVTypeCheck:Operands of bitwise-Booleans and BV arith operators must be of equal length\n";
+	    cerr << n << endl;
+	    cerr << "width of term:" << width << endl;
+	    cerr << "width of offending operand:" << it->GetValueWidth() << endl;
+	    FatalError("BVTypeCheck:Offending operand:\n",*it);
+	  }
+	  if(BITVECTOR_TYPE != it->GetType())
+	    FatalError("BVTypeCheck: ChildNodes of bitvector-terms must be bitvectors\n",n);
+	}
+	break;
+      }
+      case BVSX:
+	//in BVSX(n[0],len), the length of the BVSX term must be
+	//greater than the length of n[0]
+	if(n[0].GetValueWidth() >= n.GetValueWidth()) {
+	  FatalError("BVTypeCheck: BVSX(t,bvsx_len) : length of 't' must be <= bvsx_len\n",n);
+	} 
+	break;
+      default:
+	for(ASTVec::iterator it=v.begin(),itend=v.end();it!=itend;it++)
+	  if(BITVECTOR_TYPE != it->GetType()) {
+	    cerr << "The type is: " << it->GetType() << endl;
+	    FatalError("BVTypeCheck:ChildNodes of bitvector-terms must be bitvectors\n",n);
+	  }
+	break;
+      }
+      
+      switch(k) {
+      case BVCONCAT:
+	if(n.Degree() != 2)
+	  FatalError("BVTypeCheck: should have exactly 2 args\n",n);
+	if(n.GetValueWidth() != n[0].GetValueWidth() + n[1].GetValueWidth())
+	  FatalError("BVTypeCheck:BVCONCAT: lengths do not add up\n",n);	
+	break;
+      case BVUMINUS:
+      case BVNEG:
+	if(n.Degree() != 1)
+	  FatalError("BVTypeCheck: should have exactly 1 args\n",n);
+	break;
+      case BVEXTRACT:
+	if(n.Degree() != 3)
+	  FatalError("BVTypeCheck: should have exactly 3 args\n",n);
+	if(!(BVCONST == n[1].GetKind() && BVCONST == n[2].GetKind()))
+	  FatalError("BVTypeCheck: indices should be BVCONST\n",n);
+	if(n.GetValueWidth() != GetUnsignedConst(n[1])- GetUnsignedConst(n[2])+1)
+	  FatalError("BVTypeCheck: length mismatch\n",n);
+	break;
+      case BVLEFTSHIFT:
+      case BVRIGHTSHIFT:
+	if(n.Degree() != 2)
+	  FatalError("BVTypeCheck: should have exactly 2 args\n",n);
+	break;
+	//case BVVARSHIFT:
+	//case BVSRSHIFT:
+	break;
+      default:
+	break;
+      }
+    }
+    else {
+      if(!(is_Form_kind(k) && BOOLEAN_TYPE == n.GetType()))
+	FatalError("BVTypeCheck: not a formula:",n);
+      switch(k){
+      case TRUE:
+      case FALSE:
+      case SYMBOL:
+	return;
+      case EQ:
+      case NEQ:	 
+	if(!(n[0].GetValueWidth() == n[1].GetValueWidth() &&
+	     n[0].GetIndexWidth() == n[1].GetIndexWidth())) {
+	  cerr << "valuewidth of lhs of EQ: " << n[0].GetValueWidth() << endl;
+	  cerr << "valuewidth of rhs of EQ: " << n[1].GetValueWidth() << endl;
+	  cerr << "indexwidth of lhs of EQ: " << n[0].GetIndexWidth() << endl;
+	  cerr << "indexwidth of rhs of EQ: " << n[1].GetIndexWidth() << endl;
+	  FatalError("BVTypeCheck: terms in atomic formulas must be of equal length",n);
+	}
+	break;
+      case BVLT:
+      case BVLE:
+      case BVGT:
+      case BVGE:
+      case BVSLT:
+      case BVSLE:
+      case BVSGT:
+      case BVSGE:	
+	if(BITVECTOR_TYPE != n[0].GetType() && BITVECTOR_TYPE != n[1].GetType())
+	  FatalError("BVTypeCheck: terms in atomic formulas must be bitvectors",n);
+	if(n[0].GetValueWidth() != n[1].GetValueWidth())
+	  FatalError("BVTypeCheck: terms in atomic formulas must be of equal length",n);
+	if(n[0].GetIndexWidth() != n[1].GetIndexWidth())
+	  FatalError("BVTypeCheck: terms in atomic formulas must be of equal length",n);
+	break;
+      case NOT:
+	if(1 != n.Degree())
+	  FatalError("BVTypeCheck: NOT formula can have exactly one childNode",n);
+	break;
+      case AND:
+      case OR:
+      case XOR:
+      case NAND:
+      case NOR:
+	if(2 > n.Degree())
+	  FatalError("BVTypeCheck: AND/OR/XOR/NAND/NOR: must have atleast 2 ChildNodes",n);
+	break;
+      case IFF:
+      case IMPLIES:	
+	if(2 != n.Degree())
+	  FatalError("BVTypeCheck:IFF/IMPLIES must have exactly 2 ChildNodes",n);
+	break;
+      case ITE:
+	if(3 != n.Degree())
+	  FatalError("BVTypeCheck:ITE must have exactly 3 ChildNodes",n);		
+	break;
+      default:
+	FatalError("BVTypeCheck: Unrecognized kind: ",ASTUndefined);
+	break;
+      }
+    }
+  } //End of TypeCheck function
+
+  //add an assertion to the current logical context
+  void BeevMgr::AddAssert(const ASTNode& assert) {
+    if(!(is_Form_kind(assert.GetKind()) && BOOLEAN_TYPE == assert.GetType())) {
+      FatalError("AddAssert:Trying to assert a non-formula:",assert);
+    }
+      
+    ASTVec * v;
+    //if the stack of ASTVec is not empty, then take the top ASTVec
+    //and add the input assert to it
+    if(!_asserts.empty()) {
+      v = _asserts.back();
+      //v->push_back(TransformFormula(assert));
+      v->push_back(assert);
+    }
+    else {
+      //else create a logical context, and add it to the top of the
+      //stack
+      v = new ASTVec();
+      //v->push_back(TransformFormula(assert));
+      v->push_back(assert);
+      _asserts.push_back(v);	
+    }
+  }
+  
+  void BeevMgr::Push(void) {
+    ASTVec * v;
+    v = new ASTVec();
+    _asserts.push_back(v);
+  }
+  
+  void BeevMgr::Pop(void) {
+    if(!_asserts.empty()) {
+       ASTVec * c = _asserts.back();
+             //by calling the clear function we ensure that the ref count is
+             //decremented for the ASTNodes stored in c
+             c->clear();
+             delete c;
+      _asserts.pop_back();
+    }
+  }
+
+  void BeevMgr::AddQuery(const ASTNode& q) {
+    //_current_query = TransformFormula(q);
+    //cerr << "\nThe current query is: " << q << endl;
+    _current_query = q;
+  }
+    
+  const ASTNode BeevMgr::PopQuery() {
+    ASTNode q = _current_query;
+    _current_query = ASTTrue;
+    return q;
+  }
+   
+  const ASTNode BeevMgr::GetQuery() {
+    return _current_query;
+  }
+  
+  const ASTVec BeevMgr::GetAsserts(void) {
+    vector<ASTVec *>::iterator it = _asserts.begin();
+    vector<ASTVec *>::iterator itend = _asserts.end();
+    
+    ASTVec v;
+    for(;it!=itend;it++) {
+      if(!(*it)->empty())
+	  v.insert(v.end(),(*it)->begin(),(*it)->end());
+    }
+    return v;
+  }
+
+  //Create a new variable of ValueWidth 'n'
+  ASTNode BeevMgr::NewArrayVar(unsigned int index, unsigned int value) {
+    std:: string c("v");
+    char d[32];
+    sprintf(d,"%d",_symbol_count++);
+    std::string ccc(d);
+    c += "_writearray_" + ccc;
+    
+    ASTNode CurrentSymbol = CreateSymbol(c.c_str());
+    CurrentSymbol.SetValueWidth(value);
+    CurrentSymbol.SetIndexWidth(index);
+    return CurrentSymbol;
+  } //end of NewArrayVar()
+
+
+  //Create a new variable of ValueWidth 'n'
+  ASTNode BeevMgr::NewVar(unsigned int value) {
+    std:: string c("v");
+    char d[32];
+    sprintf(d,"%d",_symbol_count++);
+    std::string ccc(d);
+    c += "_new_stp_var_" + ccc;
+    
+    ASTNode CurrentSymbol = CreateSymbol(c.c_str());
+    CurrentSymbol.SetValueWidth(value);
+    CurrentSymbol.SetIndexWidth(0);
+    _introduced_symbols.insert(CurrentSymbol);
+    return CurrentSymbol;
+  } //end of NewVar()
+
+  //prints statistics for the ASTNode
+  void BeevMgr::ASTNodeStats(const char * c, const ASTNode& a){
+    if(!stats)
+      return;
+
+    StatInfoSet.clear();
+    //print node size:
+    cout << endl << "Printing: " << c;
+    if(print_nodes) {
+      //a.PL_Print(cout,0);
+      //cout << endl;
+      cout << a << endl;
+    }
+    cout << "Node size is: ";
+    cout << NodeSize(a) << endl << endl;    
+  }
+
+  unsigned int BeevMgr::NodeSize(const ASTNode& a, bool clearStatInfo) {    
+    if(clearStatInfo)
+      StatInfoSet.clear();
+
+    ASTNodeSet::iterator it;
+    if((it = StatInfoSet.find(a)) != StatInfoSet.end())
+      //has already been counted
+      return 0;
+
+    //record that you have seen this node already
+    StatInfoSet.insert(a);
+    
+    //leaf node has a size of 1
+    if(a.Degree() == 0)
+      return 1;
+
+    unsigned newn = 1;
+    ASTVec c = a.GetChildren();
+    for(ASTVec::iterator it=c.begin(),itend=c.end();it!=itend;it++)
+      newn += NodeSize(*it);
+    return newn;
+  }
+
+  void BeevMgr::ClearAllTables(void) {
+    //clear all tables before calling toplevelsat
+    _ASTNode_to_SATVar.clear();
+    _SATVar_to_AST.clear();
+
+    for(ASTtoBitvectorMap::iterator it=_ASTNode_to_Bitvector.begin(),
+	  itend=_ASTNode_to_Bitvector.end();it!=itend;it++) {
+      delete it->second;
+    }
+    _ASTNode_to_Bitvector.clear();
+    
+    /* OLD Destructor
+     * for(ASTNodeToVecMap::iterator ivec = BBTermMemo.begin(),
+	  ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+      ivec->second.clear();
+    }*/
+
+    /*What should I do here? For ASTNodes?
+     * for(ASTNodeMap::iterator ivec = BBTermMemo.begin(),
+	  ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+      ivec->second.clear();
+    }*/
+    BBTermMemo.clear();
+    BBFormMemo.clear();
+    NodeLetVarMap.clear();
+    NodeLetVarMap1.clear();
+    PLPrintNodeSet.clear();
+    AlreadyPrintedSet.clear();
+    SimplifyMap.clear();
+    SimplifyNegMap.clear();
+    SolverMap.clear();
+    AlwaysTrueFormMap.clear();
+    _arrayread_ite.clear();
+    _arrayread_symbol.clear();
+    _introduced_symbols.clear();
+    TransformMap.clear();
+    _letid_expr_map.clear();
+    CounterExampleMap.clear();
+    ComputeFormulaMap.clear();
+    StatInfoSet.clear();
+
+    // for(std::vector<ASTVec *>::iterator it=_asserts.begin(),
+    // 	  itend=_asserts.end();it!=itend;it++) {
+    //       (*it)->clear();
+    //     }
+    _asserts.clear();
+    for(ASTNodeToVecMap::iterator iset = _arrayname_readindices.begin(), 
+	  iset_end = _arrayname_readindices.end();
+	iset!=iset_end;iset++) {
+      iset->second.clear();
+    }
+
+    _arrayname_readindices.clear();
+    _interior_unique_table.clear();
+    _symbol_unique_table.clear();
+    _bvconst_unique_table.clear();
+  }
+
+  void BeevMgr::ClearAllCaches(void) {
+    //clear all tables before calling toplevelsat
+    _ASTNode_to_SATVar.clear();
+    _SATVar_to_AST.clear();
+
+
+    for(ASTtoBitvectorMap::iterator it=_ASTNode_to_Bitvector.begin(),
+	  itend=_ASTNode_to_Bitvector.end();it!=itend;it++) {
+      delete it->second;
+    }
+    _ASTNode_to_Bitvector.clear();
+    
+    /*OLD destructor
+     * for(ASTNodeToVecMap::iterator ivec = BBTermMemo.begin(),
+	  ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+      ivec->second.clear();
+    }*/
+
+    /*What should I do here?
+     *for(ASTNodeMap::iterator ivec = BBTermMemo.begin(),
+	  ivec_end=BBTermMemo.end();ivec!=ivec_end;ivec++) {
+      ivec->second.clear();
+    }*/
+    BBTermMemo.clear();
+    BBFormMemo.clear();
+    NodeLetVarMap.clear();
+    NodeLetVarMap1.clear();
+    PLPrintNodeSet.clear();
+    AlreadyPrintedSet.clear();
+    SimplifyMap.clear();
+    SimplifyNegMap.clear();
+    SolverMap.clear();
+    AlwaysTrueFormMap.clear();
+    _arrayread_ite.clear();
+    _arrayread_symbol.clear();
+    _introduced_symbols.clear();
+    TransformMap.clear();
+    _letid_expr_map.clear();
+    CounterExampleMap.clear();
+    ComputeFormulaMap.clear();
+    StatInfoSet.clear();
+
+    for(ASTNodeToVecMap::iterator iset = _arrayname_readindices.begin(), 
+	  iset_end = _arrayname_readindices.end();
+	iset!=iset_end;iset++) {
+      iset->second.clear();
+    }
+
+    _arrayname_readindices.clear();
+    //_interior_unique_table.clear();
+    //_symbol_unique_table.clear();
+    //_bvconst_unique_table.clear();
+  }
+
+  void BeevMgr::CopySolverMap_To_CounterExample(void) {
+    if(!SolverMap.empty()) {
+      CounterExampleMap.insert(SolverMap.begin(),SolverMap.end());
+    }
+  }
+
+  void FatalError(const char * str, const ASTNode& a, int w) {
+    if(a.GetKind() != UNDEFINED) {
+      cerr << "Fatal Error: " << str << endl << a << endl;
+      cerr << w << endl;
+    }
+    else {
+      cerr << "Fatal Error: " << str << endl;
+      cerr << w << endl;
+    }
+    if (vc_error_hdlr)
+      vc_error_hdlr(str);
+    exit(-1);
+    //assert(0);
+  }
+
+  void FatalError(const char * str) {
+    cerr << "Fatal Error: " << str << endl;
+    if (vc_error_hdlr)
+      vc_error_hdlr(str);
+    exit(-1);
+    //assert(0);
+  }
+
+  //Variable Order Printer: A global function which converts a MINISAT
+  //var into a ASTNODE var. It then prints this var along with
+  //variable order dcisions taken by MINISAT.
+  void Convert_MINISATVar_To_ASTNode_Print(int minisat_var, 
+  					   int decision_level, int polarity) {
+    BEEV::ASTNode vv = globalBeevMgr_for_parser->_SATVar_to_AST[minisat_var];
+    cout << spaces(decision_level);
+    if(polarity) {
+      cout << "!";
+    }
+    vv.PL_Print(cout,0);
+    cout << endl;
+  }
+
+  void SortByExprNum(ASTVec& v) {
+    sort(v.begin(), v.end(), exprless);
+  }
+
+  bool isAtomic(Kind kind) {
+    if(TRUE == kind ||
+       FALSE == kind ||
+       EQ == kind ||
+       NEQ == kind ||
+       BVLT == kind ||
+       BVLE == kind ||
+       BVGT == kind ||
+       BVGE == kind ||
+       BVSLT == kind ||
+       BVSLE == kind ||
+       BVSGT == kind ||
+       BVSGE == kind ||
+       SYMBOL == kind ||
+       BVGETBIT == kind)
+      return true;
+    return false;
+  }
+
+  BeevMgr::~BeevMgr() {
+    ClearAllTables();
+  }
+}; // end namespace
+