/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.jsdt.internal.compiler.ast;
import org.eclipse.wst.jsdt.core.ast.IASTNode;
import org.eclipse.wst.jsdt.core.ast.IIntLiteral;
import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
import org.eclipse.wst.jsdt.internal.compiler.impl.Constant;
import org.eclipse.wst.jsdt.internal.compiler.impl.DoubleConstant;
import org.eclipse.wst.jsdt.internal.compiler.impl.IntConstant;
import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope;
import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.wst.jsdt.internal.compiler.parser.ScannerHelper;
public class IntLiteral extends NumberLiteral implements IIntLiteral {
public int value;
static final Constant FORMAT_ERROR = DoubleConstant.fromValue(1.0/0.0); // NaN;
public IntLiteral(char[] token, int s, int e) {
super(token, s,e);
}
public IntLiteral(char[] token, int s,int e, int value) {
this(token, s,e);
this.value = value;
}
public IntLiteral(int intValue) {
//special optimized constructor : the cst is the argument
//value that should not be used
// tokens = null ;
// sourceStart = 0;
// sourceEnd = 0;
super(null,0,0);
constant = IntConstant.fromValue(intValue);
value = intValue;
}
public void computeConstant() {
//a special constant is use for the potential Integer.MAX_VALUE+1
//which is legal if used with a - as prefix....cool....
//notice that Integer.MIN_VALUE == -2147483648
int length = source.length;
long computedValue = 0L;
if (source[0] == '0')
{ if (length == 1) { constant = IntConstant.fromValue(0); return ;}
final int shift,radix;
int maxDigit=16;
int j ;
if ( (source[1] == 'x') || (source[1] == 'X') )
{ shift = 4 ; j = 2; radix = 16; maxDigit=18;}
else
{ shift = 3 ; j = 1; radix = 8;}
if (length>maxDigit)
return ;
while (source[j]=='0')
{ j++; //jump over redondant zero
if (j == length)
{ //watch for 000000000000000000
constant = IntConstant.fromValue(value = (int)computedValue);
return ;}}
while (j<length)
{ int digitValue ;
if ((digitValue = ScannerHelper.digit(source[j++],radix)) < 0 )
{ constant = FORMAT_ERROR; return ;}
computedValue = (computedValue<<shift) | digitValue ;
// if (computedValue > MAX) return /*constant stays null*/ ;
} }
else
{ //-----------regular case : radix = 10-----------
for (int i = 0 ; i < length;i++)
{ int digitValue ;
if ((digitValue = ScannerHelper.digit(source[i],10)) < 0 )
{ constant = FORMAT_ERROR; return ;}
computedValue = 10*computedValue + digitValue;
// if (computedValue > MAX) return /*constant stays null*/ ;
}}
constant = IntConstant.fromValue(value = (int)computedValue);
}
public TypeBinding literalType(BlockScope scope) {
if(scope == null)
return TypeBinding.INT;
return scope.getJavaLangNumber();
}
public final boolean mayRepresentMIN_VALUE(){
//a special autorized int literral is 2147483648
//which is ONE over the limit. This special case
//only is used in combinaison with - to denote
//the minimal value of int -2147483648
return ((source.length == 10) &&
(source[0] == '2') &&
(source[1] == '1') &&
(source[2] == '4') &&
(source[3] == '7') &&
(source[4] == '4') &&
(source[5] == '8') &&
(source[6] == '3') &&
(source[7] == '6') &&
(source[8] == '4') &&
(source[9] == '8') &&
(((this.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0));
}
public TypeBinding resolveType(BlockScope scope) {
// the format may be incorrect while the scanner could detect
// such an error only on painfull tests...easier and faster here
TypeBinding tb = super.resolveType(scope);
if (constant == FORMAT_ERROR) {
constant = Constant.NotAConstant;
scope.problemReporter().constantOutOfFormat(this);
this.resolvedType = null;
return null;
}
return tb;
}
public StringBuffer printExpression(int indent, StringBuffer output){
if (source == null) {
/* special optimized IntLiteral that are created by the compiler */
return output.append(String.valueOf(value));
}
return super.printExpression(indent, output);
}
public void traverse(ASTVisitor visitor, BlockScope scope) {
visitor.visit(this, scope);
visitor.endVisit(this, scope);
}
public int getASTType() {
return IASTNode.INT_LITERAL;
}
public static IntLiteral getOne()
{
return new IntLiteral(new char[]{'1'},0,0,1);//used for ++ and --
}
}