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: ReferenceType.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.PUSH; 025 import org.apache.bcel.generic.ALOAD; 026 import org.apache.bcel.generic.ASTORE; 027 import org.apache.bcel.generic.ConstantPoolGen; 028 import org.apache.bcel.generic.IFEQ; 029 import org.apache.bcel.generic.ILOAD; 030 import org.apache.bcel.generic.INVOKEINTERFACE; 031 import org.apache.bcel.generic.INVOKESTATIC; 032 import org.apache.bcel.generic.Instruction; 033 import org.apache.bcel.generic.InstructionList; 034 035 import org.apache.xalan.xsltc.compiler.Constants; 036 import org.apache.xalan.xsltc.compiler.FlowList; 037 038 import org.apache.xml.dtm.DTM; 039 040 /** 041 * @author Jacek Ambroziak 042 * @author Santiago Pericas-Geertsen 043 * @author Erwin Bolwidt <ejb@klomp.org> 044 */ 045 public final class ReferenceType extends Type { 046 protected ReferenceType() {} 047 048 public String toString() { 049 return "reference"; 050 } 051 052 public boolean identicalTo(Type other) { 053 return this == other; 054 } 055 056 public String toSignature() { 057 return "Ljava/lang/Object;"; 058 } 059 060 public org.apache.bcel.generic.Type toJCType() { 061 return org.apache.bcel.generic.Type.OBJECT; 062 } 063 064 /** 065 * Translates a reference to an object of internal type <code>type</code>. 066 * The translation to int is undefined since references 067 * are always converted to reals in arithmetic expressions. 068 * 069 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 070 */ 071 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 072 Type type) { 073 if (type == Type.String) { 074 translateTo(classGen, methodGen, (StringType) type); 075 } 076 else if (type == Type.Real) { 077 translateTo(classGen, methodGen, (RealType) type); 078 } 079 else if (type == Type.Boolean) { 080 translateTo(classGen, methodGen, (BooleanType) type); 081 } 082 else if (type == Type.NodeSet) { 083 translateTo(classGen, methodGen, (NodeSetType) type); 084 } 085 else if (type == Type.Node) { 086 translateTo(classGen, methodGen, (NodeType) type); 087 } 088 else if (type == Type.ResultTree) { 089 translateTo(classGen, methodGen, (ResultTreeType) type); 090 } 091 else if (type == Type.Object) { 092 translateTo(classGen, methodGen, (ObjectType) type); 093 } 094 else if (type == Type.Reference ) { 095 } 096 else { 097 ErrorMsg err = new ErrorMsg(ErrorMsg.INTERNAL_ERR, type.toString()); 098 classGen.getParser().reportError(Constants.FATAL, err); 099 } 100 } 101 102 /** 103 * Translates reference into object of internal type <code>type</code>. 104 * 105 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 106 */ 107 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 108 StringType type) { 109 final int current = methodGen.getLocalIndex("current"); 110 ConstantPoolGen cpg = classGen.getConstantPool(); 111 InstructionList il = methodGen.getInstructionList(); 112 113 // If no current, conversion is a top-level 114 if (current < 0) { 115 il.append(new PUSH(cpg, DTM.ROOT_NODE)); // push root node 116 } 117 else { 118 il.append(new ILOAD(current)); 119 } 120 il.append(methodGen.loadDOM()); 121 final int stringF = cpg.addMethodref(BASIS_LIBRARY_CLASS, 122 "stringF", 123 "(" 124 + OBJECT_SIG 125 + NODE_SIG 126 + DOM_INTF_SIG 127 + ")" + STRING_SIG); 128 il.append(new INVOKESTATIC(stringF)); 129 } 130 131 /** 132 * Translates a reference into an object of internal type <code>type</code>. 133 * 134 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 135 */ 136 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 137 RealType type) { 138 final ConstantPoolGen cpg = classGen.getConstantPool(); 139 final InstructionList il = methodGen.getInstructionList(); 140 141 il.append(methodGen.loadDOM()); 142 int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "numberF", 143 "(" 144 + OBJECT_SIG 145 + DOM_INTF_SIG 146 + ")D"); 147 il.append(new INVOKESTATIC(index)); 148 } 149 150 /** 151 * Translates a reference to an object of internal type <code>type</code>. 152 * 153 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 154 */ 155 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 156 BooleanType type) { 157 final ConstantPoolGen cpg = classGen.getConstantPool(); 158 final InstructionList il = methodGen.getInstructionList(); 159 160 int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "booleanF", 161 "(" 162 + OBJECT_SIG 163 + ")Z"); 164 il.append(new INVOKESTATIC(index)); 165 } 166 167 /** 168 * Casts a reference into a NodeIterator. 169 * 170 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 171 */ 172 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 173 NodeSetType type) { 174 final ConstantPoolGen cpg = classGen.getConstantPool(); 175 final InstructionList il = methodGen.getInstructionList(); 176 int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "referenceToNodeSet", 177 "(" 178 + OBJECT_SIG 179 + ")" 180 + NODE_ITERATOR_SIG); 181 il.append(new INVOKESTATIC(index)); 182 183 // Reset this iterator 184 index = cpg.addInterfaceMethodref(NODE_ITERATOR, RESET, RESET_SIG); 185 il.append(new INVOKEINTERFACE(index, 1)); 186 } 187 188 /** 189 * Casts a reference into a Node. 190 * 191 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 192 */ 193 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 194 NodeType type) { 195 translateTo(classGen, methodGen, Type.NodeSet); 196 Type.NodeSet.translateTo(classGen, methodGen, type); 197 } 198 199 /** 200 * Casts a reference into a ResultTree. 201 * 202 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 203 */ 204 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 205 ResultTreeType type) { 206 final ConstantPoolGen cpg = classGen.getConstantPool(); 207 final InstructionList il = methodGen.getInstructionList(); 208 int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "referenceToResultTree", 209 "(" + OBJECT_SIG + ")" + DOM_INTF_SIG); 210 il.append(new INVOKESTATIC(index)); 211 } 212 213 /** 214 * Subsume reference into ObjectType. 215 * 216 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 217 */ 218 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 219 ObjectType type) { 220 methodGen.getInstructionList().append(NOP); 221 } 222 223 /** 224 * Translates a reference into the Java type denoted by <code>clazz</code>. 225 */ 226 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 227 Class clazz) { 228 final ConstantPoolGen cpg = classGen.getConstantPool(); 229 final InstructionList il = methodGen.getInstructionList(); 230 231 int referenceToLong = cpg.addMethodref(BASIS_LIBRARY_CLASS, 232 "referenceToLong", 233 "(" + OBJECT_SIG + ")J"); 234 int referenceToDouble = cpg.addMethodref(BASIS_LIBRARY_CLASS, 235 "referenceToDouble", 236 "(" + OBJECT_SIG + ")D"); 237 int referenceToBoolean = cpg.addMethodref(BASIS_LIBRARY_CLASS, 238 "referenceToBoolean", 239 "(" + OBJECT_SIG + ")Z"); 240 241 if (clazz.getName().equals("java.lang.Object")) { 242 il.append(NOP); 243 } 244 else if (clazz == Double.TYPE) { 245 il.append(new INVOKESTATIC(referenceToDouble)); 246 } 247 else if (clazz.getName().equals("java.lang.Double")) { 248 il.append(new INVOKESTATIC(referenceToDouble)); 249 Type.Real.translateTo(classGen, methodGen, Type.Reference); 250 } 251 else if (clazz == Float.TYPE) { 252 il.append(new INVOKESTATIC(referenceToDouble)); 253 il.append(D2F); 254 } 255 else if (clazz.getName().equals("java.lang.String")) { 256 int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "referenceToString", 257 "(" 258 + OBJECT_SIG 259 + DOM_INTF_SIG 260 + ")" 261 + "Ljava/lang/String;"); 262 il.append(methodGen.loadDOM()); 263 il.append(new INVOKESTATIC(index)); 264 } 265 else if (clazz.getName().equals("org.w3c.dom.Node")) { 266 int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "referenceToNode", 267 "(" 268 + OBJECT_SIG 269 + DOM_INTF_SIG 270 + ")" 271 + "Lorg/w3c/dom/Node;"); 272 il.append(methodGen.loadDOM()); 273 il.append(new INVOKESTATIC(index)); 274 } 275 else if (clazz.getName().equals("org.w3c.dom.NodeList")) { 276 int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "referenceToNodeList", 277 "(" 278 + OBJECT_SIG 279 + DOM_INTF_SIG 280 + ")" 281 + "Lorg/w3c/dom/NodeList;"); 282 il.append(methodGen.loadDOM()); 283 il.append(new INVOKESTATIC(index)); 284 } 285 else if (clazz.getName().equals("org.apache.xalan.xsltc.DOM")) { 286 translateTo(classGen, methodGen, Type.ResultTree); 287 } 288 else if (clazz == Long.TYPE) { 289 il.append(new INVOKESTATIC(referenceToLong)); 290 } 291 else if (clazz == Integer.TYPE) { 292 il.append(new INVOKESTATIC(referenceToLong)); 293 il.append(L2I); 294 } 295 else if (clazz == Short.TYPE) { 296 il.append(new INVOKESTATIC(referenceToLong)); 297 il.append(L2I); 298 il.append(I2S); 299 } 300 else if (clazz == Byte.TYPE) { 301 il.append(new INVOKESTATIC(referenceToLong)); 302 il.append(L2I); 303 il.append(I2B); 304 } 305 else if (clazz == Character.TYPE) { 306 il.append(new INVOKESTATIC(referenceToLong)); 307 il.append(L2I); 308 il.append(I2C); 309 } 310 else if (clazz == java.lang.Boolean.TYPE) { 311 il.append(new INVOKESTATIC(referenceToBoolean)); 312 } 313 else if (clazz.getName().equals("java.lang.Boolean")) { 314 il.append(new INVOKESTATIC(referenceToBoolean)); 315 Type.Boolean.translateTo(classGen, methodGen, Type.Reference); 316 } 317 else { 318 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 319 toString(), clazz.getName()); 320 classGen.getParser().reportError(Constants.FATAL, err); 321 } 322 } 323 324 /** 325 * Translates an external Java type into a reference. Only conversion 326 * allowed is from java.lang.Object. 327 */ 328 public void translateFrom(ClassGenerator classGen, MethodGenerator methodGen, 329 Class clazz) { 330 if (clazz.getName().equals("java.lang.Object")) { 331 methodGen.getInstructionList().append(NOP); 332 } 333 else { 334 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 335 toString(), clazz.getName()); 336 classGen.getParser().reportError(Constants.FATAL, err); 337 } 338 } 339 340 /** 341 * Expects a reference on the stack and translates it to a non-synthesized 342 * boolean. It does not push a 0 or a 1 but instead returns branchhandle 343 * list to be appended to the false list. 344 * 345 * @see org.apache.xalan.xsltc.compiler.util.Type#translateToDesynthesized 346 */ 347 public FlowList translateToDesynthesized(ClassGenerator classGen, 348 MethodGenerator methodGen, 349 BooleanType type) { 350 InstructionList il = methodGen.getInstructionList(); 351 translateTo(classGen, methodGen, type); 352 return new FlowList(il.append(new IFEQ(null))); 353 } 354 355 /** 356 * Translates an object of this type to its boxed representation. 357 */ 358 public void translateBox(ClassGenerator classGen, 359 MethodGenerator methodGen) { 360 } 361 362 /** 363 * Translates an object of this type to its unboxed representation. 364 */ 365 public void translateUnBox(ClassGenerator classGen, 366 MethodGenerator methodGen) { 367 } 368 369 370 public Instruction LOAD(int slot) { 371 return new ALOAD(slot); 372 } 373 374 public Instruction STORE(int slot) { 375 return new ASTORE(slot); 376 } 377 } 378