001: /* ReferenceType Copyright (C) 1999-2002 Jochen Hoenicke.
002: *
003: * This program is free software; you can redistribute it and/or modify
004: * it under the terms of the GNU General Public License as published by
005: * the Free Software Foundation; either version 2, or (at your option)
006: * any later version.
007: *
008: * This program is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: * GNU General Public License for more details.
012: *
013: * You should have received a copy of the GNU General Public License
014: * along with this program; see the file COPYING. If not, write to
015: * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
016: *
017: * $Id: ReferenceType.java,v 1.5.4.1 2002/05/28 17:34:22 hoenicke Exp $
018: */
019:
020: package jode.type;
021:
022: import jode.GlobalOptions;
023: import jode.bytecode.ClassInfo;
024: import java.util.Vector;
025: import java.util.Stack;
026:
027: /**
028: * This is an abstrace super class of all reference types. Reference
029: * types are ClassInterfacesType, ArrayType and NullType. <p>
030: *
031: * To do intersection on range types, the reference types need three
032: * more operations: specialization, generalization and
033: * createRange. <p>
034: *
035: * specialization chooses all common sub type of two types. It is
036: * used to find the bottom of the intersected interval. <p>
037: *
038: * generalization chooses the common super type of two types. It
039: * is used to find the top of the intersected interval. <p>
040: *
041: * When the new interval is created with <code>createRangeType</code>
042: * the bottom and top are adjusted so that they only consists of
043: * possible types. It then decides, if it needs a range type, or if
044: * the reference types already represents all types.
045: *
046: * @author Jochen Hoenicke
047: */
048: public abstract class ReferenceType extends Type {
049: public ReferenceType(int typecode) {
050: super (typecode);
051: }
052:
053: /**
054: * Returns the specialized type set of this and type. The result
055: * should be a type set, so that every type, extends all types in
056: * type and this, iff it extends all types in the resulting type
057: * set.
058: * @param type the other type.
059: * @return the specialized type. */
060: public abstract Type getSpecializedType(Type type);
061:
062: /**
063: * Returns the generalized type set of this and type. The result
064: * should be a type set, so that every type, is extended/implemented
065: * by one type in this and one type in <code>type</code>, iff it is
066: * extended/implemented by one type in the resulting type set.
067: * @param type the other type.
068: * @return the generalized type
069: */
070: public abstract Type getGeneralizedType(Type type);
071:
072: /**
073: * Creates a range type set of this and bottom. The resulting type set
074: * contains all types, that extend all types in bottom and are extended
075: * by at least one type in this. <br>
076: * Note that a RangeType will do this, but we normalize the bottom and
077: * top set.
078: * @param bottom the bottom type.
079: * @return the range type set.
080: */
081: public abstract Type createRangeType(ReferenceType bottom);
082:
083: /**
084: * Tells if all otherIfaces, are implemented by at least one
085: * ifaces or by clazz.
086: *
087: * This is a useful function for generalizing/specializing interface
088: * types or arrays.
089: * @param clazz The clazz, can be null.
090: * @param ifaces The ifaces.
091: * @param otherifaces The other ifaces, that must be implemented.
092: * @return true, if all otherIfaces are implemented.
093: */
094: protected static boolean implements AllIfaces(ClassInfo clazz,
095: ClassInfo[] ifaces, ClassInfo[] otherIfaces) {
096: big: for (int i = 0; i < otherIfaces.length; i++) {
097: ClassInfo iface = otherIfaces[i];
098: if (clazz != null && iface.implementedBy(clazz))
099: continue big;
100: for (int j = 0; j < ifaces.length; j++) {
101: if (iface.implementedBy(ifaces[j]))
102: continue big;
103: }
104: return false;
105: }
106: return true;
107: }
108:
109: public Type getSuperType() {
110: return (this == tObject) ? tObject : tRange(tObject, this );
111: }
112:
113: public abstract Type getSubType();
114:
115: /**
116: * Intersect this type with another type and return the new type.
117: * @param type the other type.
118: * @return the intersection, or tError, if a type conflict happens.
119: */
120: public Type intersection(Type type) {
121: if (type == tError)
122: return type;
123: if (type == Type.tUnknown)
124: return this ;
125:
126: Type newBottom = getSpecializedType(type);
127: Type newTop = getGeneralizedType(type);
128: Type result;
129: if (newTop.equals(newBottom))
130: result = newTop;
131: else if (newTop instanceof ReferenceType
132: && newBottom instanceof ReferenceType)
133: result = ((ReferenceType) newTop)
134: .createRangeType((ReferenceType) newBottom);
135: else
136: result = tError;
137:
138: if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_TYPES) != 0) {
139: GlobalOptions.err.println("intersecting " + this + " and "
140: + type + " to " + result);
141: }
142: return result;
143: }
144: }
|