1) Fixed html syntax highlighting.
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / ast / LongLiteral.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
12
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
15 import net.sourceforge.phpdt.internal.compiler.impl.DoubleConstant;
16 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
17 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
18
19 public class LongLiteral extends NumberLiteral {
20         long value;
21
22         static final Constant FORMAT_ERROR = new DoubleConstant(1.0 / 0.0); // NaN;
23
24         public LongLiteral(char[] token, int s, int e) {
25                 super(token, s, e);
26         }
27
28         public LongLiteral(char[] token, int s, int e, long value) {
29                 this(token, s, e);
30                 this.value = value;
31         }
32
33         public void computeConstant() {
34                 // the overflow (when radix=10) is tested using the fact that
35                 // the value should always grow during its computation
36
37                 int length = source.length - 1; // minus one because the last char is
38                                                                                 // 'l' or 'L'
39
40                 long computedValue;
41                 if (source[0] == '0') {
42                         if (length == 1) {
43                                 constant = Constant.fromValue(0L);
44                                 return;
45                         }
46                         final int shift, radix;
47                         int j;
48                         if ((source[1] == 'x') | (source[1] == 'X')) {
49                                 shift = 4;
50                                 j = 2;
51                                 radix = 16;
52                         } else {
53                                 shift = 3;
54                                 j = 1;
55                                 radix = 8;
56                         }
57                         int nbDigit = 0;
58                         while (source[j] == '0') {
59                                 j++; // jump over redondant zero
60                                 if (j == length) { // watch for 0000000000000L
61                                         constant = Constant.fromValue(value = 0L);
62                                         return;
63                                 }
64                         }
65
66                         int digitValue;
67                         if ((digitValue = Character.digit(source[j++], radix)) < 0) {
68                                 constant = FORMAT_ERROR;
69                                 return;
70                         }
71                         if (digitValue >= 8)
72                                 nbDigit = 4;
73                         else if (digitValue >= 4)
74                                 nbDigit = 3;
75                         else if (digitValue >= 2)
76                                 nbDigit = 2;
77                         else
78                                 nbDigit = 1; // digitValue is not 0
79                         computedValue = digitValue;
80                         while (j < length) {
81                                 if ((digitValue = Character.digit(source[j++], radix)) < 0) {
82                                         constant = FORMAT_ERROR;
83                                         return;
84                                 }
85                                 if ((nbDigit += shift) > 64)
86                                         return /* constant stays null */;
87                                 computedValue = (computedValue << shift) | digitValue;
88                         }
89                 }
90
91                 else { // -----------case radix=10-----------------
92                         long previous = computedValue = 0;
93                         for (int i = 0; i < length; i++) {
94                                 int digitValue;
95                                 if ((digitValue = Character.digit(source[i], 10)) < 0)
96                                         return /* constant stays null */;
97                                 previous = computedValue;
98                                 computedValue = 10 * computedValue + digitValue;
99                                 if (previous > computedValue)
100                                         return /* constant stays null */;
101                         }
102                 }
103
104                 constant = Constant.fromValue(value = computedValue);
105         }
106
107         /**
108          * Code generation for long literal
109          * 
110          * @param currentScope
111          *            net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
112          * @param codeStream
113          *            net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
114          * @param valueRequired
115          *            boolean
116          */
117         // public void generateCode(BlockScope currentScope, CodeStream codeStream,
118         // boolean valueRequired) {
119         // int pc = codeStream.position;
120         // if (valueRequired)
121         // if ((implicitConversion >> 4) == T_long)
122         // codeStream.generateInlinedValue(value);
123         // else
124         // codeStream.generateConstant(constant, implicitConversion);
125         // codeStream.recordPositionsFrom(pc, this.sourceStart);
126         // }
127         public TypeBinding literalType(BlockScope scope) {
128                 return LongBinding;
129         }
130
131         public final boolean mayRepresentMIN_VALUE() {
132                 // a special autorized int literral is 9223372036854775808L
133                 // which is ONE over the limit. This special case
134                 // only is used in combinaison with - to denote
135                 // the minimal value of int -9223372036854775808L
136
137                 return ((source.length == 20) && (source[0] == '9')
138                                 && (source[1] == '2') && (source[2] == '2')
139                                 && (source[3] == '3') && (source[4] == '3')
140                                 && (source[5] == '7') && (source[6] == '2')
141                                 && (source[7] == '0') && (source[8] == '3')
142                                 && (source[9] == '6') && (source[10] == '8')
143                                 && (source[11] == '5') && (source[12] == '4')
144                                 && (source[13] == '7') && (source[14] == '7')
145                                 && (source[15] == '5') && (source[16] == '8')
146                                 && (source[17] == '0') && (source[18] == '8'));
147         }
148
149         public TypeBinding resolveType(BlockScope scope) {
150                 // the format may be incorrect while the scanner could detect
151                 // such error only on painfull tests...easier and faster here
152
153                 TypeBinding tb = super.resolveType(scope);
154                 if (constant == FORMAT_ERROR) {
155                         constant = NotAConstant;
156                         scope.problemReporter().constantOutOfFormat(this);
157                         this.resolvedType = null;
158                         return null;
159                 }
160                 return tb;
161         }
162
163         public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
164                 visitor.visit(this, scope);
165                 visitor.endVisit(this, scope);
166         }
167 }