/*******************************************************************************
 * 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.jdt.internal.compiler.ast;

import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
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 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 void traverse(ASTVisitor visitor, BlockScope scope) {
	visitor.visit(this, scope);
	visitor.endVisit(this, scope);
}
}
