001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package EDU.purdue.cs.bloat.tree;
022:
023: import EDU.purdue.cs.bloat.editor.*;
024: import EDU.purdue.cs.bloat.util.*;
025:
026: /**
027: * Expr is the superclass for a number of other classes representing expressions
028: * in byte code. Expressions are typed and may be nested.
029: *
030: * @see DefExpr
031: */
032: public abstract class Expr extends Node implements Cloneable {
033: protected Type type; // The type (descriptor) of this expression
034:
035: private DefExpr def; // The expression in which this expression
036:
037: // is defined (if applicable)
038: private Object comparator;
039:
040: /**
041: * Constructor. Initializes an expression with a given type.
042: *
043: * @param type
044: * The initial Type (descriptor) of this expression.
045: */
046: public Expr(final Type type) {
047: this .def = null;
048: this .comparator = new ExprComparator();
049: this .type = type;
050: }
051:
052: /**
053: * Sets the type of this expression. Returns whether or not the type changed
054: * as a result of calling this method.
055: */
056: public boolean setType(final Type type) {
057:
058: if (!this .type.equals(type)) {
059: // if (Tree.DEBUG) {
060: // System.out.println(" setting typeof(" + this + ") = " + type);
061: // }
062: this .type = type;
063:
064: return true;
065: }
066:
067: return false;
068: }
069:
070: /**
071: * Returns whether or not this expression is a defining occurrence. By
072: * default, false is returned.
073: */
074: public boolean isDef() {
075: return false;
076: }
077:
078: /**
079: * Returns the statement to which this expression belongs. It essentially
080: * searches up the expression tree for this expression's first ancestor
081: * which is a Stmt.
082: */
083: public Stmt stmt() {
084: Node p = parent;
085:
086: while (!(p instanceof Stmt)) {
087: Assert.isTrue(!(p instanceof Tree), "Invalid ancestor of "
088: + this );
089: Assert.isTrue(p != null, "Null ancestor of " + this );
090: p = p.parent;
091: }
092:
093: return (Stmt) p;
094: }
095:
096: /**
097: * Returns the Type of this expression.
098: */
099: public Type type() {
100: return type;
101: }
102:
103: /**
104: * Cleans up this expression only, not its children.
105: */
106: public void cleanupOnly() {
107: setDef(null);
108: }
109:
110: /**
111: * Sets the expression that defines this expression.
112: *
113: * @param def
114: * Defining expression.
115: */
116: public void setDef(final DefExpr def) {
117: // if (Tree.DEBUG) {
118: // System.out.println(" setting def of " + this +
119: // " (" + System.identityHashCode(this) + ") to " + def);
120: // }
121:
122: if (this .def == def) {
123: return;
124: }
125:
126: // If this Expr already had a defining statement, remove this from the
127: // DefExpr use list.
128: if (this .def != null) {
129: this .def.removeUse(this );
130: }
131:
132: if (this .isDef()) {
133: Assert.isTrue((def == this ) || (def == null));
134: this .def = null;
135: return;
136: }
137:
138: this .def = def;
139:
140: if (this .def != null) {
141: this .def.addUse(this ); // This Expr is a use of def
142: }
143: }
144:
145: /**
146: * Returns the expression in which this Expr is defined.
147: */
148: public DefExpr def() {
149: return def;
150: }
151:
152: /**
153: * Returns the hash code for this expresion.
154: */
155: public abstract int exprHashCode();
156:
157: /**
158: * Compares this expression to another.
159: *
160: * @param other
161: * Expr to which to compare this.
162: */
163: public abstract boolean equalsExpr(Expr other);
164:
165: public abstract Object clone();
166:
167: /**
168: * Copies the contents of another expression in this one.
169: *
170: * @param expr
171: * The expression from which to copy.
172: */
173: protected Expr copyInto(Expr expr) {
174: expr = (Expr) super .copyInto(expr);
175:
176: final DefExpr def = def();
177:
178: if (isDef()) {
179: expr.setDef(null);
180: } else {
181: expr.setDef(def);
182: }
183:
184: return expr;
185: }
186:
187: /**
188: * Returns an Object that can be used to compare other Expr to this.
189: */
190: public Object comparator() {
191: return comparator;
192: }
193:
194: /**
195: * ExprComparator is used to provide a different notion of equality among
196: * expressions than the default ==. In most cases, we want ==, but
197: * occasionally we want the equalsExpr() functionality when inserting in
198: * Hashtables, etc.
199: */
200: private class ExprComparator {
201: Expr expr = Expr.this ;
202:
203: public boolean equals(final Object obj) {
204: if (obj instanceof ExprComparator) {
205: final Expr other = ((ExprComparator) obj).expr;
206: return expr.equalsExpr(other)
207: && expr.type.simple().equals(
208: other.type.simple());
209: }
210:
211: return false;
212: }
213:
214: public int hashCode() {
215: return Expr.this.exprHashCode();
216: }
217: }
218: }
|