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: StringType.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.ALOAD; 025 import org.apache.bcel.generic.ASTORE; 026 import org.apache.bcel.generic.BranchHandle; 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.IFNONNULL; 031 import org.apache.bcel.generic.INVOKESTATIC; 032 import org.apache.bcel.generic.INVOKEVIRTUAL; 033 import org.apache.bcel.generic.Instruction; 034 import org.apache.bcel.generic.InstructionList; 035 import org.apache.bcel.generic.PUSH; 036 import org.apache.xalan.xsltc.compiler.Constants; 037 import org.apache.xalan.xsltc.compiler.FlowList; 038 039 /** 040 * @author Jacek Ambroziak 041 * @author Santiago Pericas-Geertsen 042 */ 043 public class StringType extends Type { 044 protected StringType() {} 045 046 public String toString() { 047 return "string"; 048 } 049 050 public boolean identicalTo(Type other) { 051 return this == other; 052 } 053 054 public String toSignature() { 055 return "Ljava/lang/String;"; 056 } 057 058 public boolean isSimple() { 059 return true; 060 } 061 062 public org.apache.bcel.generic.Type toJCType() { 063 return org.apache.bcel.generic.Type.STRING; 064 } 065 066 /** 067 * Translates a string into an object of internal type <code>type</code>. 068 * The translation to int is undefined since strings are always converted 069 * to reals in arithmetic expressions. 070 * 071 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 072 */ 073 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 074 Type type) { 075 if (type == Type.Boolean) { 076 translateTo(classGen, methodGen, (BooleanType) type); 077 } 078 else if (type == Type.Real) { 079 translateTo(classGen, methodGen, (RealType) type); 080 } 081 else if (type == Type.Reference) { 082 translateTo(classGen, methodGen, (ReferenceType) type); 083 } 084 else { 085 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 086 toString(), type.toString()); 087 classGen.getParser().reportError(Constants.FATAL, err); 088 } 089 } 090 091 /** 092 * Translates a string into a synthesized boolean. 093 * 094 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 095 */ 096 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 097 BooleanType type) { 098 final InstructionList il = methodGen.getInstructionList(); 099 FlowList falsel = translateToDesynthesized(classGen, methodGen, type); 100 il.append(ICONST_1); 101 final BranchHandle truec = il.append(new GOTO(null)); 102 falsel.backPatch(il.append(ICONST_0)); 103 truec.setTarget(il.append(NOP)); 104 } 105 106 /** 107 * Translates a string into a real by calling stringToReal() from the 108 * basis library. 109 * 110 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 111 */ 112 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 113 RealType type) { 114 final ConstantPoolGen cpg = classGen.getConstantPool(); 115 final InstructionList il = methodGen.getInstructionList(); 116 il.append(new INVOKESTATIC(cpg.addMethodref(BASIS_LIBRARY_CLASS, 117 STRING_TO_REAL, 118 STRING_TO_REAL_SIG))); 119 } 120 121 /** 122 * Translates a string into a non-synthesized boolean. It does not push a 123 * 0 or a 1 but instead returns branchhandle list to be appended to the 124 * false list. 125 * 126 * @see org.apache.xalan.xsltc.compiler.util.Type#translateToDesynthesized 127 */ 128 public FlowList translateToDesynthesized(ClassGenerator classGen, 129 MethodGenerator methodGen, 130 BooleanType type) { 131 final ConstantPoolGen cpg = classGen.getConstantPool(); 132 final InstructionList il = methodGen.getInstructionList(); 133 134 il.append(new INVOKEVIRTUAL(cpg.addMethodref(STRING_CLASS, 135 "length", "()I"))); 136 return new FlowList(il.append(new IFEQ(null))); 137 } 138 139 /** 140 * Expects a string on the stack and pushes a boxed string. 141 * Strings are already boxed so the translation is just a NOP. 142 * 143 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 144 */ 145 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 146 ReferenceType type) { 147 methodGen.getInstructionList().append(NOP); 148 } 149 150 /** 151 * Translates a internal string into an external (Java) string. 152 * 153 * @see org.apache.xalan.xsltc.compiler.util.Type#translateFrom 154 */ 155 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 156 Class clazz) 157 { 158 // Is String <: clazz? I.e. clazz in { String, Object } 159 if (clazz.isAssignableFrom(java.lang.String.class)) { 160 methodGen.getInstructionList().append(NOP); 161 } 162 else { 163 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 164 toString(), clazz.getName()); 165 classGen.getParser().reportError(Constants.FATAL, err); 166 } 167 } 168 169 /** 170 * Translates an external (primitive) Java type into a string. 171 * 172 * @see org.apache.xalan.xsltc.compiler.util.Type#translateFrom 173 */ 174 public void translateFrom(ClassGenerator classGen, 175 MethodGenerator methodGen, Class clazz) 176 { 177 final ConstantPoolGen cpg = classGen.getConstantPool(); 178 final InstructionList il = methodGen.getInstructionList(); 179 180 if (clazz.getName().equals("java.lang.String")) { 181 // same internal representation, convert null to "" 182 il.append(DUP); 183 final BranchHandle ifNonNull = il.append(new IFNONNULL(null)); 184 il.append(POP); 185 il.append(new PUSH(cpg, "")); 186 ifNonNull.setTarget(il.append(NOP)); 187 } 188 else { 189 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 190 toString(), clazz.getName()); 191 classGen.getParser().reportError(Constants.FATAL, err); 192 } 193 } 194 195 /** 196 * Translates an object of this type to its boxed representation. 197 */ 198 public void translateBox(ClassGenerator classGen, 199 MethodGenerator methodGen) { 200 translateTo(classGen, methodGen, Type.Reference); 201 } 202 203 /** 204 * Translates an object of this type to its unboxed representation. 205 */ 206 public void translateUnBox(ClassGenerator classGen, 207 MethodGenerator methodGen) { 208 methodGen.getInstructionList().append(NOP); 209 } 210 211 /** 212 * Returns the class name of an internal type's external representation. 213 */ 214 public String getClassName() { 215 return(STRING_CLASS); 216 } 217 218 219 public Instruction LOAD(int slot) { 220 return new ALOAD(slot); 221 } 222 223 public Instruction STORE(int slot) { 224 return new ASTORE(slot); 225 } 226 }