1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Copyright 2001-2004 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 /* 21 * $Id: RealType.java,v 1.2.4.1 2005/09/05 11:28:45 pvedula Exp $ 22 */ 23 24 package com.sun.org.apache.xalan.internal.xsltc.compiler.util; 25 26 import com.sun.org.apache.bcel.internal.generic.BranchHandle; 27 import com.sun.org.apache.bcel.internal.generic.CHECKCAST; 28 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 29 import com.sun.org.apache.bcel.internal.generic.DLOAD; 30 import com.sun.org.apache.bcel.internal.generic.DSTORE; 31 import com.sun.org.apache.bcel.internal.generic.GOTO; 32 import com.sun.org.apache.bcel.internal.generic.IFEQ; 33 import com.sun.org.apache.bcel.internal.generic.IFNE; 34 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; 35 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; 36 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; 37 import com.sun.org.apache.bcel.internal.generic.Instruction; 38 import com.sun.org.apache.bcel.internal.generic.InstructionConstants; 39 import com.sun.org.apache.bcel.internal.generic.InstructionList; 40 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; 41 import com.sun.org.apache.bcel.internal.generic.NEW; 42 import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants; 43 import com.sun.org.apache.xalan.internal.xsltc.compiler.FlowList; 44 45 /** 46 * @author Jacek Ambroziak 47 * @author Santiago Pericas-Geertsen 48 */ 49 public final class RealType extends NumberType { RealType()50 protected RealType() {} 51 toString()52 public String toString() { 53 return "real"; 54 } 55 identicalTo(Type other)56 public boolean identicalTo(Type other) { 57 return this == other; 58 } 59 toSignature()60 public String toSignature() { 61 return "D"; 62 } 63 toJCType()64 public com.sun.org.apache.bcel.internal.generic.Type toJCType() { 65 return com.sun.org.apache.bcel.internal.generic.Type.DOUBLE; 66 } 67 68 /** 69 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#distanceTo 70 */ distanceTo(Type type)71 public int distanceTo(Type type) { 72 if (type == this) { 73 return 0; 74 } 75 else if (type == Type.Int) { 76 return 1; 77 } 78 else { 79 return Integer.MAX_VALUE; 80 } 81 } 82 83 /** 84 * Translates a real into an object of internal type <code>type</code>. The 85 * translation to int is undefined since reals are never converted to ints. 86 * 87 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 88 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, Type type)89 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 90 Type type) { 91 if (type == Type.String) { 92 translateTo(classGen, methodGen, (StringType) type); 93 } 94 else if (type == Type.Boolean) { 95 translateTo(classGen, methodGen, (BooleanType) type); 96 } 97 else if (type == Type.Reference) { 98 translateTo(classGen, methodGen, (ReferenceType) type); 99 } 100 else if (type == Type.Int) { 101 translateTo(classGen, methodGen, (IntType) type); 102 } 103 else { 104 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 105 toString(), type.toString()); 106 classGen.getParser().reportError(Constants.FATAL, err); 107 } 108 } 109 110 /** 111 * Expects a real on the stack and pushes its string value by calling 112 * <code>Double.toString(double d)</code>. 113 * 114 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 115 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, StringType type)116 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 117 StringType type) { 118 final ConstantPoolGen cpg = classGen.getConstantPool(); 119 final InstructionList il = methodGen.getInstructionList(); 120 il.append(new INVOKESTATIC(cpg.addMethodref(BASIS_LIBRARY_CLASS, 121 "realToString", 122 "(D)" + STRING_SIG))); 123 } 124 125 /** 126 * Expects a real on the stack and pushes a 0 if that number is 0.0 and 127 * a 1 otherwise. 128 * 129 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 130 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, BooleanType type)131 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 132 BooleanType type) { 133 final InstructionList il = methodGen.getInstructionList(); 134 FlowList falsel = translateToDesynthesized(classGen, methodGen, type); 135 il.append(ICONST_1); 136 final BranchHandle truec = il.append(new GOTO(null)); 137 falsel.backPatch(il.append(ICONST_0)); 138 truec.setTarget(il.append(NOP)); 139 } 140 141 /** 142 * Expects a real on the stack and pushes a truncated integer value 143 * 144 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 145 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, IntType type)146 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 147 IntType type) { 148 final ConstantPoolGen cpg = classGen.getConstantPool(); 149 final InstructionList il = methodGen.getInstructionList(); 150 il.append(new INVOKESTATIC(cpg.addMethodref(BASIS_LIBRARY_CLASS, 151 "realToInt","(D)I"))); 152 } 153 154 /** 155 * Translates a real into a non-synthesized boolean. It does not push a 156 * 0 or a 1 but instead returns branchhandle list to be appended to the 157 * false list. A NaN must be converted to "false". 158 * 159 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateToDesynthesized 160 */ translateToDesynthesized(ClassGenerator classGen, MethodGenerator methodGen, BooleanType type)161 public FlowList translateToDesynthesized(ClassGenerator classGen, 162 MethodGenerator methodGen, 163 BooleanType type) { 164 LocalVariableGen local; 165 final FlowList flowlist = new FlowList(); 166 final ConstantPoolGen cpg = classGen.getConstantPool(); 167 final InstructionList il = methodGen.getInstructionList(); 168 169 // Store real into a local variable 170 il.append(DUP2); 171 local = methodGen.addLocalVariable("real_to_boolean_tmp", 172 com.sun.org.apache.bcel.internal.generic.Type.DOUBLE, 173 null, null); 174 local.setStart(il.append(new DSTORE(local.getIndex()))); 175 176 // Compare it to 0.0 177 il.append(DCONST_0); 178 il.append(DCMPG); 179 flowlist.add(il.append(new IFEQ(null))); 180 181 //!!! call isNaN 182 // Compare it to itself to see if NaN 183 il.append(new DLOAD(local.getIndex())); 184 local.setEnd(il.append(new DLOAD(local.getIndex()))); 185 il.append(DCMPG); 186 flowlist.add(il.append(new IFNE(null))); // NaN != NaN 187 return flowlist; 188 } 189 190 /** 191 * Expects a double on the stack and pushes a boxed double. Boxed 192 * double are represented by an instance of <code>java.lang.Double</code>. 193 * 194 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 195 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, ReferenceType type)196 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 197 ReferenceType type) { 198 final ConstantPoolGen cpg = classGen.getConstantPool(); 199 final InstructionList il = methodGen.getInstructionList(); 200 il.append(new NEW(cpg.addClass(DOUBLE_CLASS))); 201 il.append(DUP_X2); 202 il.append(DUP_X2); 203 il.append(POP); 204 il.append(new INVOKESPECIAL(cpg.addMethodref(DOUBLE_CLASS, 205 "<init>", "(D)V"))); 206 } 207 208 /** 209 * Translates a real into the Java type denoted by <code>clazz</code>. 210 * Expects a real on the stack and pushes a number of the appropriate 211 * type after coercion. 212 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, final Class clazz)213 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 214 final Class clazz) { 215 final InstructionList il = methodGen.getInstructionList(); 216 if (clazz == Character.TYPE) { 217 il.append(D2I); 218 il.append(I2C); 219 } 220 else if (clazz == Byte.TYPE) { 221 il.append(D2I); 222 il.append(I2B); 223 } 224 else if (clazz == Short.TYPE) { 225 il.append(D2I); 226 il.append(I2S); 227 } 228 else if (clazz == Integer.TYPE) { 229 il.append(D2I); 230 } 231 else if (clazz == Long.TYPE) { 232 il.append(D2L); 233 } 234 else if (clazz == Float.TYPE) { 235 il.append(D2F); 236 } 237 else if (clazz == Double.TYPE) { 238 il.append(NOP); 239 } 240 // Is Double <: clazz? I.e. clazz in { Double, Number, Object } 241 else if (clazz.isAssignableFrom(java.lang.Double.class)) { 242 translateTo(classGen, methodGen, Type.Reference); 243 } 244 else { 245 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 246 toString(), clazz.getName()); 247 classGen.getParser().reportError(Constants.FATAL, err); 248 } 249 } 250 251 /** 252 * Translates an external (primitive) Java type into a real. Expects a java 253 * object on the stack and pushes a real (i.e., a double). 254 */ translateFrom(ClassGenerator classGen, MethodGenerator methodGen, Class clazz)255 public void translateFrom(ClassGenerator classGen, MethodGenerator methodGen, 256 Class clazz) { 257 InstructionList il = methodGen.getInstructionList(); 258 259 if (clazz == Character.TYPE || clazz == Byte.TYPE || 260 clazz == Short.TYPE || clazz == Integer.TYPE) { 261 il.append(I2D); 262 } 263 else if (clazz == Long.TYPE) { 264 il.append(L2D); 265 } 266 else if (clazz == Float.TYPE) { 267 il.append(F2D); 268 } 269 else if (clazz == Double.TYPE) { 270 il.append(NOP); 271 } 272 else { 273 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 274 toString(), clazz.getName()); 275 classGen.getParser().reportError(Constants.FATAL, err); 276 } 277 } 278 279 /** 280 * Translates an object of this type to its boxed representation. 281 */ translateBox(ClassGenerator classGen, MethodGenerator methodGen)282 public void translateBox(ClassGenerator classGen, 283 MethodGenerator methodGen) { 284 translateTo(classGen, methodGen, Type.Reference); 285 } 286 287 /** 288 * Translates an object of this type to its unboxed representation. 289 */ translateUnBox(ClassGenerator classGen, MethodGenerator methodGen)290 public void translateUnBox(ClassGenerator classGen, 291 MethodGenerator methodGen) { 292 final ConstantPoolGen cpg = classGen.getConstantPool(); 293 final InstructionList il = methodGen.getInstructionList(); 294 il.append(new CHECKCAST(cpg.addClass(DOUBLE_CLASS))); 295 il.append(new INVOKEVIRTUAL(cpg.addMethodref(DOUBLE_CLASS, 296 DOUBLE_VALUE, 297 DOUBLE_VALUE_SIG))); 298 } 299 ADD()300 public Instruction ADD() { 301 return InstructionConstants.DADD; 302 } 303 SUB()304 public Instruction SUB() { 305 return InstructionConstants.DSUB; 306 } 307 MUL()308 public Instruction MUL() { 309 return InstructionConstants.DMUL; 310 } 311 DIV()312 public Instruction DIV() { 313 return InstructionConstants.DDIV; 314 } 315 REM()316 public Instruction REM() { 317 return InstructionConstants.DREM; 318 } 319 NEG()320 public Instruction NEG() { 321 return InstructionConstants.DNEG; 322 } 323 LOAD(int slot)324 public Instruction LOAD(int slot) { 325 return new DLOAD(slot); 326 } 327 STORE(int slot)328 public Instruction STORE(int slot) { 329 return new DSTORE(slot); 330 } 331 POP()332 public Instruction POP() { 333 return POP2; 334 } 335 CMP(boolean less)336 public Instruction CMP(boolean less) { 337 return less ? InstructionConstants.DCMPG : InstructionConstants.DCMPL; 338 } 339 DUP()340 public Instruction DUP() { 341 return DUP2; 342 } 343 } 344