View Javadoc
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: StringType.java,v 1.2.4.1 2005/09/05 11:35:57 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.ALOAD;
27  import com.sun.org.apache.bcel.internal.generic.ASTORE;
28  import com.sun.org.apache.bcel.internal.generic.BranchHandle;
29  import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
30  import com.sun.org.apache.bcel.internal.generic.GOTO;
31  import com.sun.org.apache.bcel.internal.generic.IFEQ;
32  import com.sun.org.apache.bcel.internal.generic.IFNONNULL;
33  import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC;
34  import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
35  import com.sun.org.apache.bcel.internal.generic.Instruction;
36  import com.sun.org.apache.bcel.internal.generic.InstructionList;
37  import com.sun.org.apache.bcel.internal.generic.PUSH;
38  import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants;
39  import com.sun.org.apache.xalan.internal.xsltc.compiler.FlowList;
40  
41  /**
42   * @author Jacek Ambroziak
43   * @author Santiago Pericas-Geertsen
44   */
45  public class StringType extends Type {
46      protected StringType() {}
47  
48      public String toString() {
49          return "string";
50      }
51  
52      public boolean identicalTo(Type other) {
53          return this == other;
54      }
55  
56      public String toSignature() {
57          return "Ljava/lang/String;";
58      }
59  
60      public boolean isSimple() {
61          return true;
62      }
63  
64      public com.sun.org.apache.bcel.internal.generic.Type toJCType() {
65          return com.sun.org.apache.bcel.internal.generic.Type.STRING;
66      }
67  
68      /**
69       * Translates a string into an object of internal type <code>type</code>.
70       * The translation to int is undefined since strings are always converted
71       * to reals in arithmetic expressions.
72       *
73       * @see     com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
74       */
75      public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
76                              Type type) {
77          if (type == Type.Boolean) {
78              translateTo(classGen, methodGen, (BooleanType) type);
79          }
80          else if (type == Type.Real) {
81              translateTo(classGen, methodGen, (RealType) type);
82          }
83          else if (type == Type.Reference) {
84              translateTo(classGen, methodGen, (ReferenceType) type);
85          }
86          else if (type == Type.ObjectString) {
87              // NOP -> same representation
88          }
89          else {
90              ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
91                                          toString(), type.toString());
92              classGen.getParser().reportError(Constants.FATAL, err);
93          }
94      }
95  
96      /**
97       * Translates a string into a synthesized boolean.
98       *
99       * @see     com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
100      */
101     public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
102                             BooleanType type) {
103         final InstructionList il = methodGen.getInstructionList();
104         FlowList falsel = translateToDesynthesized(classGen, methodGen, type);
105         il.append(ICONST_1);
106         final BranchHandle truec = il.append(new GOTO(null));
107         falsel.backPatch(il.append(ICONST_0));
108         truec.setTarget(il.append(NOP));
109     }
110 
111     /**
112      * Translates a string into a real by calling stringToReal() from the
113      * basis library.
114      *
115      * @see     com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
116      */
117     public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
118                             RealType type) {
119         final ConstantPoolGen cpg = classGen.getConstantPool();
120         final InstructionList il = methodGen.getInstructionList();
121         il.append(new INVOKESTATIC(cpg.addMethodref(BASIS_LIBRARY_CLASS,
122                                                     STRING_TO_REAL,
123                                                     STRING_TO_REAL_SIG)));
124     }
125 
126     /**
127      * Translates a string into a non-synthesized boolean. It does not push a
128      * 0 or a 1 but instead returns branchhandle list to be appended to the
129      * false list.
130      *
131      * @see     com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateToDesynthesized
132      */
133     public FlowList translateToDesynthesized(ClassGenerator classGen,
134                                              MethodGenerator methodGen,
135                                              BooleanType type) {
136         final ConstantPoolGen cpg = classGen.getConstantPool();
137         final InstructionList il = methodGen.getInstructionList();
138 
139         il.append(new INVOKEVIRTUAL(cpg.addMethodref(STRING_CLASS,
140                                                      "length", "()I")));
141         return new FlowList(il.append(new IFEQ(null)));
142     }
143 
144     /**
145      * Expects a string on the stack and pushes a boxed string.
146      * Strings are already boxed so the translation is just a NOP.
147      *
148      * @see     com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
149      */
150     public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
151                             ReferenceType type) {
152         methodGen.getInstructionList().append(NOP);
153     }
154 
155     /**
156      * Translates a internal string into an external (Java) string.
157      *
158      * @see     com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateFrom
159      */
160     public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
161                             Class clazz)
162     {
163         // Is String <: clazz? I.e. clazz in { String, Object }
164         if (clazz.isAssignableFrom(java.lang.String.class)) {
165             methodGen.getInstructionList().append(NOP);
166         }
167         else {
168             ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
169                                         toString(), clazz.getName());
170             classGen.getParser().reportError(Constants.FATAL, err);
171         }
172     }
173 
174     /**
175      * Translates an external (primitive) Java type into a string.
176      *
177      * @see     com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateFrom
178      */
179     public void translateFrom(ClassGenerator classGen,
180         MethodGenerator methodGen, Class clazz)
181     {
182         final ConstantPoolGen cpg = classGen.getConstantPool();
183         final InstructionList il = methodGen.getInstructionList();
184 
185         if (clazz.getName().equals("java.lang.String")) {
186             // same internal representation, convert null to ""
187             il.append(DUP);
188             final BranchHandle ifNonNull = il.append(new IFNONNULL(null));
189             il.append(POP);
190             il.append(new PUSH(cpg, ""));
191             ifNonNull.setTarget(il.append(NOP));
192         }
193         else {
194             ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
195                                         toString(), clazz.getName());
196             classGen.getParser().reportError(Constants.FATAL, err);
197         }
198     }
199 
200     /**
201      * Translates an object of this type to its boxed representation.
202      */
203     public void translateBox(ClassGenerator classGen,
204                              MethodGenerator methodGen) {
205         translateTo(classGen, methodGen, Type.Reference);
206     }
207 
208     /**
209      * Translates an object of this type to its unboxed representation.
210      */
211     public void translateUnBox(ClassGenerator classGen,
212                                MethodGenerator methodGen) {
213         methodGen.getInstructionList().append(NOP);
214     }
215 
216     /**
217      * Returns the class name of an internal type's external representation.
218      */
219     public String getClassName() {
220         return(STRING_CLASS);
221     }
222 
223 
224     public Instruction LOAD(int slot) {
225         return new ALOAD(slot);
226     }
227 
228     public Instruction STORE(int slot) {
229         return new ASTORE(slot);
230     }
231 }