/* This file is part of the db4o object database http://www.db4o.com Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com db4o is free software; you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation. db4o is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. */ package EDU.purdue.cs.bloat.trans; import EDU.purdue.cs.bloat.tree.*; /** * NodeComparator is a class used to differentiate nodes in an expression tree. */ public class NodeComparator { public static boolean DEBUG = false; /** * Determines whether or not two <tt>Node</tt>s are equal. */ public static boolean equals(final Node v, final Node w) { class Bool { boolean value = false; } ; final Bool eq = new Bool(); v.visit(new TreeVisitor() { public void visitExprStmt(final ExprStmt stmt) { if (w instanceof ExprStmt) { eq.value = true; } } public void visitIfCmpStmt(final IfCmpStmt stmt) { if (w instanceof IfCmpStmt) { final IfCmpStmt s = (IfCmpStmt) w; eq.value = (stmt.trueTarget() == s.trueTarget()) && (stmt.falseTarget() == s.falseTarget()) && (stmt.comparison() == s.comparison()); } } public void visitIfZeroStmt(final IfZeroStmt stmt) { if (w instanceof IfZeroStmt) { final IfZeroStmt s = (IfZeroStmt) w; eq.value = (stmt.trueTarget() == s.trueTarget()) && (stmt.falseTarget() == s.falseTarget()) && (stmt.comparison() == s.comparison()); } } public void visitSCStmt(final SCStmt stmt) { if (w instanceof SCStmt) { final SCStmt s = (SCStmt) w; eq.value = (stmt.array() == s.array()) && (stmt.index() == s.index()); } } public void visitSRStmt(final SRStmt stmt) { if (w instanceof SRStmt) { final SRStmt s = (SRStmt) w; eq.value = (stmt.array() == s.array()) && (stmt.start() == s.start()) && (stmt.end() == s.end()); } } public void visitInitStmt(final InitStmt stmt) { if (w instanceof InitStmt) { eq.value = true; } } public void visitGotoStmt(final GotoStmt stmt) { if (w instanceof GotoStmt) { final GotoStmt s = (GotoStmt) w; eq.value = stmt.target() == s.target(); } } public void visitLabelStmt(final LabelStmt stmt) { if (w instanceof LabelStmt) { final LabelStmt s = (LabelStmt) w; eq.value = stmt.label().equals(s.label()); } } public void visitMonitorStmt(final MonitorStmt stmt) { if (w instanceof MonitorStmt) { final MonitorStmt s = (MonitorStmt) w; eq.value = stmt.kind() == s.kind(); } } public void visitPhiJoinStmt(final PhiJoinStmt stmt) { if (w instanceof PhiJoinStmt) { eq.value = true; } } public void visitPhiCatchStmt(final PhiCatchStmt stmt) { if (w instanceof PhiCatchStmt) { eq.value = true; } } public void visitCatchExpr(final CatchExpr expr) { // Catches are not equivalent. eq.value = false; } public void visitStackManipStmt(final StackManipStmt stmt) { if (w instanceof StackManipStmt) { final StackManipStmt s = (StackManipStmt) w; eq.value = stmt.kind() == s.kind(); } } public void visitRetStmt(final RetStmt stmt) { if (w instanceof RetStmt) { final RetStmt s = (RetStmt) w; eq.value = stmt.sub() == s.sub(); } } public void visitReturnExprStmt(final ReturnExprStmt stmt) { if (w instanceof ReturnExprStmt) { eq.value = true; } } public void visitReturnStmt(final ReturnStmt stmt) { if (w instanceof ReturnStmt) { eq.value = true; } } public void visitAddressStoreStmt(final AddressStoreStmt stmt) { if (w instanceof AddressStoreStmt) { final AddressStoreStmt s = (AddressStoreStmt) w; eq.value = stmt.sub() == s.sub(); } } public void visitStoreExpr(final StoreExpr expr) { if (w instanceof StoreExpr) { eq.value = true; } } public void visitJsrStmt(final JsrStmt stmt) { if (w instanceof JsrStmt) { final JsrStmt s = (JsrStmt) w; eq.value = stmt.sub() == s.sub(); } } public void visitSwitchStmt(final SwitchStmt stmt) { if (w instanceof SwitchStmt) { eq.value = stmt == w; } } public void visitThrowStmt(final ThrowStmt stmt) { if (w instanceof ThrowStmt) { eq.value = true; } } public void visitArithExpr(final ArithExpr expr) { if (w instanceof ArithExpr) { final ArithExpr e = (ArithExpr) w; eq.value = e.operation() == expr.operation(); } } public void visitArrayLengthExpr(final ArrayLengthExpr expr) { if (w instanceof ArrayLengthExpr) { eq.value = true; } } public void visitArrayRefExpr(final ArrayRefExpr expr) { if (w instanceof ArrayRefExpr) { eq.value = true; } } public void visitCallMethodExpr(final CallMethodExpr expr) { // Calls are never equal. eq.value = false; } public void visitCallStaticExpr(final CallStaticExpr expr) { // Calls are never equal. eq.value = false; } public void visitCastExpr(final CastExpr expr) { if (w instanceof CastExpr) { final CastExpr e = (CastExpr) w; eq.value = e.castType().equals(expr.castType()); } } public void visitConstantExpr(final ConstantExpr expr) { if (w instanceof ConstantExpr) { final ConstantExpr e = (ConstantExpr) w; if (e.value() == null) { eq.value = expr.value() == null; } else { eq.value = e.value().equals(expr.value()); } } } public void visitFieldExpr(final FieldExpr expr) { if (w instanceof FieldExpr) { final FieldExpr e = (FieldExpr) w; eq.value = e.field().equals(expr.field()); } } public void visitInstanceOfExpr(final InstanceOfExpr expr) { if (w instanceof InstanceOfExpr) { final InstanceOfExpr e = (InstanceOfExpr) w; eq.value = e.checkType().equals(expr.checkType()); } } public void visitLocalExpr(final LocalExpr expr) { if (w instanceof LocalExpr) { final LocalExpr e = (LocalExpr) w; eq.value = e.def() == expr.def(); } } public void visitNegExpr(final NegExpr expr) { if (w instanceof NegExpr) { eq.value = true; } } public void visitNewArrayExpr(final NewArrayExpr expr) { eq.value = false; } public void visitNewExpr(final NewExpr expr) { eq.value = false; } public void visitNewMultiArrayExpr(final NewMultiArrayExpr expr) { eq.value = false; } public void visitZeroCheckExpr(final ZeroCheckExpr expr) { if (w instanceof ZeroCheckExpr) { eq.value = true; } } public void visitRCExpr(final RCExpr expr) { if (w instanceof RCExpr) { eq.value = true; } } public void visitUCExpr(final UCExpr expr) { if (w instanceof UCExpr) { final UCExpr e = (UCExpr) w; eq.value = e.kind() == expr.kind(); } } public void visitReturnAddressExpr(final ReturnAddressExpr expr) { if (w instanceof ReturnAddressExpr) { eq.value = true; } } public void visitShiftExpr(final ShiftExpr expr) { if (w instanceof ShiftExpr) { final ShiftExpr e = (ShiftExpr) w; eq.value = e.dir() == expr.dir(); } } public void visitStackExpr(final StackExpr expr) { if (w instanceof StackExpr) { final StackExpr e = (StackExpr) w; eq.value = e.def() == expr.def(); } } public void visitStaticFieldExpr(final StaticFieldExpr expr) { if (w instanceof StaticFieldExpr) { final StaticFieldExpr e = (StaticFieldExpr) w; eq.value = e.field().equals(expr.field()); } } public void visitNode(final Node node) { throw new RuntimeException("No method for " + node); } }); return eq.value; } /** * Computes a hash code for a given <tt>Node</tt> based upon its type. The * hash code of nodes that are composed of other nodes are based upon their * composits. */ public static int hashCode(final Node node) { class Int { int value = 0; } ; final Int hash = new Int(); node.visit(new TreeVisitor() { public void visitExprStmt(final ExprStmt stmt) { hash.value = 1; } public void visitIfCmpStmt(final IfCmpStmt stmt) { hash.value = stmt.comparison() + stmt.trueTarget().hashCode() + stmt.falseTarget().hashCode(); } public void visitIfZeroStmt(final IfZeroStmt stmt) { hash.value = stmt.comparison() + stmt.trueTarget().hashCode() + stmt.falseTarget().hashCode(); } public void visitInitStmt(final InitStmt stmt) { hash.value = 2; } public void visitGotoStmt(final GotoStmt stmt) { hash.value = stmt.target().hashCode(); } public void visitLabelStmt(final LabelStmt stmt) { hash.value = stmt.label().hashCode(); } public void visitMonitorStmt(final MonitorStmt stmt) { hash.value = stmt.kind(); } public void visitPhiJoinStmt(final PhiJoinStmt stmt) { hash.value = 3; } public void visitPhiCatchStmt(final PhiCatchStmt stmt) { hash.value = 4; } public void visitCatchExpr(final CatchExpr expr) { // Catches are not equivalent. hash.value = expr.hashCode(); } public void visitStackManipStmt(final StackManipStmt stmt) { hash.value = stmt.kind(); } public void visitRetStmt(final RetStmt stmt) { hash.value = 5; } public void visitReturnExprStmt(final ReturnExprStmt stmt) { hash.value = 6; } public void visitReturnStmt(final ReturnStmt stmt) { hash.value = 7; } public void visitAddressStoreStmt(final AddressStoreStmt stmt) { hash.value = 8; } public void visitStoreExpr(final StoreExpr expr) { hash.value = 9; } public void visitJsrStmt(final JsrStmt stmt) { hash.value = 10; } public void visitSwitchStmt(final SwitchStmt stmt) { hash.value = 11; } public void visitThrowStmt(final ThrowStmt stmt) { hash.value = 12; } public void visitArithExpr(final ArithExpr expr) { hash.value = expr.operation(); } public void visitArrayLengthExpr(final ArrayLengthExpr expr) { hash.value = 13; } public void visitArrayRefExpr(final ArrayRefExpr expr) { hash.value = 14; } public void visitCallMethodExpr(final CallMethodExpr expr) { // Calls are never equal. hash.value = expr.hashCode(); } public void visitCallStaticExpr(final CallStaticExpr expr) { // Calls are never equal. hash.value = expr.hashCode(); } public void visitCastExpr(final CastExpr expr) { hash.value = expr.castType().hashCode(); } public void visitConstantExpr(final ConstantExpr expr) { if (expr.value() == null) { hash.value = 0; } else { hash.value = expr.value().hashCode(); } } public void visitFieldExpr(final FieldExpr expr) { hash.value = expr.field().hashCode(); } public void visitInstanceOfExpr(final InstanceOfExpr expr) { hash.value = expr.checkType().hashCode(); } public void visitLocalExpr(final LocalExpr expr) { if (expr.def() != null) { hash.value = expr.def().hashCode(); } else { hash.value = 0; } } public void visitNegExpr(final NegExpr expr) { hash.value = 16; } public void visitNewArrayExpr(final NewArrayExpr expr) { hash.value = expr.hashCode(); } public void visitNewExpr(final NewExpr expr) { hash.value = expr.hashCode(); } public void visitNewMultiArrayExpr(final NewMultiArrayExpr expr) { hash.value = expr.hashCode(); } public void visitZeroCheckExpr(final ZeroCheckExpr expr) { hash.value = 15; } public void visitRCExpr(final RCExpr expr) { hash.value = 17; } public void visitUCExpr(final UCExpr expr) { hash.value = 18 + expr.kind(); } public void visitReturnAddressExpr(final ReturnAddressExpr expr) { hash.value = 21; } public void visitSCStmt(final SCStmt stmt) { hash.value = 23; } public void visitSRStmt(final SRStmt stmt) { hash.value = 22; } public void visitShiftExpr(final ShiftExpr expr) { hash.value = expr.dir(); } public void visitStackExpr(final StackExpr expr) { if (expr.def() != null) { hash.value = expr.def().hashCode(); } else { hash.value = 0; } } public void visitStaticFieldExpr(final StaticFieldExpr expr) { hash.value = expr.field().hashCode(); } public void visitNode(final Node node) { throw new RuntimeException("No method for " + node); } }); return hash.value; } }