001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.compiler.ast;
011:
012: import org.eclipse.jdt.internal.compiler.ASTVisitor;
013: import org.eclipse.jdt.internal.compiler.impl.*;
014: import org.eclipse.jdt.internal.compiler.codegen.*;
015: import org.eclipse.jdt.internal.compiler.lookup.*;
016: import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
017:
018: public class IntLiteral extends NumberLiteral {
019: public int value;
020:
021: public static final IntLiteral One = new IntLiteral(
022: new char[] { '1' }, 0, 0, 1);//used for ++ and --
023:
024: static final Constant FORMAT_ERROR = DoubleConstant
025: .fromValue(1.0 / 0.0); // NaN;
026:
027: public IntLiteral(char[] token, int s, int e) {
028: super (token, s, e);
029: }
030:
031: public IntLiteral(char[] token, int s, int e, int value) {
032: this (token, s, e);
033: this .value = value;
034: }
035:
036: public IntLiteral(int intValue) {
037: //special optimized constructor : the cst is the argument
038:
039: //value that should not be used
040: // tokens = null ;
041: // sourceStart = 0;
042: // sourceEnd = 0;
043: super (null, 0, 0);
044: constant = IntConstant.fromValue(intValue);
045: value = intValue;
046:
047: }
048:
049: public void computeConstant() {
050: //a special constant is use for the potential Integer.MAX_VALUE+1
051: //which is legal if used with a - as prefix....cool....
052: //notice that Integer.MIN_VALUE == -2147483648
053:
054: long MAX = Integer.MAX_VALUE;
055: if (this == One) {
056: constant = IntConstant.fromValue(1);
057: return;
058: }
059:
060: int length = source.length;
061: long computedValue = 0L;
062: if (source[0] == '0') {
063: MAX = 0xFFFFFFFFL; //a long in order to be positive !
064: if (length == 1) {
065: constant = IntConstant.fromValue(0);
066: return;
067: }
068: final int shift, radix;
069: int j;
070: if ((source[1] == 'x') || (source[1] == 'X')) {
071: shift = 4;
072: j = 2;
073: radix = 16;
074: } else {
075: shift = 3;
076: j = 1;
077: radix = 8;
078: }
079: while (source[j] == '0') {
080: j++; //jump over redondant zero
081: if (j == length) { //watch for 000000000000000000
082: constant = IntConstant
083: .fromValue(value = (int) computedValue);
084: return;
085: }
086: }
087:
088: while (j < length) {
089: int digitValue;
090: if ((digitValue = ScannerHelper.digit(source[j++],
091: radix)) < 0) {
092: constant = FORMAT_ERROR;
093: return;
094: }
095: computedValue = (computedValue << shift) | digitValue;
096: if (computedValue > MAX)
097: return /*constant stays null*/;
098: }
099: } else { //-----------regular case : radix = 10-----------
100: for (int i = 0; i < length; i++) {
101: int digitValue;
102: if ((digitValue = ScannerHelper.digit(source[i], 10)) < 0) {
103: constant = FORMAT_ERROR;
104: return;
105: }
106: computedValue = 10 * computedValue + digitValue;
107: if (computedValue > MAX)
108: return /*constant stays null*/;
109: }
110: }
111:
112: constant = IntConstant.fromValue(value = (int) computedValue);
113:
114: }
115:
116: /**
117: * Code generation for int literal
118: *
119: * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
120: * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
121: * @param valueRequired boolean
122: */
123: public void generateCode(BlockScope currentScope,
124: CodeStream codeStream, boolean valueRequired) {
125: int pc = codeStream.position;
126: if (valueRequired) {
127: codeStream.generateConstant(constant, implicitConversion);
128: }
129: codeStream.recordPositionsFrom(pc, this .sourceStart);
130: }
131:
132: public TypeBinding literalType(BlockScope scope) {
133: return TypeBinding.INT;
134: }
135:
136: public final boolean mayRepresentMIN_VALUE() {
137: //a special autorized int literral is 2147483648
138: //which is ONE over the limit. This special case
139: //only is used in combinaison with - to denote
140: //the minimal value of int -2147483648
141:
142: return ((source.length == 10) && (source[0] == '2')
143: && (source[1] == '1') && (source[2] == '4')
144: && (source[3] == '7') && (source[4] == '4')
145: && (source[5] == '8') && (source[6] == '3')
146: && (source[7] == '6') && (source[8] == '4')
147: && (source[9] == '8') && (((this .bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0));
148: }
149:
150: public TypeBinding resolveType(BlockScope scope) {
151: // the format may be incorrect while the scanner could detect
152: // such an error only on painfull tests...easier and faster here
153:
154: TypeBinding tb = super .resolveType(scope);
155: if (constant == FORMAT_ERROR) {
156: constant = Constant.NotAConstant;
157: scope.problemReporter().constantOutOfFormat(this );
158: this .resolvedType = null;
159: return null;
160: }
161: return tb;
162: }
163:
164: public StringBuffer printExpression(int indent, StringBuffer output) {
165:
166: if (source == null) {
167: /* special optimized IntLiteral that are created by the compiler */
168: return output.append(String.valueOf(value));
169: }
170: return super .printExpression(indent, output);
171: }
172:
173: public void traverse(ASTVisitor visitor, BlockScope scope) {
174: visitor.visit(this, scope);
175: visitor.endVisit(this, scope);
176: }
177: }
|