summaryrefslogtreecommitdiff
path: root/sources/scalac/atree/AConstant.java
blob: 12c58d5889bf46254f34792acff2953311adf757 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002, LAMP/EPFL              **
** /_____/\____/\___/\____/____/                                        **
\*                                                                      */

// $Id$

package scalac.atree;

import scalac.util.Debug;
import scalac.symtab.Symbol;

/** This class represents a constant. */
public class AConstant {

    public static final AConstant[] EMPTY_ARRAY = new AConstant[0];

    //########################################################################
    // Public Cases

    public case UNIT;
    public case BOOLEAN(boolean value);
    public case BYTE(byte value);
    public case SHORT(short value);
    public case CHAR(char value);
    public case INT(int value);
    public case LONG(long value);
    public case FLOAT(float value);
    public case DOUBLE(double value);
    public case STRING(String value);
    public case SYMBOL_NAME(Symbol value);
    public case NULL;
    public case ZERO;

    //########################################################################
    // Public Methods

    /** Returns the type kind of this constant. */
    public ATypeKind kind() {
        switch (this) {
        case UNIT:
            return ATypeKind.UNIT;
        case BOOLEAN(_):
            return ATypeKind.BOOL;
        case BYTE(_):
            return ATypeKind.I1;
        case SHORT(_):
            return ATypeKind.I2;
        case CHAR(_):
            return ATypeKind.U2;
        case INT(_):
            return ATypeKind.I4;
        case LONG(_):
            return ATypeKind.I8;
        case FLOAT(_):
            return ATypeKind.R4;
        case DOUBLE(_):
            return ATypeKind.R8;
        case STRING(_):
        case SYMBOL_NAME(_):
            return ATypeKind.STR;
        case NULL:
            return ATypeKind.NULL;
        case ZERO:
            return ATypeKind.ZERO;
        default:
            throw Debug.abort("unknown case", this);
        }
    }


    /** Converts this constant to a boolean value. */
    public boolean booleanValue() {
        switch (this) {
        case BOOLEAN(boolean value):
            return value;
        default:
            throw Debug.abort("not convertible to boolean", this);
        }
    }

    /** Converts this constant to a byte value. */
    public byte byteValue() {
        switch (this) {
        case BYTE(byte value):
            return (byte)value;
        case SHORT(short value):
            return (byte)value;
        case CHAR(char value):
            return (byte)value;
        case INT(int value):
            return (byte)value;
        case LONG(long value):
            return (byte)value;
        case FLOAT(float value):
            return (byte)value;
        case DOUBLE(double value):
            return (byte)value;
        default:
            throw Debug.abort("not convertible to byte", this);
        }
    }

    /** Converts this constant to a short value. */
    public short shortValue() {
        switch (this) {
        case BYTE(byte value):
            return (short)value;
        case SHORT(short value):
            return (short)value;
        case CHAR(char value):
            return (short)value;
        case INT(int value):
            return (short)value;
        case LONG(long value):
            return (short)value;
        case FLOAT(float value):
            return (short)value;
        case DOUBLE(double value):
            return (short)value;
        default:
            throw Debug.abort("not convertible to short", this);
        }
    }

    /** Converts this constant to a char value. */
    public char charValue() {
        switch (this) {
        case BYTE(byte value):
            return (char)value;
        case SHORT(short value):
            return (char)value;
        case CHAR(char value):
            return (char)value;
        case INT(int value):
            return (char)value;
        case LONG(long value):
            return (char)value;
        case FLOAT(float value):
            return (char)value;
        case DOUBLE(double value):
            return (char)value;
        default:
            throw Debug.abort("not convertible to char", this);
        }
    }

    /** Converts this constant to a int value. */
    public int intValue() {
        switch (this) {
        case BYTE(byte value):
            return (int)value;
        case SHORT(short value):
            return (int)value;
        case CHAR(char value):
            return (int)value;
        case INT(int value):
            return (int)value;
        case LONG(long value):
            return (int)value;
        case FLOAT(float value):
            return (int)value;
        case DOUBLE(double value):
            return (int)value;
        default:
            throw Debug.abort("not convertible to int", this);
        }
    }

    /** Converts this constant to a long value. */
    public long longValue() {
        switch (this) {
        case BYTE(byte value):
            return (long)value;
        case SHORT(short value):
            return (long)value;
        case CHAR(char value):
            return (long)value;
        case INT(int value):
            return (long)value;
        case LONG(long value):
            return (long)value;
        case FLOAT(float value):
            return (long)value;
        case DOUBLE(double value):
            return (long)value;
        default:
            throw Debug.abort("not convertible to long", this);
        }
    }

