fix #761 also see #762.
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / ast / IntLiteral.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 IntLiteral extends NumberLiteral {
20         public int value;
21
22         public static final IntLiteral One = new IntLiteral(new char[] { '1' }, 0,
23                         0, 1);// used for ++ and --
24
25         static final Constant FORMAT_ERROR = new DoubleConstant(1.0 / 0.0); // NaN;
26
27         public IntLiteral(char[] token, int s, int e) {
28                 super(token, s, e);
29         }
30
31         public IntLiteral(char[] token, int s, int e, int value) {
32                 this(token, s, e);
33                 this.value = value;
34         }
35
36         public IntLiteral(int intValue) {
37                 // special optimized constructor : the cst is the argument
38
39                 // value that should not be used
40                 // tokens = null ;
41                 // sourceStart = 0;
42                 // sourceEnd = 0;
43                 super(null, 0, 0);
44                 constant = Constant.fromValue(intValue);
45                 value = intValue;
46
47         }
48
49         public void computeConstant() {
50                 // a special constant is use for the potential Integer.MAX_VALUE+1
51                 // which is legal if used with a - as prefix....cool....
52                 // notice that Integer.MIN_VALUE == -2147483648
53
54                 long MAX = Integer.MAX_VALUE;
55                 if (this == One) {
56                         constant = Constant.One;
57                         return;
58                 }
59
60                 int length = source.length;
61                 long computedValue = 0L;
62                 if (source[0] == '0') {
63                         MAX = 0xFFFFFFFFL; // a long in order to be positive !
64                         if (length == 1) {
65                                 constant = Constant.fromValue(0);
66                                 return;
67                         }
68                         final int shift, radix;
69                         int j;
70                         if ((source[1] == 'x') | (source[1] == 'X')) {
71                                 shift = 4;
72                                 j = 2;
73                                 radix = 16;
74                         } else {
75                                 shift = 3;
76                                 j = 1;
77                                 radix = 8;
78                         }
79                         while (source[j] == '0') {
80                                 j++; // jump over redondant zero
81                                 if (j == length) { // watch for 000000000000000000 :-(
82                                         constant = Constant.fromValue(value = (int) computedValue);
83                                         return;
84                                 }
85                         }
86
87                         while (j < length) {
88                                 int digitValue;
89                                 if ((digitValue = Character.digit(source[j++], radix)) < 0) {
90                                         constant = FORMAT_ERROR;
91                                         return;
92                                 }
93                                 computedValue = (computedValue << shift) | digitValue;
94                                 if (computedValue > MAX)
95                                         return /* constant stays null */;
96                         }
97                 } else { // -----------regular case : radix = 10-----------
98                         for (int i = 0; i < length; i++) {
99                                 int digitValue;
100                                 if ((digitValue = Character.digit(source[i], 10)) < 0) {
101                                         constant = FORMAT_ERROR;
102                                         return;
103                                 }
104                                 computedValue = 10 * computedValue + digitValue;
105                                 if (computedValue > MAX)
106                                         return /* constant stays null */;
107                         }
108                 }
109
110                 constant = Constant.fromValue(value = (int) computedValue);
111
112         }
113
114         /**
115          * Code generation for int literal
116          * 
117          * @param currentScope
118          *            net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
119          * @param codeStream
120          *            net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
121          * @param valueRequired
122          *            boolean
123          */
124         // public void generateCode(BlockScope currentScope, CodeStream codeStream,
125         // boolean valueRequired) {
126         // int pc = codeStream.position;
127         // if (valueRequired)
128         // if ((implicitConversion >> 4) == T_int)
129         // codeStream.generateInlinedValue(value);
130         // else
131         // codeStream.generateConstant(constant, implicitConversion);
132         // codeStream.recordPositionsFrom(pc, this.sourceStart);
133         // }
134         public TypeBinding literalType(BlockScope scope) {
135                 return IntBinding;
136         }
137
138         public final boolean mayRepresentMIN_VALUE() {
139                 // a special autorized int literral is 2147483648
140                 // which is ONE over the limit. This special case
141                 // only is used in combinaison with - to denote
142                 // the minimal value of int -2147483648
143
144                 return ((source.length == 10) && (source[0] == '2')
145                                 && (source[1] == '1') && (source[2] == '4')
146                                 && (source[3] == '7') && (source[4] == '4')
147                                 && (source[5] == '8') && (source[6] == '3')
148                                 && (source[7] == '6') && (source[8] == '4') && (source[9] == '8'));
149         }
150
151         public TypeBinding resolveType(BlockScope scope) {
152                 // the format may be incorrect while the scanner could detect
153                 // such an error only on painfull tests...easier and faster here
154
155                 TypeBinding tb = super.resolveType(scope);
156                 if (constant == FORMAT_ERROR) {
157                         constant = NotAConstant;
158                         scope.problemReporter().constantOutOfFormat(this);
159                         this.resolvedType = null;
160                         return null;
161                 }
162                 return tb;
163         }
164
165         public String toStringExpression() {
166
167                 if (source == null)
168                         /* special optimized IntLiteral that are created by the compiler */
169                         return String.valueOf(value);
170
171                 return super.toStringExpression();
172         }
173
174         public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
175                 visitor.visit(this, scope);
176                 visitor.endVisit(this, scope);
177         }
178 }