001: /* IntegerType 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: IntegerType.java,v 1.7.4.1 2002/05/28 17:34:22 hoenicke Exp $
018: */
019:
020: package jode.type;
021:
022: import jode.GlobalOptions;
023:
024: /**
025: * This is a type class for 16 bit integral types. There are seven
026: * different types, namely <code>int, char, short, byte, boolean,
027: * const short, const byte</code> abbreviated <code>I, C, S, B, Z, cS,
028: * cB</code>. <code>cB</code> and <code>cS</code> specify constant
029: * ints whose value is in byte resp. short range. They may be
030: * converted to B resp. S, but sometimes need an explicit cast.
031: *
032: * @author Jochen Hoenicke
033: */
034: public class IntegerType extends Type {
035:
036: /* Order does matter:
037: * First type that is possible (and hinted) will be taken.
038: */
039: public static final int IT_Z = 0x01;
040: public static final int IT_I = 0x02;
041: public static final int IT_C = 0x04;
042: public static final int IT_S = 0x08;
043: public static final int IT_B = 0x10;
044: public static final int IT_cS = 0x20;
045: public static final int IT_cB = 0x40;
046: private static final int NUM_TYPES = 7;
047:
048: private static final int[] subTypes = {
049: /*Z*/IT_Z,
050: /*I*/IT_I | IT_C | IT_S | IT_B/*|IT_cS|IT_cB*/, /*C*/IT_C,
051: /*S*/IT_S | IT_B/*|IT_cS|IT_cB*/, /*B*/IT_B/*|IT_cB*/,
052: /*cS*/IT_cS | IT_cB, /*cB*/IT_cB };
053: private static final int[] super Types = {
054: /*Z*/IT_Z,
055: /*I*/IT_I, /*C*/IT_I | IT_C,
056: /*S*/IT_I | IT_S, /*B*/IT_I | IT_S | IT_B,
057: /*cS*/IT_I | IT_C | IT_S | IT_cS, /*cB*/
058: IT_I | IT_C | IT_S | IT_B | IT_cS | IT_cB };
059: private static final Type[] simpleTypes = { new IntegerType(IT_Z),
060: new IntegerType(IT_I), new IntegerType(IT_C),
061: new IntegerType(IT_S), new IntegerType(IT_B),
062: new IntegerType(IT_cS), new IntegerType(IT_cB) };
063: private static final String[] typeNames = { "Z", "I", "C", "S",
064: "B", "s", "b" };
065:
066: int possTypes;
067: int hintTypes;
068:
069: /**
070: * Create a new type with the given type.
071: */
072: public IntegerType(int types) {
073: this (types, types);
074: }
075:
076: public IntegerType(int types, int hints) {
077: super (TC_INTEGER);
078: possTypes = types;
079: hintTypes = hints;
080: }
081:
082: public Type getHint() {
083: int hint = possTypes & hintTypes;
084: if (hint == 0)
085: hint = possTypes;
086: int i = 0;
087: while ((hint & 1) == 0) {
088: hint >>= 1;
089: i++;
090: }
091: return simpleTypes[i];
092: }
093:
094: public Type getCanonic() {
095: int types = possTypes;
096: int i = 0;
097: while ((types >>= 1) != 0) {
098: i++;
099: }
100: return simpleTypes[i];
101: }
102:
103: private static int getSubTypes(int types) {
104: int result = 0;
105: for (int i = 0; i < NUM_TYPES; i++) {
106: if (((1 << i) & types) != 0)
107: result |= subTypes[i];
108: }
109: return result;
110: }
111:
112: private static int getSuperTypes(int types) {
113: int result = 0;
114: for (int i = 0; i < NUM_TYPES; i++) {
115: if (((1 << i) & types) != 0)
116: result |= super Types[i];
117: }
118: return result;
119: }
120:
121: public Type getSubType() {
122: return new IntegerType(getSubTypes(possTypes),
123: getSubTypes(hintTypes));
124: }
125:
126: public Type getSuperType() {
127: /* Don't upgrade hints */
128: return new IntegerType(getSuperTypes(possTypes), hintTypes);
129: }
130:
131: /**
132: * Checks if this type represents a valid type instead of a list
133: * of minimum types.
134: */
135: public boolean isValidType() {
136: return true;
137: }
138:
139: /**
140: * Check if this and <unknown -- type&rt; are not disjunct.
141: * @param type a simple type; this mustn't be a range type.
142: * @return true if this is the case.
143: */
144: public boolean isOfType(Type type) {
145: return (type.typecode == TC_INTEGER && (((IntegerType) type).possTypes & possTypes) != 0);
146: }
147:
148: public String getDefaultName() {
149: switch (((IntegerType) getHint()).possTypes) {
150: case IT_Z:
151: return "bool";
152: case IT_C:
153: return "c";
154: case IT_B:
155: case IT_S:
156: case IT_I:
157: return "i";
158: default:
159: throw new jode.AssertError(
160: "Local can't be of constant type!");
161: }
162: }
163:
164: public Object getDefaultValue() {
165: return new Integer(0);
166: }
167:
168: public String getTypeSignature() {
169: switch (((IntegerType) getHint()).possTypes) {
170: case IT_Z:
171: return "Z";
172: case IT_C:
173: return "C";
174: case IT_B:
175: return "B";
176: case IT_S:
177: return "S";
178: case IT_I:
179: default:
180: return "I";
181: }
182: }
183:
184: public Class getTypeClass() {
185: switch (((IntegerType) getHint()).possTypes) {
186: case IT_Z:
187: return Boolean.TYPE;
188: case IT_C:
189: return Character.TYPE;
190: case IT_B:
191: return Byte.TYPE;
192: case IT_S:
193: return Short.TYPE;
194: case IT_I:
195: default:
196: return Integer.TYPE;
197: }
198: }
199:
200: public String toString() {
201: if (possTypes == hintTypes) {
202: switch (possTypes) {
203: case IT_Z:
204: return "boolean";
205: case IT_C:
206: return "char";
207: case IT_B:
208: return "byte";
209: case IT_S:
210: return "short";
211: case IT_I:
212: return "int";
213: }
214: }
215: StringBuffer sb = new StringBuffer("{");
216: for (int i = 0; i < NUM_TYPES; i++) {
217: if (((1 << i) & possTypes) != 0)
218: sb.append(typeNames[i]);
219: }
220: if (possTypes != hintTypes) {
221: sb.append(":");
222: for (int i = 0; i < NUM_TYPES; i++) {
223: if (((1 << i) & hintTypes) != 0)
224: sb.append(typeNames[i]);
225: }
226: }
227: sb.append("}");
228: return sb.toString();
229: }
230:
231: /**
232: * Intersect this type with another type and return the new type.
233: * @param type the other type.
234: * @return the intersection, or tError, if a type conflict happens.
235: */
236: public Type intersection(Type type) {
237: if (type == tError)
238: return type;
239: if (type == tUnknown)
240: return this ;
241:
242: int mergeTypes;
243: int mergeHints = 0;
244: if (type.typecode != TC_INTEGER)
245: mergeTypes = 0;
246: else {
247: IntegerType other = (IntegerType) type;
248: mergeTypes = possTypes & other.possTypes;
249: mergeHints = hintTypes & other.hintTypes;
250:
251: if (mergeTypes == possTypes && mergeHints == hintTypes)
252: return this ;
253: if (mergeTypes == other.possTypes
254: && mergeHints == other.hintTypes)
255: return other;
256: }
257: Type result = mergeTypes == 0 ? tError : new IntegerType(
258: mergeTypes, mergeHints);
259: if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_TYPES) != 0) {
260: GlobalOptions.err.println("intersecting " + this + " and "
261: + type + " to " + result);
262: }
263: return result;
264: }
265:
266: public boolean equals(Object o) {
267: if (o == this )
268: return true;
269: if (o instanceof IntegerType) {
270: IntegerType other = (IntegerType) o;
271: return other.possTypes == possTypes
272: && other.hintTypes == hintTypes;
273: }
274: return false;
275: }
276: }
|