    /** Converts this constant to a float value. */
    public float floatValue() {
        switch (this) {
        case BYTE(byte value):
            return (float)value;
        case SHORT(short value):
            return (float)value;
        case CHAR(char value):
            return (float)value;
        case INT(int value):
            return (float)value;
        case LONG(long value):
            return (float)value;
        case FLOAT(float value):
            return (float)value;
        case DOUBLE(double value):
            return (float)value;
        default:
            throw Debug.abort("not convertible to float", this);
        }
    }

    /** Converts this constant to a double value. */
    public double doubleValue() {
        switch (this) {
        case BYTE(byte value):
            return (double)value;
        case SHORT(short value):
            return (double)value;
        case CHAR(char value):
            return (double)value;
        case INT(int value):
            return (double)value;
        case LONG(long value):
            return (double)value;
        case FLOAT(float value):
            return (double)value;
        case DOUBLE(double value):
            return (double)value;
        default:
            throw Debug.abort("not convertible to double", this);
        }
    }

    /** Converts this constant to a String value. */
    public String stringValue() {
        switch (this) {
        case UNIT:
            return "()";
        case BOOLEAN(boolean value):
            return String.valueOf(value);
        case BYTE(byte value):
            return String.valueOf(value);
        case SHORT(short value):
            return String.valueOf(value);
        case CHAR(char value):
            return String.valueOf(value);
        case INT(int value):
            return String.valueOf(value);
        case LONG(long value):
            return String.valueOf(value);
        case FLOAT(float value):
            return String.valueOf(value);
        case DOUBLE(double value):
            return String.valueOf(value);
        case STRING(String value):
            return value;
        case SYMBOL_NAME(Symbol value):
            return value.name.toString();
        case NULL:
            return String.valueOf(null);
        default:
            throw Debug.abort("not convertible to String", this);
        }
    }

    /** Tests whether this constant equals given Object. */
    public boolean equals(Object that) {
        if (this == that) return true;
        return (that instanceof AConstant) && this.equals((AConstant)that);
    }

    /** Tests whether this constant equals given one. */
    public boolean equals(AConstant that) {
        if (this == that) return true;
        if (null == that) return false;
        switch (this) {
        case UNIT:
            return false;
        case BOOLEAN(boolean ivalue):
            switch (that) {
            case BOOLEAN(boolean avalue):
                return ivalue == avalue;
            default:
                return false;
            }
        case BYTE(byte ivalue):
            switch (that) {
            case BYTE(byte avalue):
                return ivalue == avalue;
            default:
                return false;
            }
        case SHORT(short ivalue):
            switch (that) {
            case SHORT(short avalue):
                return ivalue == avalue;
            default:
                return false;
            }
        case CHAR(char ivalue):
            switch (that) {
            case CHAR(char avalue):
                return ivalue == avalue;
            default:
                return false;
            }
        case INT(int ivalue):
            switch (that) {
            case INT(int avalue):
                return ivalue == avalue;
            default:
                return false;
            }
        case LONG(long ivalue):
            switch (that) {
            case LONG(long avalue):
                return ivalue == avalue;
            default:
                return false;
            }
        case FLOAT(float ivalue):
            switch (that) {
            case FLOAT(float avalue):
                return ivalue == avalue;
            default:
                return false;
            }
        case DOUBLE(double ivalue):
            switch (that) {
            case DOUBLE(double avalue):
                return ivalue == avalue;
            default:
                return false;
            }
        case STRING(String ivalue):
            switch (that) {
            case STRING(String avalue):
                return ivalue.equals(avalue);
            default:
                return false;
            }
        case SYMBOL_NAME(Symbol ivalue):
            switch (that) {
            case SYMBOL_NAME(Symbol avalue):
                return ivalue == avalue;
            default:
                return false;
            }
        case NULL:
            return false;
        case ZERO:
            return false;
        default:
            throw Debug.abort("unknown case", this);
        }
    }

    /** Returns the hash code of this constant. */
    public int hashCode() {
        switch (this) {
        case UNIT:
            return 4041;
        case BOOLEAN(boolean value):
            return value ? 1231 : 1237;
        case BYTE(byte value):
            return value;
        case SHORT(short value):
            return value;
        case CHAR(char value):
            return value;
        case INT(int value):
            return value;
        case LONG(long value):
            long bits = value;
            return (int)(bits ^ (bits >>> 32));
        case FLOAT(float value):
            int bits = java.lang.Float.floatToIntBits(value);
            return bits;
        case DOUBLE(double value):
            long bits = java.lang.Double.doubleToLongBits(value);
            return (int)(bits ^ (bits >>> 32));
        case STRING(String value):
            return value.hashCode();
        case SYMBOL_NAME(Symbol value):
            return value.hashCode();
        case NULL:
            return 0;
        case ZERO:
            return 0;
        default:
            throw Debug.abort("unknown case", this);
        }
    }

    /** Returns a string representation of this constant. */
    public String toString() {
        return new ATreePrinter().printConstant(this).toString();
    }

    //########################################################################
}