/*******************************************************************************
* Copyright (c) 2000, 2009 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.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.eclipse.jdt.internal.compiler.impl.IntConstant;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
public class IntLiteral extends NumberLiteral {
public int value;
public static final IntLiteral One= new IntLiteral(new char[] { '1' }, 0, 0, 1);//used for ++ and --
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);
this.constant= IntConstant.fromValue(intValue);
this.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) {
this.constant= IntConstant.fromValue(1);
return;
}
int length= this.source.length;
long computedValue= 0L;
if (this.source[0] == '0') {
MAX= 0xFFFFFFFFL; //a long in order to be positive !
if (length == 1) {
this.constant= IntConstant.fromValue(0);
return;
}
final int shift, radix;
int j;
if ((this.source[1] == 'x') || (this.source[1] == 'X')) {
shift= 4;
j= 2;
radix= 16;
} else {
shift= 3;
j= 1;
radix= 8;
}
while (this.source[j] == '0') {
j++; //jump over redondant zero
if (j == length) {
//watch for 000000000000000000
this.constant= IntConstant.fromValue(this.value= (int)computedValue);
return;
}
}
while (j < length) {
int digitValue;
if ((digitValue= ScannerHelper.digit(this.source[j++], radix)) < 0) {
return; /*constant stays null*/
}
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(this.source[i], 10)) < 0) {
return; /*constant stays null*/
}
computedValue= 10 * computedValue + digitValue;
if (computedValue > MAX)
return /*constant stays null*/;
}
}
this.constant= IntConstant.fromValue(this.value= (int)computedValue);
}
/**
* Code generation for int literal
*
* @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
* @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
* @param valueRequired boolean
*/
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
int pc= codeStream.position;
if (valueRequired) {
codeStream.generateConstant(this.constant, this.implicitConversion);
}
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
public TypeBinding literalType(BlockScope scope) {
return TypeBinding.INT;
}
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 ((this.source.length == 10) &&
(this.source[0] == '2') &&
(this.source[1] == '1') &&
(this.source[2] == '4') &&
(this.source[3] == '7') &&
(this.source[4] == '4') &&
(this.source[5] == '8') &&
(this.source[6] == '3') &&
(this.source[7] == '6') &&
(this.source[8] == '4') &&
(this.source[9] == '8') && (((this.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0));
}
public StringBuffer printExpression(int indent, StringBuffer output) {
if (this.source == null) {
/* special optimized IntLiteral that are created by the compiler */
return output.append(String.valueOf(this.value));
}
return super.printExpression(indent, output);
}
public void traverse(ASTVisitor visitor, BlockScope scope) {
visitor.visit(this, scope);
visitor.endVisit(this, scope);
}
}