void OutputInputs(ostream &os, const ASTNode& n, hash_set<int> *alreadyOutput) { if (alreadyOutput->find(n.GetNodeNum()) != alreadyOutput->end()) return; alreadyOutput->insert(n.GetNodeNum()); if (n.GetKind() == BVGETBIT) { assert(n[1].GetKind() == BVCONST); std::stringstream nn; n[0].nodeprint(nn); nn << "_" << bvconstToString(n[1]); os << "INPUT(" << nn.str() << ")" << endl; return; } // A boolean symbol. if (n.GetKind() == SYMBOL) { os << "INPUT(" << symbolToString(n) << ")" << endl; return; } for (unsigned i = 0; i < n.Degree(); i++) { OutputInputs(os, n[i], alreadyOutput); } }
bool SubstitutionMap::UpdateSubstitutionMap(const ASTNode& e0, const ASTNode& e1) { int i = TermOrder(e0, e1); if (0 == i) return false; assert(e0 != e1); assert(e0.GetValueWidth() == e1.GetValueWidth()); assert(e0.GetIndexWidth() == e1.GetIndexWidth()); if (e0.GetKind() == SYMBOL) { if (CheckSubstitutionMap(e0)) { // e0 and e1 might both be variables, e0 is already substituted for, // but maybe not e1. if (e1.GetKind() == SYMBOL) i = -1; else return false; // already in the map. } if (loops(e0, e1)) return false; // loops. } if (e1.GetKind() == SYMBOL) { if (CheckSubstitutionMap(e1)) return false; // already in the map. if (loops(e1, e0)) return false; // loops } //e0 is of the form READ(Arr,const), and e1 is const, or //e0 is of the form var, and e1 is a function. if (1 == i && !CheckSubstitutionMap(e0)) { buildDepends(e0, e1); (*SolverMap)[e0] = e1; return true; } //e1 is of the form READ(Arr,const), and e0 is const, or //e1 is of the form var, and e0 is const if (-1 == i && !CheckSubstitutionMap(e1)) { buildDepends(e1, e0); (*SolverMap)[e1] = e0; return true; } return false; }
bool PropagateEqualities::searchTerm(const ASTNode& lhs, const ASTNode& rhs) { const unsigned width = lhs.GetValueWidth(); if (lhs == rhs) return true; if (lhs.GetKind() == SYMBOL) return simp->UpdateSubstitutionMap(lhs, rhs); // checks whether it's been // solved for, or if the RHS // contains the LHS. if (lhs.GetKind() == BVUMINUS) return searchTerm(lhs[0], nf->CreateTerm(BVUMINUS, width, rhs)); if (lhs.GetKind() == BVNEG) return searchTerm(lhs[0], nf->CreateTerm(BVNEG, width, rhs)); if (lhs.GetKind() == BVXOR || lhs.GetKind() == BVPLUS) for (size_t i = 0; i < lhs.Degree(); i++) { ASTVec others; for (size_t j = 0; j < lhs.Degree(); j++) if (j != i) others.push_back(lhs[j]); ASTNode new_rhs; if (lhs.GetKind() == BVXOR) { others.push_back(rhs); assert(others.size() > 1); new_rhs = nf->CreateTerm(lhs.GetKind(), width, others); } else if (lhs.GetKind() == BVPLUS) { if (others.size() > 1) new_rhs = nf->CreateTerm(BVPLUS, width, others); else new_rhs = others[0]; new_rhs = nf->CreateTerm(BVUMINUS, width, new_rhs); new_rhs = nf->CreateTerm(BVPLUS, width, new_rhs, rhs); } else FatalError("sdafasfsdf2q3234423"); bool result = searchTerm(lhs[i], new_rhs); if (result) return true; } if (lhs.Degree() == 2 && lhs.GetKind() == BVMULT && lhs[0].isConstant() && simp->BVConstIsOdd(lhs[0])) return searchTerm(lhs[1], nf->CreateTerm(BVMULT, width, simp->MultiplicativeInverse(lhs[0]), rhs)); return false; }
// If n0 is replaced by n1 in the substitution map. Will it cause a loop? // i.e. will the dependency graph be an acyclic graph still. // For example, if we have x = F(y,z,w), it would make the substitutionMap loop // if there's already z = F(x). bool SubstitutionMap::loops(const ASTNode& n0, const ASTNode& n1) { if (n0.GetKind() != SYMBOL) return false; // sometimes this function is called with constants on the // lhs. if (n1.isConstant()) return false; // constants contain no variables. Can't loop. // We are adding an edge FROM n0, so unless there is already an edge TO n0, // there is no change it can loop. Unless adding this would add a TO and FROM // edge. if (rhs.find(n0) == rhs.end()) { return vars.VarSeenInTerm(n0, n1); } if (n1.GetKind() == SYMBOL && dependsOn.find(n1) == dependsOn.end()) return false; // The rhs is a symbol and doesn't appear. if (debug_substn) cout << loopCount++ << endl; bool destruct = true; ASTNodeSet* dependN = vars.SetofVarsSeenInTerm(n1, destruct); if (debug_substn) { cout << n0 << " " << n1.GetNodeNum(); //<< " Expression size:" << bm->NodeSize(n1,true); cout << "Variables in expression: " << dependN->size() << endl; } set<ASTNode> depend(dependN->begin(), dependN->end()); if (destruct) delete dependN; set<ASTNode> visited; loops_helper(depend, visited); bool loops = visited.find(n0) != visited.end(); if (debug_substn) cout << "Visited:" << visited.size() << "Loops:" << loops << endl; return (loops); }
string bvconstToString(const ASTNode& n) { assert (n.GetKind() == BVCONST); std::stringstream output; output << *n.GetBVConst(); return output.str(); }
void outputBitVecSMTLIB2(const ASTNode n, ostream& os) { const Kind k = n.GetKind(); const ASTVec &c = n.GetChildren(); ASTNode op; if (BITVECTOR == k) { op = c[0]; } else if (BVCONST == k) { op = n; } else FatalError("nsadfsdaf"); // CONSTANTBV::BitVector_to_Dec returns a signed representation by default. // Prepend with zero to convert to unsigned. os << "(_ bv"; CBV unsign = CONSTANTBV::BitVector_Concat( n.GetSTPMgr()->CreateZeroConst(1).GetBVConst(), op.GetBVConst()); unsigned char * str = CONSTANTBV::BitVector_to_Dec(unsign); CONSTANTBV::BitVector_Destroy(unsign); os << str << " " << op.GetValueWidth() << ")"; CONSTANTBV::BitVector_Dispose(str); }
//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. STPMgr * bm = GetSTPMgr(); 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 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(),this->GetIndexWidth(),this->GetValueWidth()); /* 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. */ bm->NodeLetVarMap[ccc] = CurrentSymbol; std::pair<ASTNode, ASTNode> node_letvar_pair(CurrentSymbol, ccc); bm->NodeLetVarVec.push_back(node_letvar_pair); } } } } //end of LetizeNode()
ASTNode STPMgr::CreateSimpNot(const ASTNode& form) { Kind k = form.GetKind(); switch (k) { case FALSE: { return ASTTrue; } case TRUE: { return ASTFalse; } case NOT: { return form[0]; } // NOT NOT cancellation case XOR: { // Push negation down in this case. // FIXME: Separate pre-pass to push negation down? // CreateSimp should be local, and this isn't. // It isn't memoized. Arg. ASTVec children = form.GetChildren(); children[0] = CreateSimpNot(children[0]); return CreateSimpXor(children); } default: { return CreateNode(NOT, form); //return CreateNode(XOR, ASTTrue, form); } } }
// Build the polarities, then iterate through fixing them. bool FindPureLiterals::topLevel(ASTNode& n, Simplifier* simplifier, STPMgr* stpMgr) { stpMgr->GetRunTimes()->start(RunTimes::PureLiterals); build(n, truePolarity); bool changed = false; map<ASTNode, polarity_type>::const_iterator it = nodeToPolarity.begin(); while (it != nodeToPolarity.end()) { const ASTNode& n = it->first; const polarity_type polarity = it->second; if (n.GetType() == BOOLEAN_TYPE && n.GetKind() == SYMBOL && polarity != bothPolarity) { if (polarity == truePolarity) simplifier->UpdateSubstitutionMap(n, stpMgr->ASTTrue); else { assert(polarity == falsePolarity); simplifier->UpdateSubstitutionMap(n, stpMgr->ASTFalse); } changed = true; } it++; } stpMgr->GetRunTimes()->stop(RunTimes::PureLiterals); return changed; }
// Check that the transformations have occurred. void ArrayTransformer::assertTransformPostConditions(const ASTNode& term, ASTNodeSet& visited) { // I haven't measure whether this is the quickest way to do it? std::pair<ASTNodeSet::iterator, bool> p = visited.insert(term); if (!p.second) return; const Kind k = term.GetKind(); // Check the array reads / writes have been removed assert(READ != k); assert(WRITE != k); // There should be no nodes left of type array. assert(0 == term.GetIndexWidth()); const ASTVec& c = term.GetChildren(); ASTVec::const_iterator it = c.begin(); const ASTVec::const_iterator itend = c.end(); for (; it != itend; it++) { assertTransformPostConditions(*it, visited); } }
void LetizeNode(const ASTNode& n, ASTNodeSet& PLPrintNodeSet, bool smtlib1) { const Kind kind = n.GetKind(); if (kind == SYMBOL || kind == BVCONST || kind == FALSE || kind == TRUE) return; const ASTVec& c = n.GetChildren(); for (ASTVec::const_iterator it = c.begin(), itend = c.end(); it != itend; it++) { const ASTNode& ccc = *it; const Kind k = ccc.GetKind(); if (k == SYMBOL || k == BVCONST || k == FALSE || k == TRUE) continue; if (PLPrintNodeSet.find(ccc) == PLPrintNodeSet.end()) { // If branch: if *it is not in NodeSet then, // // 1. add it to NodeSet // // 2. Letize its childNodes PLPrintNodeSet.insert(ccc); LetizeNode(ccc, PLPrintNodeSet, smtlib1); } else { // 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 ((!smtlib1 || ccc.GetType() == BITVECTOR_TYPE) && NodeLetVarMap.find(ccc) == NodeLetVarMap.end()) { // Create a new symbol. Get some name. if it conflicts with a // declared name, too bad. int sz = NodeLetVarMap.size(); std::ostringstream oss; oss << "?let_k_" << sz; ASTNode CurrentSymbol = n.GetSTPMgr()->CreateSymbol( oss.str().c_str(), n.GetIndexWidth(), n.GetValueWidth()); /* 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.] */ NodeLetVarMap[ccc] = CurrentSymbol; std::pair<ASTNode, ASTNode> node_letvar_pair(CurrentSymbol, ccc); NodeLetVarVec.push_back(node_letvar_pair); } } } } // end of LetizeNode()
// Adds to the dependency graph that n0 depends on the variables in n1. // It's not the transitive closure of the dependencies. Just the variables in the expression "n1". // This is only needed as long as all the substitution rules haven't been written through. void SubstitutionMap::buildDepends(const ASTNode& n0, const ASTNode& n1) { if (n0.GetKind() != SYMBOL) return; if (n1.isConstant()) return; vector<Symbols*> av; vars.VarSeenInTerm(vars.getSymbol(n1), rhs_visited, rhs, av); sort(av.begin(), av.end()); for (int i = 0; i < av.size(); i++) { if (i != 0 && av[i] == av[i - 1]) continue; // Treat it like a set of Symbol* in effect. ASTNodeSet* sym = (vars.TermsAlreadySeenMap.find(av[i])->second); if (rhsAlreadyAdded.find(sym) != rhsAlreadyAdded.end()) continue; rhsAlreadyAdded.insert(sym); //cout << loopCount++ << " "; //cout << "initial" << rhs.size() << " Adding: " <<sym->size(); rhs.insert(sym->begin(), sym->end()); //cout << "final:" << rhs.size(); //cout << "added:" << sym << endl; } assert(dependsOn.find(n0) == dependsOn.end()); dependsOn.insert(make_pair(n0, vars.getSymbol(n1))); }
//this function looksup the "var to letexpr map" and returns the //corresponding letexpr. if there is no letexpr, then it simply //returns the var. ASTNode BeevMgr::ResolveID(const ASTNode& v) { if(v.GetKind() != SYMBOL) { return v; } if(_parser_symbol_table.find(v) != _parser_symbol_table.end()) { return v; } ASTNodeMap::iterator it; if((it =_letid_expr_map.find(v)) != _letid_expr_map.end()) { if(it->second == ASTUndefined) FatalError("Unresolved Identifier: ",v); else return it->second; } //this is to mark the let-var as undefined. the let var is defined //only after the LetExprMgr has completed its work, and until then //'v' is undefined. // //declared variables also get stored in this map, but there value //is ASTUndefined. This is really a hack. I don't know how to get //rid of this hack. _letid_expr_map[v] = ASTUndefined; return v; }
// nb. This avoids the expensive checks that usually updating the substitution map // entails. void RemoveUnconstrained::replace(const ASTNode& from, const ASTNode to) { assert(from.GetKind() == SYMBOL); assert(from.GetValueWidth() == to.GetValueWidth()); simplifier_convenient->UpdateSubstitutionMapFewChecks(from, to); return; }
void Dot_Print1(ostream &os, const ASTNode n, hash_set<int> *alreadyOutput) { // check if this node has already been printed. If so return. if (alreadyOutput->find(n.GetNodeNum()) != alreadyOutput->end()) return; alreadyOutput->insert(n.GetNodeNum()); os << "n" << n.GetNodeNum() << "[label =\""; switch (n.GetKind()) { case SYMBOL: n.nodeprint(os); break; case BITVECTOR: case BVCONST: outputBitVec(n, os); break; default: os << _kind_names[n.GetKind()]; } os << "\"];" << endl; // print the edges to each child. ASTVec ch = n.GetChildren(); ASTVec::iterator itend = ch.end(); int i = 0; for (ASTVec::iterator it = ch.begin(); it < itend; it++) { os << "n" << n.GetNodeNum() << " -> " << "n" << it->GetNodeNum() << "[label=" << i++ << "];" << endl; } // print each of the children. for (ASTVec::iterator it = ch.begin(); it < itend; it++) { Dot_Print1(os, *it, alreadyOutput); } }
bool CNFMgr::onChildDoNeg(const ASTNode& varphi, unsigned int idx) { bool result = false; Kind k = varphi.GetKind(); switch (k) { case NOT: { result = true; break; } case NAND: { result = true; break; } case NOR: { result = true; break; } case XOR: { result = true; break; } case IFF: { result = true; break; } case IMPLIES: { if (idx == 0) { result = true; } break; } case ITE: { if (idx == 0) { result = true; } break; } default: { break; } } return result; } //End of onChildDoNeg()
// ABC doesn't like spaces, nor brackets. in variable names. // TODO CHECK that this doesn't cause duplicate names string symbolToString(const ASTNode& n) { assert(n.GetKind() == SYMBOL); std::stringstream output; n.nodeprint(output); string result = output.str(); replace(result.begin(), result.end(), ' ', '_'); replace(result.begin(), result.end(), '(', '_'); replace(result.begin(), result.end(), ')', '_'); return result; }
/* 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. * * If this returns, this ALWAYS returns true. If there is an error it * will call FatalError() and abort. */ bool BVTypeCheck(const ASTNode& n) { const Kind k = n.GetKind(); if (is_Term_kind(k)) { return BVTypeCheck_term_kind(n, k); } else { return BVTypeCheck_nonterm_kind(n, k); } }
bool VariablesInExpression::VarSeenInTerm(const ASTNode& var, const ASTNode& term) { // This only returns true if we are searching for variables that aren't arrays. assert(var.GetKind() == SYMBOL && var.GetIndexWidth() == 0); if (term.isConstant()) return false; getSymbol(term); SymbolPtrSet visited; ASTNodeSet *symbols = new ASTNodeSet(); vector<Symbols*> av; VarSeenInTerm(symbol_graph[term.GetNodeNum()], visited, *symbols, av); bool result = (symbols->count(var) != 0); //cerr << "visited:" << visited.size() << endl; //cerr << "av:" << av.size() << endl; //cerr << "Term is const" << term.isConstant() << endl; if (visited.size() > 250) // No use caching it, unless we've done some work. { sort(av.begin(), av.end()); //cout << "===" << endl; for (size_t i = 0; i < av.size(); i++) { if (i!=0 && av[i] == av[i-1]) continue; const ASTNodeSet& sym = *TermsAlreadySeenMap.find(av[i])->second; //cout << "set: " << i << " " << sym.size() << endl; symbols->insert(sym.begin(), sym.end()); } TermsAlreadySeenMap.insert(make_pair(symbol_graph[term.GetNodeNum()], symbols)); //cout << "finish" << symbols->size() << endl; //cout << "===" << endl; result = (symbols->count(var) != 0); } else { const int size = av.size(); for (int i = 0; i < size; i++) { if (result) break; const ASTNodeSet& sym = *TermsAlreadySeenMap.find(av[i])->second; result |= (sym.find(var) != sym.end()); } delete symbols; } return result; }
//if a is READ(Arr,const) and b is BVCONST then return 1. //if a is a symbol SYMBOL, return 1. //if b is READ(Arr,const) and a is BVCONST then return -1 // if b is a symbol return -1. // //else return 0 by default int TermOrder(const ASTNode& a, const ASTNode& b) { const Kind k1 = a.GetKind(); const Kind k2 = b.GetKind(); if (k1 == SYMBOL) return 1; if (k2 == SYMBOL) return -1; //a is of the form READ(Arr,const), and b is const, or if ((k1 == READ && a[0].GetKind() == SYMBOL && a[1].GetKind() == BVCONST && (k2 == BVCONST))) return 1; //b is of the form READ(Arr,const), and a is const, or //b is of the form var, and a is const if ((k1 == BVCONST) && ((k2 == READ && b[0].GetKind() == SYMBOL && b[1].GetKind() == BVCONST))) return -1; return 0; } //End of TermOrder()
// This is for sorting by arithmetic expressions (for // combining like terms, etc.) bool arithless(const ASTNode n1, const ASTNode n2) { Kind k1 = n1.GetKind(); Kind k2 = n2.GetKind(); if (n1 == n2) { // necessary for "strict weak ordering" return false; } else if (BVCONST == k1 && BVCONST != k2) { // put consts first return true; } else if (BVCONST != k1 && BVCONST == k2) { // put consts first return false; } else if (SYMBOL == k1 && SYMBOL != k2) { // put symbols next return true; } else if (SYMBOL != k1 && SYMBOL == k2) { // put symbols next return false; } else { // otherwise, sort by exprnum (descendents will appear // before ancestors). return (n1.GetNodeNum() < n2.GetNodeNum()); } } //end of arithless
void CNFMgr::convertFormulaToCNFPosPred(const ASTNode& varphi, ClauseList* defs) { ASTVec psis; ASTVec::const_iterator it = varphi.GetChildren().begin(); for (; it != varphi.GetChildren().end(); it++) { convertTermForCNF(*it, defs); psis.push_back(*(info[*it]->termforcnf)); } info[varphi]->clausespos = SINGLETON(bm->CreateNode(varphi.GetKind(), psis)); } //End of convertFormulaToCNFPosPred()
//Creates Array Write Axioms ASTNode AbsRefine_CounterExample::Create_ArrayWriteAxioms(const ASTNode& term, const ASTNode& newvar) { if (READ != term.GetKind() && WRITE != term[0].GetKind()) { FatalError("Create_ArrayWriteAxioms: "\ "Input must be a READ over a WRITE", term); } ASTNode lhs = newvar; ASTNode rhs = term; ASTNode arraywrite_axiom = simp->CreateSimplifiedEQ(lhs, rhs); return arraywrite_axiom; }//end of Create_ArrayWriteAxioms()
void buildListOfSymbols(const ASTNode& n, ASTNodeSet& visited, ASTNodeSet& symbols) { if (visited.find(n) != visited.end()) return; // already visited. visited.insert(n); if (n.GetKind() == SYMBOL) { symbols.insert(n); } for (unsigned i = 0; i < n.GetChildren().size(); i++) buildListOfSymbols(n[i], visited, symbols); }
bool PropagateEqualities::searchXOR(const ASTNode& lhs, const ASTNode& rhs) { Kind k = lhs.GetKind(); if (lhs == rhs) return true; if (k == SYMBOL) return simp->UpdateSubstitutionMap( lhs, rhs); // checks whether it's been solved for or loops. if (k == NOT) return searchXOR(lhs[0], nf->CreateNode(NOT, rhs)); bool result = false; if (k == XOR) for (size_t i = 0; i < lhs.Degree(); i++) { ASTVec others; for (size_t j = 0; j < lhs.Degree(); j++) if (j != i) others.push_back(lhs[j]); others.push_back(rhs); assert(others.size() > 1); ASTNode new_rhs = nf->CreateNode(XOR, others); result = searchXOR(lhs[i], new_rhs); if (result) return result; } if (k == EQ && lhs[0].GetValueWidth() == 1) { bool result = searchTerm(lhs[0], nf->CreateTerm(ITE, 1, rhs, lhs[1], nf->CreateTerm(BVNEG, 1, lhs[1]))); if (!result) result = searchTerm(lhs[1], nf->CreateTerm(ITE, 1, rhs, lhs[0], nf->CreateTerm(BVNEG, 1, lhs[0]))); } return result; }
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); assert(0); // gdb will stop here giving a stacktrace. exit(-1); }
//this function looks up the "var to letexpr map" and returns the //corresponding letexpr. if there is no letexpr, then it simply //returns the var. ASTNode LETMgr::ResolveID(const ASTNode& v) { if (v.GetKind() != SYMBOL) { return v; } if(_parser_symbol_table.find(v) != _parser_symbol_table.end()) { return v; } MapType::iterator it; if((it =_letid_expr_map->find(v.GetName())) != _letid_expr_map->end()) { return it->second; } return v; }//End of ResolveID()
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); } abort(); }
void CNFMgr::convertTermForCNF(const ASTNode& varphi, ClauseList* defs) { CNFInfo* x = info[varphi]; //######################################## // step 1, done if we've already visited //######################################## if (x->termforcnf != NULL) { return; } //######################################## // step 2, ITE's always get renamed //######################################## if (varphi.isITE()) { x->termforcnf = doRenameITE(varphi, defs); reduceMemoryFootprintPos(varphi[0]); reduceMemoryFootprintNeg(varphi[0]); } else if (varphi.isAtom()) { x->termforcnf = ASTNodeToASTNodePtr(varphi); } else { ASTVec psis; ASTVec::const_iterator it = varphi.GetChildren().begin(); for (; it != varphi.GetChildren().end(); it++) { convertTermForCNF(*it, defs); psis.push_back(*(info[*it]->termforcnf)); } ASTNode psi = bm->CreateNode(varphi.GetKind(), psis); psi.SetValueWidth(varphi.GetValueWidth()); psi.SetIndexWidth(varphi.GetIndexWidth()); x->termforcnf = ASTNodeToASTNodePtr(psi); } } //End of convertTermForCNF()
// counts the number of reads. Shortcut when we get to the limit. void numberOfReadsLessThan(const ASTNode& n, hash_set<int>& visited, int& soFar, const int limit) { if (n.isAtom()) return; if (visited.find(n.GetNodeNum()) != visited.end()) return; if (n.GetKind() == READ) soFar++; if (soFar > limit) return; visited.insert(n.GetNodeNum()); for (size_t i = 0; i < n.Degree(); i++) numberOfReadsLessThan(n[i], visited, soFar, limit); }