class RewritingVisitor :
ISolverModelConstraintVisitor<AbstractConstraint>,
ISolverModelExprVisitor<AbstractExpr> {
private readonly IDictionary<AbstractExpr, AbstractExpr> _rewrites;
public RewritingVisitor(
IDictionary<AbstractExpr, AbstractExpr> rewrites) {
_rewrites = rewrites;
}
// ...
}
ISolverModelConstraintVisitor<AbstractConstraint>,
ISolverModelExprVisitor<AbstractExpr> {
private readonly IDictionary<AbstractExpr, AbstractExpr> _rewrites;
public RewritingVisitor(
IDictionary<AbstractExpr, AbstractExpr> rewrites) {
_rewrites = rewrites;
}
// ...
}
For the three simple expressions—NamedVariables, AnchorVariables, and Constants—we return the replacement from the dictionary; or the original expression, if there is no replacement:
private AbstractExpr RewriteSimpleExpr(AbstractExpr expr) {
AbstractExpr result;
return _rewrites.TryGetValue(expr, out result) ? result : expr;
}
public AbstractExpr Visit(Constant constant, Ignore p) {
return RewriteSimpleExpr(constant);
}
public AbstractExpr Visit(NamedVariable namedVariable, Ignore p) {
return RewriteSimpleExpr(namedVariable);
}
public AbstractExpr Visit(AnchorVariable anchorVariable, Ignore p) {
return RewriteSimpleExpr(anchorVariable);
}
AbstractExpr result;
return _rewrites.TryGetValue(expr, out result) ? result : expr;
}
public AbstractExpr Visit(Constant constant, Ignore p) {
return RewriteSimpleExpr(constant);
}
public AbstractExpr Visit(NamedVariable namedVariable, Ignore p) {
return RewriteSimpleExpr(namedVariable);
}
public AbstractExpr Visit(AnchorVariable anchorVariable, Ignore p) {
return RewriteSimpleExpr(anchorVariable);
}
The code for unary and binary epxressions looks somewhat similar to the constant folding visitor. But as we do not need any operator-specific behavior, it consists only of these two methods:
public AbstractExpr Visit(UnaryExpression unaryExpression, Ignore p) {
AbstractExpr result;
if (_rewrites.TryGetValue(unaryExpression, out result)) {
return result;
} else {
AbstractExpr oldInner = unaryExpression.Inner;
AbstractExpr newInner = oldInner.Accept(this, Ig.nore);
if (newInner != oldInner) {
return new UnaryExpression(newInner, unaryExpression.Op);
} else {
return unaryExpression;
}
}
}
public AbstractExpr Visit(BinaryExpression binaryExpression, Ignore p) {
AbstractExpr result;
if (_rewrites.TryGetValue(binaryExpression, out result)) {
return result;
} else {
AbstractExpr oldLhs = binaryExpression.Lhs;
AbstractExpr oldRhs = binaryExpression.Rhs;
AbstractExpr newLhs = oldLhs.Accept(this, Ig.nore);
AbstractExpr newRhs = oldRhs.Accept(this, Ig.nore);
if (newLhs != oldLhs | newRhs != oldRhs) {
return new BinaryExpression(
newLhs, binaryExpression.Op, newRhs);
} else {
return binaryExpression;
}
}
}
AbstractExpr result;
if (_rewrites.TryGetValue(unaryExpression, out result)) {
return result;
} else {
AbstractExpr oldInner = unaryExpression.Inner;
AbstractExpr newInner = oldInner.Accept(this, Ig.nore);
if (newInner != oldInner) {
return new UnaryExpression(newInner, unaryExpression.Op);
} else {
return unaryExpression;
}
}
}
public AbstractExpr Visit(BinaryExpression binaryExpression, Ignore p) {
AbstractExpr result;
if (_rewrites.TryGetValue(binaryExpression, out result)) {
return result;
} else {
AbstractExpr oldLhs = binaryExpression.Lhs;
AbstractExpr oldRhs = binaryExpression.Rhs;
AbstractExpr newLhs = oldLhs.Accept(this, Ig.nore);
AbstractExpr newRhs = oldRhs.Accept(this, Ig.nore);
if (newLhs != oldLhs | newRhs != oldRhs) {
return new BinaryExpression(
newLhs, binaryExpression.Op, newRhs);
} else {
return binaryExpression;
}
}
}
Oh yes—test cases. I forgot to present them here. But I wrote a few of them!
No comments:
Post a Comment