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.codegen.CodeStream;
014: import org.eclipse.jdt.internal.compiler.impl.FloatConstant;
015: import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
016: import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
017: import org.eclipse.jdt.internal.compiler.util.FloatUtil;
018:
019: public class FloatLiteral extends NumberLiteral {
020: float value;
021: final static float Float_MIN_VALUE = Float.intBitsToFloat(1); // work-around VAJ problem 1F6IGUU
022:
023: public FloatLiteral(char[] token, int s, int e) {
024: super (token, s, e);
025: }
026:
027: public void computeConstant() {
028: Float computedValue;
029: try {
030: computedValue = Float.valueOf(String.valueOf(source));
031: } catch (NumberFormatException e) {
032: // hex floating point literal
033: // being rejected by 1.4 libraries where Float.valueOf(...) doesn't handle hex decimal floats
034: try {
035: float v = FloatUtil.valueOfHexFloatLiteral(source);
036: if (v == Float.POSITIVE_INFINITY) {
037: // error: the number is too large to represent
038: return;
039: }
040: if (Float.isNaN(v)) {
041: // error: the number is too small to represent
042: return;
043: }
044: value = v;
045: constant = FloatConstant.fromValue(v);
046: } catch (NumberFormatException e1) {
047: // if the computation of the constant fails
048: }
049: return;
050: }
051:
052: final float floatValue = computedValue.floatValue();
053: if (floatValue > Float.MAX_VALUE) {
054: // error: the number is too large to represent
055: return;
056: }
057: if (floatValue < Float.MIN_VALUE) {
058: // see 1F6IGUU
059: // a true 0 only has '0' and '.' in mantissa
060: // 1.0e-5000d is non-zero, but underflows to 0
061: boolean isHexaDecimal = false;
062: label: for (int i = 0; i < source.length; i++) { //it is welled formated so just test against '0' and potential . D d
063: switch (source[i]) {
064: case '0':
065: case '.':
066: break;
067: case 'x':
068: case 'X':
069: isHexaDecimal = true;
070: break;
071: case 'e':
072: case 'E':
073: case 'f':
074: case 'F':
075: case 'd':
076: case 'D':
077: if (isHexaDecimal) {
078: return;
079: }
080: // starting the exponent - mantissa is all zero
081: // no exponent - mantissa is all zero
082: break label;
083: case 'p':
084: case 'P':
085: break label;
086: default:
087: // error: the number is too small to represent
088: return;
089: }
090: }
091: }
092: value = floatValue;
093: constant = FloatConstant.fromValue(value);
094: }
095:
096: /**
097: * Code generation for float literal
098: *
099: * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
100: * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
101: * @param valueRequired boolean
102: */
103: public void generateCode(BlockScope currentScope,
104: CodeStream codeStream, boolean valueRequired) {
105: int pc = codeStream.position;
106: if (valueRequired) {
107: codeStream.generateConstant(constant, implicitConversion);
108: }
109: codeStream.recordPositionsFrom(pc, this .sourceStart);
110: }
111:
112: public TypeBinding literalType(BlockScope scope) {
113: return TypeBinding.FLOAT;
114: }
115:
116: public void traverse(ASTVisitor visitor, BlockScope scope) {
117: visitor.visit(this, scope);
118: visitor.endVisit(this, scope);
119: }
120: }
|