/******************************************************************************* | |
* Copyright (c) 2000, 2004 IBM Corporation and others. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Common Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/cpl-v10.html | |
* | |
* Contributors: | |
* IBM Corporation - initial API and implementation | |
*******************************************************************************/ | |
package org.eclipse.wst.jsdt.internal.compiler.ast; | |
import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor; | |
import org.eclipse.wst.jsdt.internal.compiler.impl.*; | |
import org.eclipse.wst.jsdt.internal.compiler.codegen.*; | |
import org.eclipse.wst.jsdt.internal.compiler.lookup.*; | |
public class IntLiteral extends NumberLiteral { | |
public int value; | |
public static final IntLiteral | |
One = new IntLiteral(new char[]{'1'},0,0,1);//used for ++ and -- | |
static final Constant FORMAT_ERROR = new DoubleConstant(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 = Constant.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 | |
long MAX = Integer.MAX_VALUE; | |
if (this == One) { constant = Constant.One; return ;} | |
int length = source.length; | |
long computedValue = 0L; | |
if (source[0] == '0') | |
{ MAX = 0xFFFFFFFFL ; //a long in order to be positive ! | |
if (length == 1) { constant = Constant.fromValue(0); return ;} | |
final int shift,radix; | |
int j ; | |
if ( (source[1] == 'x') || (source[1] == 'X') ) | |
{ shift = 4 ; j = 2; radix = 16;} | |
else | |
{ shift = 3 ; j = 1; radix = 8;} | |
while (source[j]=='0') | |
{ j++; //jump over redondant zero | |
if (j == length) | |
{ //watch for 000000000000000000 | |
constant = Constant.fromValue(value = (int)computedValue); | |
return ;}} | |
while (j<length) | |
{ int digitValue ; | |
if ((digitValue = Character.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 = Character.digit(source[i],10)) < 0 ) | |
{ constant = FORMAT_ERROR; return ;} | |
computedValue = 10*computedValue + digitValue; | |
if (computedValue > MAX) return /*constant stays null*/ ; }} | |
constant = Constant.fromValue(value = (int)computedValue); | |
} | |
/** | |
* Code generation for int literal | |
* | |
* @param currentScope org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope | |
* @param codeStream org.eclipse.wst.jsdt.internal.compiler.codegen.CodeStream | |
* @param valueRequired boolean | |
*/ | |
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { | |
int pc = codeStream.position; | |
if (valueRequired) | |
if ((implicitConversion >> 4) == T_int) | |
codeStream.generateInlinedValue(value); | |
else | |
codeStream.generateConstant(constant, implicitConversion); | |
codeStream.recordPositionsFrom(pc, this.sourceStart); | |
} | |
public TypeBinding literalType(BlockScope scope) { | |
return IntBinding; | |
} | |
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'));} | |
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 = 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); | |
} | |
} |