001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2006-2007 Robert Grimm
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * version 2 as published by the Free Software Foundation.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
017: * USA.
018: */
019: package xtc.type;
020:
021: import java.io.IOException;
022:
023: import xtc.Limits;
024:
025: /**
026: * The superclass of all number types.
027: *
028: * @author Robert Grimm
029: * @version $Revision: 1.27 $
030: */
031: public abstract class NumberT extends Type {
032:
033: /** The number kind. */
034: public static enum Kind {
035: /** A signed byte. */
036: BYTE,
037: /** A char. */
038: CHAR,
039: /** A signed char. */
040: S_CHAR,
041: /** An unsigned char. */
042: U_CHAR,
043: /** A signed short. */
044: SHORT,
045: /** An unsigned short. */
046: U_SHORT,
047: /**
048: * An int. Per C99 6.7.2, it depends on the implementation
049: * whether <code>int</code> appearing by itself in a bit-field is
050: * signed or unsigned. Hence we distinguish between ints and
051: * signed ints. (Whatever.)
052: */
053: INT,
054: /** A signed int. */
055: S_INT,
056: /** An unsigned int. */
057: U_INT,
058: /** A signed long. */
059: LONG,
060: /** An unsigned long. */
061: U_LONG,
062: /** A signed long long. */
063: LONG_LONG,
064: /** An unsigned long long. */
065: U_LONG_LONG,
066: /** A float. */
067: FLOAT,
068: /** A double. */
069: DOUBLE,
070: /** A long double. */
071: LONG_DOUBLE,
072: /** A float complex. */
073: FLOAT_COMPLEX,
074: /** A double complex. */
075: DOUBLE_COMPLEX,
076: /** A long double complex. */
077: LONG_DOUBLE_COMPLEX
078: }
079:
080: // =========================================================================
081:
082: /** The canonical signed byte type. */
083: public static final IntegerT BYTE = new IntegerT(Kind.BYTE);
084:
085: /** The canonical char type. */
086: public static final IntegerT CHAR = new IntegerT(Kind.CHAR);
087:
088: /** The canonical signed char type. */
089: public static final IntegerT S_CHAR = new IntegerT(Kind.S_CHAR);
090:
091: /** The canonical unsigned char type. */
092: public static final IntegerT U_CHAR = new IntegerT(Kind.U_CHAR);
093:
094: /** The canonical short type. */
095: public static final IntegerT SHORT = new IntegerT(Kind.SHORT);
096:
097: /** The canonical unsigned short type. */
098: public static final IntegerT U_SHORT = new IntegerT(Kind.U_SHORT);
099:
100: /** The canonical int type. */
101: public static final IntegerT INT = new IntegerT(Kind.INT);
102:
103: /** The canonical signed int type. */
104: public static final IntegerT S_INT = new IntegerT(Kind.S_INT);
105:
106: /** The cannical unsigned int type. */
107: public static final IntegerT U_INT = new IntegerT(Kind.U_INT);
108:
109: /** The canonical signed long type. */
110: public static final IntegerT LONG = new IntegerT(Kind.LONG);
111:
112: /** The canonical unsigned long type. */
113: public static final IntegerT U_LONG = new IntegerT(Kind.U_LONG);
114:
115: /** The canonical signed long long type. */
116: public static final IntegerT LONG_LONG = new IntegerT(
117: Kind.LONG_LONG);
118:
119: /** The canonical unsigned long long type. */
120: public static final IntegerT U_LONG_LONG = new IntegerT(
121: Kind.U_LONG_LONG);
122:
123: /** The canonical float type. */
124: public static final FloatT FLOAT = new FloatT(Kind.FLOAT);
125:
126: /** The canonical double type. */
127: public static final FloatT DOUBLE = new FloatT(Kind.DOUBLE);
128:
129: /** The canonical long double type. */
130: public static final FloatT LONG_DOUBLE = new FloatT(
131: Kind.LONG_DOUBLE);
132:
133: /** The canonical float complex type. */
134: public static final FloatT FLOAT_COMPLEX = new FloatT(
135: Kind.FLOAT_COMPLEX);
136:
137: /** The canonical double complex type. */
138: public static final FloatT DOUBLE_COMPLEX = new FloatT(
139: Kind.DOUBLE_COMPLEX);
140:
141: /** The canonical long double complex type. */
142: public static final FloatT LONG_DOUBLE_COMPLEX = new FloatT(
143: Kind.LONG_DOUBLE_COMPLEX);
144:
145: static {
146: BYTE.seal();
147: CHAR.seal();
148: S_CHAR.seal();
149: U_CHAR.seal();
150: SHORT.seal();
151: U_SHORT.seal();
152: INT.seal();
153: S_INT.seal();
154: U_INT.seal();
155: LONG.seal();
156: U_LONG.seal();
157: LONG_LONG.seal();
158: U_LONG_LONG.seal();
159: FLOAT.seal();
160: DOUBLE.seal();
161: LONG_DOUBLE.seal();
162: FLOAT_COMPLEX.seal();
163: DOUBLE_COMPLEX.seal();
164: LONG_DOUBLE_COMPLEX.seal();
165: }
166:
167: // =========================================================================
168:
169: /** The kind. */
170: protected final Kind kind;
171:
172: /**
173: * Create a new number type. The specified kind must be a valid
174: * integer or float kind.
175: *
176: * @param kind The kind.
177: */
178: public NumberT(Kind kind) {
179: this .kind = kind;
180: }
181:
182: /**
183: * Create a new number type. The specified kind must be a valid
184: * integer or float kind.
185: *
186: * @param template The type whose annotations to copy.
187: * @param kind The kind.
188: */
189: public NumberT(Type template, Kind kind) {
190: super (template);
191: this .kind = kind;
192: }
193:
194: public boolean isNumber() {
195: return true;
196: }
197:
198: public NumberT toNumber() {
199: return this ;
200: }
201:
202: /**
203: * Determine whether this number has the specified kind. Note that
204: * this method uses {@link #equal(Kind,Kind)} to perform the kind
205: * comparison.
206: *
207: * @param kind The kind.
208: * @return <code>true</code> if this number has the specified kind.
209: */
210: public boolean hasKind(Kind kind) {
211: return equal(this .kind, kind);
212: }
213:
214: /**
215: * Get the kind.
216: *
217: * @return The kind.
218: */
219: public Kind getKind() {
220: return kind;
221: }
222:
223: /**
224: * Determine whether this number is signed.
225: *
226: * @return <code>true</code> if this number is signed.
227: */
228: public boolean isSigned() {
229: switch (kind) {
230: case U_CHAR:
231: case U_SHORT:
232: case U_INT:
233: case U_LONG:
234: case U_LONG_LONG:
235: return false;
236: case CHAR:
237: return Limits.IS_CHAR_SIGNED;
238: default:
239: return true;
240: }
241: }
242:
243: public int hashCode() {
244: return (kind.ordinal() + 1) * 37;
245: }
246:
247: /**
248: * Determine whether this type equals the specified object. This
249: * number equals the specified object if the specified object also
250: * is a number and the two numbers' kinds are either the same or a
251: * combination of the {@link Kind#INT int} and {@link Kind#S_INT
252: * signed int} kinds.
253: *
254: * @param o The object.
255: * @return <code>true</code> if this type equals the object.
256: */
257: public boolean equals(Object o) {
258: if (!(o instanceof Type))
259: return false;
260: Type t = resolve(o);
261:
262: if (this == t)
263: return true;
264: if (!t.isNumber())
265: return false;
266: return equal(kind, ((NumberT) t).kind);
267: }
268:
269: public void write(Appendable out) throws IOException {
270: out.append(toString());
271: }
272:
273: public String toString() {
274: switch (kind) {
275: case BYTE:
276: return "byte";
277: case CHAR:
278: return "char";
279: case S_CHAR:
280: return "signed char";
281: case U_CHAR:
282: return "unsigned char";
283: case SHORT:
284: return "short";
285: case U_SHORT:
286: return "unsigned short";
287: case INT:
288: return "int";
289: case S_INT:
290: return "signed int";
291: case U_INT:
292: return "unsigned int";
293: case LONG:
294: return "long";
295: case U_LONG:
296: return "unsigned long";
297: case LONG_LONG:
298: return "long long";
299: case U_LONG_LONG:
300: return "unsigned long long";
301: case FLOAT:
302: return "float";
303: case DOUBLE:
304: return "double";
305: case LONG_DOUBLE:
306: return "long double";
307: case FLOAT_COMPLEX:
308: return "float _Complex";
309: case DOUBLE_COMPLEX:
310: return "double _Complex";
311: case LONG_DOUBLE_COMPLEX:
312: return "long double _Complex";
313: default:
314: throw new AssertionError("Invalid kind: " + kind);
315: }
316: }
317:
318: // =========================================================================
319:
320: /**
321: * Determine whether the specified kinds equal each other. This
322: * method treats implicit, int, and signed int types as equal.
323: *
324: * @param k1 The first kind.
325: * @param k2 The second kind.
326: * @return <code>true</code> if the kinds are equal.
327: */
328: public static boolean equal(Kind k1, Kind k2) {
329: return ((k1 == k2) || (((Kind.INT == k1) || (Kind.S_INT == k1)) && ((Kind.INT == k2) || (Kind.S_INT == k2))));
330: }
331:
332: /**
333: * Determine whether the specified kinds equal each other, modulo
334: * their signs. This method treats implicit, int, and signed int
335: * types as equal.
336: *
337: * @param k1 The first kind.
338: * @param k2 The second kind.
339: * @return <code>true</code> if the kinds are equal modulo their
340: * signs.
341: */
342: public static boolean equalIgnoringSign(Kind k1, Kind k2) {
343: switch (k1) {
344: case CHAR:
345: case S_CHAR:
346: case U_CHAR:
347: return (Kind.CHAR == k2) || (Kind.S_CHAR == k2)
348: || (Kind.U_CHAR == k2);
349: case SHORT:
350: case U_SHORT:
351: return (Kind.SHORT == k2) || (Kind.U_SHORT == k2);
352: case INT:
353: case S_INT:
354: case U_INT:
355: return (Kind.INT == k2) || (Kind.S_INT == k2)
356: || (Kind.U_INT == k2);
357: case LONG:
358: case U_LONG:
359: return (Kind.LONG == k2) || (Kind.U_LONG == k2);
360: case LONG_LONG:
361: case U_LONG_LONG:
362: return (Kind.LONG_LONG == k2) || (Kind.U_LONG_LONG == k2);
363: default:
364: return (k1 == k2);
365: }
366: }
367:
368: }
|