001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 /* 019 * $Id: IntType.java 468649 2006-10-28 07:00:55Z minchau $ 020 */ 021 022 package org.apache.xalan.xsltc.compiler.util; 023 024 import org.apache.bcel.generic.BranchHandle; 025 import org.apache.bcel.generic.BranchInstruction; 026 import org.apache.bcel.generic.CHECKCAST; 027 import org.apache.bcel.generic.ConstantPoolGen; 028 import org.apache.bcel.generic.GOTO; 029 import org.apache.bcel.generic.IFEQ; 030 import org.apache.bcel.generic.IFGE; 031 import org.apache.bcel.generic.IFGT; 032 import org.apache.bcel.generic.IFLE; 033 import org.apache.bcel.generic.IFLT; 034 import org.apache.bcel.generic.IF_ICMPGE; 035 import org.apache.bcel.generic.IF_ICMPGT; 036 import org.apache.bcel.generic.IF_ICMPLE; 037 import org.apache.bcel.generic.IF_ICMPLT; 038 import org.apache.bcel.generic.ILOAD; 039 import org.apache.bcel.generic.INVOKESPECIAL; 040 import org.apache.bcel.generic.INVOKESTATIC; 041 import org.apache.bcel.generic.INVOKEVIRTUAL; 042 import org.apache.bcel.generic.ISTORE; 043 import org.apache.bcel.generic.Instruction; 044 import org.apache.bcel.generic.InstructionConstants; 045 import org.apache.bcel.generic.InstructionList; 046 import org.apache.bcel.generic.NEW; 047 import org.apache.xalan.xsltc.compiler.Constants; 048 import org.apache.xalan.xsltc.compiler.FlowList; 049 050 /** 051 * @author Jacek Ambroziak 052 * @author Santiago Pericas-Geertsen 053 */ 054 public final class IntType extends NumberType { 055 protected IntType() {} 056 057 public String toString() { 058 return "int"; 059 } 060 061 public boolean identicalTo(Type other) { 062 return this == other; 063 } 064 065 public String toSignature() { 066 return "I"; 067 } 068 069 public org.apache.bcel.generic.Type toJCType() { 070 return org.apache.bcel.generic.Type.INT; 071 } 072 073 /** 074 * @see org.apache.xalan.xsltc.compiler.util.Type#distanceTo 075 */ 076 public int distanceTo(Type type) { 077 if (type == this) { 078 return 0; 079 } 080 else if (type == Type.Real) { 081 return 1; 082 } 083 else 084 return Integer.MAX_VALUE; 085 } 086 087 /** 088 * Translates an integer into an object of internal type <code>type</code>. 089 * 090 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 091 */ 092 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 093 final Type type) { 094 if (type == Type.Real) { 095 translateTo(classGen, methodGen, (RealType) type); 096 } 097 else if (type == Type.String) { 098 translateTo(classGen, methodGen, (StringType) type); 099 } 100 else if (type == Type.Boolean) { 101 translateTo(classGen, methodGen, (BooleanType) type); 102 } 103 else if (type == Type.Reference) { 104 translateTo(classGen, methodGen, (ReferenceType) type); 105 } 106 else { 107 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 108 toString(), type.toString()); 109 classGen.getParser().reportError(Constants.FATAL, err); 110 } 111 } 112 113 /** 114 * Expects an integer on the stack and pushes a real. 115 * 116 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 117 */ 118 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 119 RealType type) { 120 methodGen.getInstructionList().append(I2D); 121 } 122 123 /** 124 * Expects an integer on the stack and pushes its string value by calling 125 * <code>Integer.toString(int i)</code>. 126 * 127 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 128 */ 129 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 130 StringType type) { 131 final ConstantPoolGen cpg = classGen.getConstantPool(); 132 final InstructionList il = methodGen.getInstructionList(); 133 il.append(new INVOKESTATIC(cpg.addMethodref(INTEGER_CLASS, 134 "toString", 135 "(I)" + STRING_SIG))); 136 } 137 138 /** 139 * Expects an integer on the stack and pushes a 0 if its value is 0 and 140 * a 1 otherwise. 141 * 142 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 143 */ 144 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 145 BooleanType type) { 146 final InstructionList il = methodGen.getInstructionList(); 147 final BranchHandle falsec = il.append(new IFEQ(null)); 148 il.append(ICONST_1); 149 final BranchHandle truec = il.append(new GOTO(null)); 150 falsec.setTarget(il.append(ICONST_0)); 151 truec.setTarget(il.append(NOP)); 152 } 153 154 /** 155 * Expects an integer on the stack and translates it to a non-synthesized 156 * boolean. It does not push a 0 or a 1 but instead returns branchhandle 157 * list to be appended to the false list. 158 * 159 * @see org.apache.xalan.xsltc.compiler.util.Type#translateToDesynthesized 160 */ 161 public FlowList translateToDesynthesized(ClassGenerator classGen, 162 MethodGenerator methodGen, 163 BooleanType type) { 164 final InstructionList il = methodGen.getInstructionList(); 165 return new FlowList(il.append(new IFEQ(null))); 166 } 167 168 /** 169 * Expects an integer on the stack and pushes a boxed integer. 170 * Boxed integers are represented by an instance of 171 * <code>java.lang.Integer</code>. 172 * 173 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 174 */ 175 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 176 ReferenceType type) { 177 final ConstantPoolGen cpg = classGen.getConstantPool(); 178 final InstructionList il = methodGen.getInstructionList(); 179 il.append(new NEW(cpg.addClass(INTEGER_CLASS))); 180 il.append(DUP_X1); 181 il.append(SWAP); 182 il.append(new INVOKESPECIAL(cpg.addMethodref(INTEGER_CLASS, 183 "<init>", "(I)V"))); 184 } 185 186 /** 187 * Translates an integer into the Java type denoted by <code>clazz</code>. 188 * Expects an integer on the stack and pushes a number of the appropriate 189 * type after coercion. 190 */ 191 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 192 Class clazz) { 193 final InstructionList il = methodGen.getInstructionList(); 194 if (clazz == Character.TYPE) { 195 il.append(I2C); 196 } 197 else if (clazz == Byte.TYPE) { 198 il.append(I2B); 199 } 200 else if (clazz == Short.TYPE) { 201 il.append(I2S); 202 } 203 else if (clazz == Integer.TYPE) { 204 il.append(NOP); 205 } 206 else if (clazz == Long.TYPE) { 207 il.append(I2L); 208 } 209 else if (clazz == Float.TYPE) { 210 il.append(I2F); 211 } 212 else if (clazz == Double.TYPE) { 213 il.append(I2D); 214 } 215 // Is Double <: clazz? I.e. clazz in { Double, Number, Object } 216 else if (clazz.isAssignableFrom(java.lang.Double.class)) { 217 il.append(I2D); 218 Type.Real.translateTo(classGen, methodGen, Type.Reference); 219 } 220 else { 221 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 222 toString(), clazz.getName()); 223 classGen.getParser().reportError(Constants.FATAL, err); 224 } 225 } 226 227 /** 228 * Translates an object of this type to its boxed representation. 229 */ 230 public void translateBox(ClassGenerator classGen, 231 MethodGenerator methodGen) { 232 translateTo(classGen, methodGen, Type.Reference); 233 } 234 235 /** 236 * Translates an object of this type to its unboxed representation. 237 */ 238 public void translateUnBox(ClassGenerator classGen, 239 MethodGenerator methodGen) { 240 final ConstantPoolGen cpg = classGen.getConstantPool(); 241 final InstructionList il = methodGen.getInstructionList(); 242 il.append(new CHECKCAST(cpg.addClass(INTEGER_CLASS))); 243 final int index = cpg.addMethodref(INTEGER_CLASS, 244 INT_VALUE, 245 INT_VALUE_SIG); 246 il.append(new INVOKEVIRTUAL(index)); 247 } 248 249 public Instruction ADD() { 250 return InstructionConstants.IADD; 251 } 252 253 public Instruction SUB() { 254 return InstructionConstants.ISUB; 255 } 256 257 public Instruction MUL() { 258 return InstructionConstants.IMUL; 259 } 260 261 public Instruction DIV() { 262 return InstructionConstants.IDIV; 263 } 264 265 public Instruction REM() { 266 return InstructionConstants.IREM; 267 } 268 269 public Instruction NEG() { 270 return InstructionConstants.INEG; 271 } 272 273 public Instruction LOAD(int slot) { 274 return new ILOAD(slot); 275 } 276 277 public Instruction STORE(int slot) { 278 return new ISTORE(slot); 279 } 280 281 public BranchInstruction GT(boolean tozero) { 282 return tozero ? (BranchInstruction) new IFGT(null) : 283 (BranchInstruction) new IF_ICMPGT(null); 284 } 285 286 public BranchInstruction GE(boolean tozero) { 287 return tozero ? (BranchInstruction) new IFGE(null) : 288 (BranchInstruction) new IF_ICMPGE(null); 289 } 290 291 public BranchInstruction LT(boolean tozero) { 292 return tozero ? (BranchInstruction) new IFLT(null) : 293 (BranchInstruction) new IF_ICMPLT(null); 294 } 295 296 public BranchInstruction LE(boolean tozero) { 297 return tozero ? (BranchInstruction) new IFLE(null) : 298 (BranchInstruction) new IF_ICMPLE(null); 299 } 300 }