/******************************************************************************* * Copyright (c) 2000, 2003 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 net.sourceforge.phpdt.internal.compiler.ast; import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor; import net.sourceforge.phpdt.internal.compiler.impl.Constant; import net.sourceforge.phpdt.internal.compiler.impl.DoubleConstant; import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope; import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding; 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 * net.sourceforge.phpdt.internal.compiler.lookup.BlockScope * @param codeStream * net.sourceforge.phpdt.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 String toStringExpression() { if (source == null) /* special optimized IntLiteral that are created by the compiler */ return String.valueOf(value); return super.toStringExpression(); } public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } }