/* 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.tree;
import EDU.purdue.cs.bloat.editor.*;
import EDU.purdue.cs.bloat.util.*;
/**
* Expr is the superclass for a number of other classes representing expressions
* in byte code. Expressions are typed and may be nested.
*
* @see DefExpr
*/
public abstract class Expr extends Node implements Cloneable {
protected Type type; // The type (descriptor) of this expression
private DefExpr def; // The expression in which this expression
// is defined (if applicable)
private Object comparator;
/**
* Constructor. Initializes an expression with a given type.
*
* @param type
* The initial Type (descriptor) of this expression.
*/
public Expr(final Type type) {
this.def = null;
this.comparator = new ExprComparator();
this.type = type;
}
/**
* Sets the type of this expression. Returns whether or not the type changed
* as a result of calling this method.
*/
public boolean setType(final Type type) {
if (!this.type.equals(type)) {
// if (Tree.DEBUG) {
// System.out.println(" setting typeof(" + this + ") = " + type);
// }
this.type = type;
return true;
}
return false;
}
/**
* Returns whether or not this expression is a defining occurrence. By
* default, false is returned.
*/
public boolean isDef() {
return false;
}
/**
* Returns the statement to which this expression belongs. It essentially
* searches up the expression tree for this expression's first ancestor
* which is a Stmt.
*/
public Stmt stmt() {
Node p = parent;
while (!(p instanceof Stmt)) {
Assert.isTrue(!(p instanceof Tree), "Invalid ancestor of " + this);
Assert.isTrue(p != null, "Null ancestor of " + this);
p = p.parent;
}
return (Stmt) p;
}
/**
* Returns the Type of this expression.
*/
public Type type() {
return type;
}
/**
* Cleans up this expression only, not its children.
*/
public void cleanupOnly() {
setDef(null);
}
/**
* Sets the expression that defines this expression.
*
* @param def
* Defining expression.
*/
public void setDef(final DefExpr def) {
// if (Tree.DEBUG) {
// System.out.println(" setting def of " + this +
// " (" + System.identityHashCode(this) + ") to " + def);
// }
if (this.def == def) {
return;
}
// If this Expr already had a defining statement, remove this from the
// DefExpr use list.
if (this.def != null) {
this.def.removeUse(this);
}
if (this.isDef()) {
Assert.isTrue((def == this) || (def == null));
this.def = null;
return;
}
this.def = def;
if (this.def != null) {
this.def.addUse(this); // This Expr is a use of def
}
}
/**
* Returns the expression in which this Expr is defined.
*/
public DefExpr def() {
return def;
}
/**
* Returns the hash code for this expresion.
*/
public abstract int exprHashCode();
/**
* Compares this expression to another.
*
* @param other
* Expr to which to compare this.
*/
public abstract boolean equalsExpr(Expr other);
public abstract Object clone();
/**
* Copies the contents of another expression in this one.
*
* @param expr
* The expression from which to copy.
*/
protected Expr copyInto(Expr expr) {
expr = (Expr) super.copyInto(expr);
final DefExpr def = def();
if (isDef()) {
expr.setDef(null);
} else {
expr.setDef(def);
}
return expr;
}
/**
* Returns an Object that can be used to compare other Expr to this.
*/
public Object comparator() {
return comparator;
}
/**
* ExprComparator is used to provide a different notion of equality among
* expressions than the default ==. In most cases, we want ==, but
* occasionally we want the equalsExpr() functionality when inserting in
* Hashtables, etc.
*/
private class ExprComparator {
Expr expr = Expr.this;
public boolean equals(final Object obj) {
if (obj instanceof ExprComparator) {
final Expr other = ((ExprComparator) obj).expr;
return expr.equalsExpr(other)
&& expr.type.simple().equals(other.type.simple());
}
return false;
}
public int hashCode() {
return Expr.this.exprHashCode();
}
}
}