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