Exp *GenericExpTransformer::applyTo(Exp *e, bool &bMod) { bool change; Exp *bindings = e->match(match); if (bindings == NULL) { #if 0 if (e->getOper() == match->getOper()) LOG << "match failed: " << e << " with " << match << "\n"; #endif return e; } if (where) { Exp *cond = where->clone(); if (checkCond(cond, bindings) == false) return e; } LOG << "applying generic exp transformer match: " << match; if (where) LOG << " where: " << where; LOG << " become: " << become; LOG << " to: " << e; LOG << " bindings: " << bindings << "\n"; e = become->clone(); for (Exp *l = bindings; l->getOper() != opNil; l = l->getSubExp2()) e = e->searchReplaceAll(l->getSubExp1()->getSubExp1(), l->getSubExp1()->getSubExp2(), change); LOG << "calculated result: " << e << "\n"; bMod = true; Exp *r; if (e->search(new Unary(opVar, new Terminal(opWild)), r)) { LOG << "error: variable " << r << " in result!\n"; assert(false); } return e; }
Exp *ExpTransformer::applyAllTo(Exp *p, bool &bMod) { for (std::list<Exp*>::iterator it = cache.begin(); it != cache.end(); it++) if (*(*it)->getSubExp1() == *p) return (*it)->getSubExp2()->clone(); Exp *e = p->clone(); Exp *subs[3]; subs[0] = e->getSubExp1(); subs[1] = e->getSubExp2(); subs[2] = e->getSubExp3(); for (int i = 0; i < 3; i++) if (subs[i]) { bool mod = false; subs[i] = applyAllTo(subs[i], mod); if (mod && i == 0) e->setSubExp1(subs[i]); if (mod && i == 1) e->setSubExp2(subs[i]); if (mod && i == 2) e->setSubExp3(subs[i]); bMod |= mod; // if (mod) i--; } #if 0 LOG << "applyAllTo called on " << e << "\n"; #endif bool mod; //do { mod = false; for (std::list<ExpTransformer *>::iterator it = transformers.begin(); it != transformers.end(); it++) { e = (*it)->applyTo(e, mod); bMod |= mod; } //} while (mod); cache.push_back(new Binary(opEquals, p->clone(), e->clone())); return e; }
bool GenericExpTransformer::checkCond(Exp *cond, Exp *bindings) { switch (cond->getOper()) { case opAnd: return checkCond(cond->getSubExp1(), bindings) && checkCond(cond->getSubExp2(), bindings); case opEquals: { Exp *lhs = cond->getSubExp1(), *rhs = cond->getSubExp2(); for (Exp *l = bindings; l->getOper() != opNil; l = l->getSubExp2()) { Exp *e = l->getSubExp1(); bool change = false; lhs = lhs->searchReplaceAll(e->getSubExp1()->clone(), e->getSubExp2()->clone(), change); #if 0 if (change) LOG << "replaced " << e->getSubExp1() << " with " << e->getSubExp2() << "\n"; #endif change = false; rhs = rhs->searchReplaceAll(e->getSubExp1()->clone(), e->getSubExp2()->clone(), change); #if 0 if (change) LOG << "replaced " << e->getSubExp1() << " with " << e->getSubExp2() << "\n"; #endif } if (lhs->getOper() == opTypeOf) { #if 0 // ADHOC TA Type *ty = lhs->getSubExp1()->getType(); #else Type *ty = NULL; #endif if (ty == NULL) { #if 0 if (VERBOSE) LOG << "no type for typeof " << lhs << "\n"; #endif return false; } lhs = new TypeVal(ty); #if 0 LOG << "got typeval: " << lhs << "\n"; #endif } if (lhs->getOper() == opKindOf) { OPER op = lhs->getSubExp1()->getOper(); lhs = new Const(operStrings[op]); } rhs = applyFuncs(rhs); #if 0 LOG << "check equals in cond: " << lhs << " == " << rhs << "\n"; #endif if (lhs->getOper() == opVar) { Exp *le; for (le = bindings; le->getOper() != opNil && le->getSubExp2()->getOper() != opNil; le = le->getSubExp2()) ; assert(le->getOper() != opNil); le->setSubExp2(new Binary(opList, new Binary(opEquals, lhs->clone(), rhs->clone()), new Terminal(opNil))); #if 0 LOG << "bindings now: " << bindings << "\n"; #endif return true; } if (*lhs == *rhs) return true; #if 0 // ADHOC TA if (lhs->getOper() == opTypeVal && rhs->getOper() == opTypeVal && lhs->getType()->resolvesToCompound() && rhs->getType()->isCompound()) return true; #endif Exp *new_bindings = lhs->match(rhs); if (new_bindings == NULL) return false; #if 0 LOG << "matched lhs with rhs, bindings: " << new_bindings << "\n"; #endif Exp *le; for (le = bindings; le->getOper() != opNil && le->getSubExp2()->getOper() != opNil; le = le->getSubExp2()) ; assert(le->getOper() != opNil); le->setSubExp2(new_bindings); #if 0 LOG << "bindings now: " << bindings << "\n"; #endif return true; } default: LOG << "don't know how to handle oper " << operStrings[cond->getOper()] << " in cond.\n"; } return false; }