diff options
Diffstat (limited to 'src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/RealType.java')
-rw-r--r-- | src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/RealType.java | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/RealType.java b/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/RealType.java new file mode 100644 index 0000000..2d1e745 --- /dev/null +++ b/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/RealType.java @@ -0,0 +1,343 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/* + * Copyright 2001-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * $Id: RealType.java,v 1.2.4.1 2005/09/05 11:28:45 pvedula Exp $ + */ + +package com.sun.org.apache.xalan.internal.xsltc.compiler.util; + +import com.sun.org.apache.bcel.internal.generic.BranchHandle; +import com.sun.org.apache.bcel.internal.generic.CHECKCAST; +import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.DLOAD; +import com.sun.org.apache.bcel.internal.generic.DSTORE; +import com.sun.org.apache.bcel.internal.generic.GOTO; +import com.sun.org.apache.bcel.internal.generic.IFEQ; +import com.sun.org.apache.bcel.internal.generic.IFNE; +import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; +import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; +import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; +import com.sun.org.apache.bcel.internal.generic.Instruction; +import com.sun.org.apache.bcel.internal.generic.InstructionConstants; +import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; +import com.sun.org.apache.bcel.internal.generic.NEW; +import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants; +import com.sun.org.apache.xalan.internal.xsltc.compiler.FlowList; + +/** + * @author Jacek Ambroziak + * @author Santiago Pericas-Geertsen + */ +public final class RealType extends NumberType { + protected RealType() {} + + public String toString() { + return "real"; + } + + public boolean identicalTo(Type other) { + return this == other; + } + + public String toSignature() { + return "D"; + } + + public com.sun.org.apache.bcel.internal.generic.Type toJCType() { + return com.sun.org.apache.bcel.internal.generic.Type.DOUBLE; + } + + /** + * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#distanceTo + */ + public int distanceTo(Type type) { + if (type == this) { + return 0; + } + else if (type == Type.Int) { + return 1; + } + else { + return Integer.MAX_VALUE; + } + } + + /** + * Translates a real into an object of internal type <code>type</code>. The + * translation to int is undefined since reals are never converted to ints. + * + * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo + */ + public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, + Type type) { + if (type == Type.String) { + translateTo(classGen, methodGen, (StringType) type); + } + else if (type == Type.Boolean) { + translateTo(classGen, methodGen, (BooleanType) type); + } + else if (type == Type.Reference) { + translateTo(classGen, methodGen, (ReferenceType) type); + } + else if (type == Type.Int) { + translateTo(classGen, methodGen, (IntType) type); + } + else { + ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, + toString(), type.toString()); + classGen.getParser().reportError(Constants.FATAL, err); + } + } + + /** + * Expects a real on the stack and pushes its string value by calling + * <code>Double.toString(double d)</code>. + * + * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo + */ + public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, + StringType type) { + final ConstantPoolGen cpg = classGen.getConstantPool(); + final InstructionList il = methodGen.getInstructionList(); + il.append(new INVOKESTATIC(cpg.addMethodref(BASIS_LIBRARY_CLASS, + "realToString", + "(D)" + STRING_SIG))); + } + + /** + * Expects a real on the stack and pushes a 0 if that number is 0.0 and + * a 1 otherwise. + * + * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo + */ + public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, + BooleanType type) { + final InstructionList il = methodGen.getInstructionList(); + FlowList falsel = translateToDesynthesized(classGen, methodGen, type); + il.append(ICONST_1); + final BranchHandle truec = il.append(new GOTO(null)); + falsel.backPatch(il.append(ICONST_0)); + truec.setTarget(il.append(NOP)); + } + + /** + * Expects a real on the stack and pushes a truncated integer value + * + * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo + */ + public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, + IntType type) { + final ConstantPoolGen cpg = classGen.getConstantPool(); + final InstructionList il = methodGen.getInstructionList(); + il.append(new INVOKESTATIC(cpg.addMethodref(BASIS_LIBRARY_CLASS, + "realToInt","(D)I"))); + } + + /** + * Translates a real into a non-synthesized boolean. It does not push a + * 0 or a 1 but instead returns branchhandle list to be appended to the + * false list. A NaN must be converted to "false". + * + * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateToDesynthesized + */ + public FlowList translateToDesynthesized(ClassGenerator classGen, + MethodGenerator methodGen, + BooleanType type) { + LocalVariableGen local; + final FlowList flowlist = new FlowList(); + final ConstantPoolGen cpg = classGen.getConstantPool(); + final InstructionList il = methodGen.getInstructionList(); + + // Store real into a local variable + il.append(DUP2); + local = methodGen.addLocalVariable("real_to_boolean_tmp", + com.sun.org.apache.bcel.internal.generic.Type.DOUBLE, + il.getEnd(), null); + il.append(new DSTORE(local.getIndex())); + + // Compare it to 0.0 + il.append(DCONST_0); + il.append(DCMPG); + flowlist.add(il.append(new IFEQ(null))); + + //!!! call isNaN + // Compare it to itself to see if NaN + il.append(new DLOAD(local.getIndex())); + il.append(new DLOAD(local.getIndex())); + il.append(DCMPG); + flowlist.add(il.append(new IFNE(null))); // NaN != NaN + return flowlist; + } + + /** + * Expects a double on the stack and pushes a boxed double. Boxed + * double are represented by an instance of <code>java.lang.Double</code>. + * + * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo + */ + public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, + ReferenceType type) { + final ConstantPoolGen cpg = classGen.getConstantPool(); + final InstructionList il = methodGen.getInstructionList(); + il.append(new NEW(cpg.addClass(DOUBLE_CLASS))); + il.append(DUP_X2); + il.append(DUP_X2); + il.append(POP); + il.append(new INVOKESPECIAL(cpg.addMethodref(DOUBLE_CLASS, + "<init>", "(D)V"))); + } + + /** + * Translates a real into the Java type denoted by <code>clazz</code>. + * Expects a real on the stack and pushes a number of the appropriate + * type after coercion. + */ + public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, + final Class clazz) { + final InstructionList il = methodGen.getInstructionList(); + if (clazz == Character.TYPE) { + il.append(D2I); + il.append(I2C); + } + else if (clazz == Byte.TYPE) { + il.append(D2I); + il.append(I2B); + } + else if (clazz == Short.TYPE) { + il.append(D2I); + il.append(I2S); + } + else if (clazz == Integer.TYPE) { + il.append(D2I); + } + else if (clazz == Long.TYPE) { + il.append(D2L); + } + else if (clazz == Float.TYPE) { + il.append(D2F); + } + else if (clazz == Double.TYPE) { + il.append(NOP); + } + // Is Double <: clazz? I.e. clazz in { Double, Number, Object } + else if (clazz.isAssignableFrom(java.lang.Double.class)) { + translateTo(classGen, methodGen, Type.Reference); + } + else { + ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, + toString(), clazz.getName()); + classGen.getParser().reportError(Constants.FATAL, err); + } + } + + /** + * Translates an external (primitive) Java type into a real. Expects a java + * object on the stack and pushes a real (i.e., a double). + */ + public void translateFrom(ClassGenerator classGen, MethodGenerator methodGen, + Class clazz) { + InstructionList il = methodGen.getInstructionList(); + + if (clazz == Character.TYPE || clazz == Byte.TYPE || + clazz == Short.TYPE || clazz == Integer.TYPE) { + il.append(I2D); + } + else if (clazz == Long.TYPE) { + il.append(L2D); + } + else if (clazz == Float.TYPE) { + il.append(F2D); + } + else if (clazz == Double.TYPE) { + il.append(NOP); + } + else { + ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, + toString(), clazz.getName()); + classGen.getParser().reportError(Constants.FATAL, err); + } + } + + /** + * Translates an object of this type to its boxed representation. + */ + public void translateBox(ClassGenerator classGen, + MethodGenerator methodGen) { + translateTo(classGen, methodGen, Type.Reference); + } + + /** + * Translates an object of this type to its unboxed representation. + */ + public void translateUnBox(ClassGenerator classGen, + MethodGenerator methodGen) { + final ConstantPoolGen cpg = classGen.getConstantPool(); + final InstructionList il = methodGen.getInstructionList(); + il.append(new CHECKCAST(cpg.addClass(DOUBLE_CLASS))); + il.append(new INVOKEVIRTUAL(cpg.addMethodref(DOUBLE_CLASS, + DOUBLE_VALUE, + DOUBLE_VALUE_SIG))); + } + + public Instruction ADD() { + return InstructionConstants.DADD; + } + + public Instruction SUB() { + return InstructionConstants.DSUB; + } + + public Instruction MUL() { + return InstructionConstants.DMUL; + } + + public Instruction DIV() { + return InstructionConstants.DDIV; + } + + public Instruction REM() { + return InstructionConstants.DREM; + } + + public Instruction NEG() { + return InstructionConstants.DNEG; + } + + public Instruction LOAD(int slot) { + return new DLOAD(slot); + } + + public Instruction STORE(int slot) { + return new DSTORE(slot); + } + + public Instruction POP() { + return POP2; + } + + public Instruction CMP(boolean less) { + return less ? InstructionConstants.DCMPG : InstructionConstants.DCMPL; + } + + public Instruction DUP() { + return DUP2; + } +} |