1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * $Id: StringType.java,v 1.12 2004/02/16 22:26:45 minchau Exp $
  18. */
  19. package com.sun.org.apache.xalan.internal.xsltc.compiler.util;
  20. import com.sun.org.apache.bcel.internal.generic.ALOAD;
  21. import com.sun.org.apache.bcel.internal.generic.ASTORE;
  22. import com.sun.org.apache.bcel.internal.generic.BranchHandle;
  23. import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
  24. import com.sun.org.apache.bcel.internal.generic.GOTO;
  25. import com.sun.org.apache.bcel.internal.generic.IFEQ;
  26. import com.sun.org.apache.bcel.internal.generic.IFNONNULL;
  27. import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC;
  28. import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
  29. import com.sun.org.apache.bcel.internal.generic.Instruction;
  30. import com.sun.org.apache.bcel.internal.generic.InstructionList;
  31. import com.sun.org.apache.bcel.internal.generic.PUSH;
  32. import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants;
  33. import com.sun.org.apache.xalan.internal.xsltc.compiler.FlowList;
  34. /**
  35. * @author Jacek Ambroziak
  36. * @author Santiago Pericas-Geertsen
  37. */
  38. public class StringType extends Type {
  39. protected StringType() {}
  40. public String toString() {
  41. return "string";
  42. }
  43. public boolean identicalTo(Type other) {
  44. return this == other;
  45. }
  46. public String toSignature() {
  47. return "Ljava/lang/String;";
  48. }
  49. public boolean isSimple() {
  50. return true;
  51. }
  52. public com.sun.org.apache.bcel.internal.generic.Type toJCType() {
  53. return com.sun.org.apache.bcel.internal.generic.Type.STRING;
  54. }
  55. /**
  56. * Translates a string into an object of internal type <code>type</code>.
  57. * The translation to int is undefined since strings are always converted
  58. * to reals in arithmetic expressions.
  59. *
  60. * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
  61. */
  62. public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
  63. Type type) {
  64. if (type == Type.Boolean) {
  65. translateTo(classGen, methodGen, (BooleanType) type);
  66. }
  67. else if (type == Type.Real) {
  68. translateTo(classGen, methodGen, (RealType) type);
  69. }
  70. else if (type == Type.Reference) {
  71. translateTo(classGen, methodGen, (ReferenceType) type);
  72. }
  73. else if (type == Type.ObjectString) {
  74. // NOP -> same representation
  75. }
  76. else {
  77. ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
  78. toString(), type.toString());
  79. classGen.getParser().reportError(Constants.FATAL, err);
  80. }
  81. }
  82. /**
  83. * Translates a string into a synthesized boolean.
  84. *
  85. * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
  86. */
  87. public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
  88. BooleanType type) {
  89. final InstructionList il = methodGen.getInstructionList();
  90. FlowList falsel = translateToDesynthesized(classGen, methodGen, type);
  91. il.append(ICONST_1);
  92. final BranchHandle truec = il.append(new GOTO(null));
  93. falsel.backPatch(il.append(ICONST_0));
  94. truec.setTarget(il.append(NOP));
  95. }
  96. /**
  97. * Translates a string into a real by calling stringToReal() from the
  98. * basis library.
  99. *
  100. * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
  101. */
  102. public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
  103. RealType type) {
  104. final ConstantPoolGen cpg = classGen.getConstantPool();
  105. final InstructionList il = methodGen.getInstructionList();
  106. il.append(new INVOKESTATIC(cpg.addMethodref(BASIS_LIBRARY_CLASS,
  107. STRING_TO_REAL,
  108. STRING_TO_REAL_SIG)));
  109. }
  110. /**
  111. * Translates a string into a non-synthesized boolean. It does not push a
  112. * 0 or a 1 but instead returns branchhandle list to be appended to the
  113. * false list.
  114. *
  115. * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateToDesynthesized
  116. */
  117. public FlowList translateToDesynthesized(ClassGenerator classGen,
  118. MethodGenerator methodGen,
  119. BooleanType type) {
  120. final ConstantPoolGen cpg = classGen.getConstantPool();
  121. final InstructionList il = methodGen.getInstructionList();
  122. il.append(new INVOKEVIRTUAL(cpg.addMethodref(STRING_CLASS,
  123. "length", "()I")));
  124. return new FlowList(il.append(new IFEQ(null)));
  125. }
  126. /**
  127. * Expects a string on the stack and pushes a boxed string.
  128. * Strings are already boxed so the translation is just a NOP.
  129. *
  130. * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
  131. */
  132. public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
  133. ReferenceType type) {
  134. methodGen.getInstructionList().append(NOP);
  135. }
  136. /**
  137. * Translates a internal string into an external (Java) string.
  138. *
  139. * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateFrom
  140. */
  141. public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
  142. Class clazz)
  143. {
  144. // Is String <: clazz? I.e. clazz in { String, Object }
  145. if (clazz.isAssignableFrom(java.lang.String.class)) {
  146. methodGen.getInstructionList().append(NOP);
  147. }
  148. else {
  149. ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
  150. toString(), clazz.getName());
  151. classGen.getParser().reportError(Constants.FATAL, err);
  152. }
  153. }
  154. /**
  155. * Translates an external (primitive) Java type into a string.
  156. *
  157. * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateFrom
  158. */
  159. public void translateFrom(ClassGenerator classGen,
  160. MethodGenerator methodGen, Class clazz)
  161. {
  162. final ConstantPoolGen cpg = classGen.getConstantPool();
  163. final InstructionList il = methodGen.getInstructionList();
  164. if (clazz.getName().equals("java.lang.String")) {
  165. // same internal representation, convert null to ""
  166. il.append(DUP);
  167. final BranchHandle ifNonNull = il.append(new IFNONNULL(null));
  168. il.append(POP);
  169. il.append(new PUSH(cpg, ""));
  170. ifNonNull.setTarget(il.append(NOP));
  171. }
  172. else {
  173. ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
  174. toString(), clazz.getName());
  175. classGen.getParser().reportError(Constants.FATAL, err);
  176. }
  177. }
  178. /**
  179. * Translates an object of this type to its boxed representation.
  180. */
  181. public void translateBox(ClassGenerator classGen,
  182. MethodGenerator methodGen) {
  183. translateTo(classGen, methodGen, Type.Reference);
  184. }
  185. /**
  186. * Translates an object of this type to its unboxed representation.
  187. */
  188. public void translateUnBox(ClassGenerator classGen,
  189. MethodGenerator methodGen) {
  190. methodGen.getInstructionList().append(NOP);
  191. }
  192. /**
  193. * Returns the class name of an internal type's external representation.
  194. */
  195. public String getClassName() {
  196. return(STRING_CLASS);
  197. }
  198. public Instruction LOAD(int slot) {
  199. return new ALOAD(slot);
  200. }
  201. public Instruction STORE(int slot) {
  202. return new ASTORE(slot);
  203. }
  204. }