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