/* * Kodkod -- Copyright (c) 2005-present, Emina Torlak * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package kodkod.ast.visitor; import kodkod.ast.BinaryExpression; import kodkod.ast.BinaryFormula; import kodkod.ast.BinaryIntExpression; import kodkod.ast.ComparisonFormula; import kodkod.ast.Comprehension; import kodkod.ast.ConstantExpression; import kodkod.ast.ConstantFormula; import kodkod.ast.Decl; import kodkod.ast.Decls; import kodkod.ast.ExprToIntCast; import kodkod.ast.Expression; import kodkod.ast.Formula; import kodkod.ast.IfExpression; import kodkod.ast.IfIntExpression; import kodkod.ast.IntComparisonFormula; import kodkod.ast.IntConstant; import kodkod.ast.IntExpression; import kodkod.ast.IntToExprCast; import kodkod.ast.MultiplicityFormula; import kodkod.ast.NaryExpression; import kodkod.ast.NaryFormula; import kodkod.ast.NaryIntExpression; import kodkod.ast.Node; import kodkod.ast.NotFormula; import kodkod.ast.ProjectExpression; import kodkod.ast.QuantifiedFormula; import kodkod.ast.Relation; import kodkod.ast.RelationPredicate; import kodkod.ast.SumExpression; import kodkod.ast.UnaryExpression; import kodkod.ast.UnaryIntExpression; import kodkod.ast.Variable; /** * Implements a depth first traversal of the kodkod AST. * * @author Emina Torlak */ public abstract class AbstractVoidVisitor implements VoidVisitor { protected AbstractVoidVisitor() {} /** * Returns true if this node has already been visited. * Otherwise returns false. * @return true if this node has already been visited. */ protected abstract boolean visited(Node n) ; /** * Visits all the children of the given declarations node if * this.visited(decls) returns false. Otherwise does nothing. * @ensures all d: declarations.declarations | d.variable.accept(this) && d.expression.accept(this) */ public void visit(Decls decls) { if (visited(decls)) return; for (Decl decl : decls) { decl.accept(this); } } /** * Visits the variable and expression of this decl if * this.visited(decl) returns false. Otherwise does nothing. * @ensures decl.variable.accept(this) && decl.expression.accept(this) */ public void visit(Decl decl) { if (visited(decl)) return; decl.variable().accept(this); decl.expression().accept(this); } /** * Does nothing. */ public void visit(Relation relation) {} /** * Does nothing. */ public void visit(Variable variable) {} /** * Does nothing. */ public void visit(ConstantExpression constExpr) {} /** * Visits the children if this.visited(expr) returns false. Otherwise does nothing. * @ensures all i: [0..#expr.children) | expr.child(i).accept(this) */ public void visit(NaryExpression expr) { if (visited(expr)) return; for(Expression child : expr) { child.accept(this); } } /** * Visits the left and right subexpressions if * this.visited(binExpr) returns false. Otherwise does nothing. * @ensures binExpr.left.accept(this) && binExpr.right.accept(this) */ public void visit(BinaryExpression binExpr) { if (visited(binExpr)) return; binExpr.left().accept(this); binExpr.right().accept(this); } /** * Visits the subexpression if * this.visited(unaryExpr) returns false. Otherwise does nothing. * @ensures unaryExpr.expression.accept(this) */ public void visit(UnaryExpression unaryExpr) { if (visited(unaryExpr)) return; unaryExpr.expression().accept(this); } /** * Visits the declarations and the formula if * this.visited(comprehension) returns false. Otherwise does nothing. * @ensures comprehension.declarations.accept(this) && comprehension.formula.accept(this) */ public void visit(Comprehension comprehension) { if (visited(comprehension)) return; comprehension.decls().accept(this); comprehension.formula().accept(this); } /** * Visits the if-condition, the then-expression, and the else-expression if * this.visited(ifExpr) returns false. Otherwise does nothing. * @ensures ifExpr.condition.accept(this) && ifExpr.thenExpr.accept(this) && * ifExpr.elseExpr.accept(this) */ public void visit(IfExpression ifExpr) { if (visited(ifExpr)) return; ifExpr.condition().accept(this); ifExpr.thenExpr().accept(this); ifExpr.elseExpr().accept(this); } /** * Visits project.expression and project.columns if this.visited(project) returns false. * Otherwise does nothing. * @ensures project.expression.accept(this) && all i: project.arity | project.columns[i].accept(this) */ public void visit(ProjectExpression project) { if (visited(project)) return; project.expression().accept(this); for(int i = 0, arity = project.arity(); i < arity; i++) { project.column(i).accept(this); } } /** * Visits castExpr.intExpr if * this.visited(castExpr) returns false. Otherwise does nothing. * @ensures castExpr.expression.accept(this) */ public void visit(IntToExprCast castExpr) { if (visited(castExpr)) return; castExpr.intExpr().accept(this); } /** * Does nothing. */ public void visit(IntConstant intConst) {} /** * Visits the if-condition, the then-expression, and the else-expression if * this.visited(intExpr) returns false. Otherwise does nothing. * @ensures intExpr.condition.accept(this) && intExpr.thenExpr.accept(this) && * intExpr.elseExpr.accept(this) */ public void visit(IfIntExpression intExpr) { if (visited(intExpr)) return; intExpr.condition().accept(this); intExpr.thenExpr().accept(this); intExpr.elseExpr().accept(this); } /** * Visits intExpr.expression if * this.visited(intExpr) returns false. Otherwise does nothing. * @ensures intExpr.expression.accept(this) */ public void visit(ExprToIntCast intExpr) { if (visited(intExpr)) return; intExpr.expression().accept(this); } /** * Visits the children if this.visited(intExpr) returns false. Otherwise does nothing. * @ensures all i: [0..#intExpr.children) | intExpr.child(i).accept(this) */ public void visit(NaryIntExpression intExpr) { if (visited(intExpr)) return; for(IntExpression child : intExpr) { child.accept(this); } } /** * Visits the children of the given integer expression if * this.visited(intExpr) returns false. Otherwise does nothing. * @ensures intExpr.left.accept(this) && intExpr.right.accept(this) */ public void visit(BinaryIntExpression intExpr) { if (visited(intExpr)) return; intExpr.left().accept(this); intExpr.right().accept(this); } /** * Visits the subexpression if * this.visited(intExpr) returns false. Otherwise does nothing. * @ensures unaryExpr.expression.accept(this) */ public void visit(UnaryIntExpression intExpr) { if (visited(intExpr)) return; intExpr.intExpr().accept(this); } /** * Visits the children of the given sum expression if * this.visited(intExpr) returns false. Otherwise does nothing. * @ensures intExpr.decls.accept(this) && intExpr.intExpr.accept(this) */ public void visit(SumExpression intExpr) { if (visited(intExpr)) return; intExpr.decls().accept(this); intExpr.intExpr().accept(this); } /** * Visits the children of the given integer comparison formula if * this.visited(intComp) returns false. Otherwise does nothing. * @ensures intComp.left.accept(this) && intComp.right.accept(this) */ public void visit(IntComparisonFormula intComp) { if (visited(intComp)) return; intComp.left().accept(this); intComp.right().accept(this); } /** * Visits the declarations and the formula if * this.visited(quantFormula) returns false. Otherwise does nothing. * @ensures quantFormula.declarations.accept(this) && quantFormula.formula.accept(this) */ public void visit(QuantifiedFormula quantFormula) { if (visited(quantFormula)) return; quantFormula.decls().accept(this); quantFormula.formula().accept(this); } /** * Visits the children if this.visited(formula) returns false. Otherwise does nothing. * @ensures all i: [0..#formula.children) | formula.child(i).accept(this) */ public void visit(NaryFormula formula) { if (visited(formula)) return; for(Formula child : formula) { child.accept(this); } } /** * Visits the left and right children if * this.visited(binFormula) returns false. Otherwise does nothing. * @ensures binFormula.left.accept(this) && binFormula.right.accept(this) */ public void visit(BinaryFormula binFormula) { if (visited(binFormula)) return; binFormula.left().accept(this); binFormula.right().accept(this); } /** * Visits the subformula if * this.visited(not) returns false. Otherwise does nothing. * @ensures not.formula.accept(this) */ public void visit(NotFormula not) { if (visited(not)) return; not.formula().accept(this); } /** * Does nothing. */ public void visit(ConstantFormula constant) {} /** * Visits the left and right children if * this.visited(compFormula) returns false. Otherwise does nothing. * @ensures compFormula.left.accept(this) && compFormula.right.accept(this) */ public void visit(ComparisonFormula compFormula) { if (visited(compFormula)) return; compFormula.left().accept(this); compFormula.right().accept(this); } /** * Visits the formula if * this.visited(multFormula) returns false. Otherwise does nothing. * @ensures multFormula.expression.accept(this) */ public void visit(MultiplicityFormula multFormula) { if (visited(multFormula)) return; multFormula.expression().accept(this); } /** * Visits the children of the predicate if * this.visited(pred) returns false. Otherwise does nothing. * @ensures pred.relation.accept(this) && * (pred.name = FUNCTION => pred.domain.accept(this) && pred.range.accept(this)) && * (pred.name = TOTAL_ORDERING => * pred.ordered.accept(this) && pred.first.accept(this) && pred.last.accept(this) ) */ public void visit(RelationPredicate pred) { if (visited(pred)) return; pred.relation().accept(this); if (pred.name()==RelationPredicate.Name.FUNCTION) { final RelationPredicate.Function fp = (RelationPredicate.Function) pred; fp.domain().accept(this); fp.range().accept(this); } else if (pred.name()==RelationPredicate.Name.TOTAL_ORDERING) { final RelationPredicate.TotalOrdering tp = (RelationPredicate.TotalOrdering) pred; tp.ordered().accept(this); tp.first().accept(this); tp.last().accept(this); } } }