1 /*
   2  * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  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 package com.sun.org.apache.xalan.internal.xsltc.compiler.util;
  22 
  23 import com.sun.org.apache.bcel.internal.generic.BranchHandle;
  24 import com.sun.org.apache.bcel.internal.generic.BranchInstruction;
  25 import com.sun.org.apache.bcel.internal.generic.CHECKCAST;
  26 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
  27 import com.sun.org.apache.bcel.internal.generic.GOTO;
  28 import com.sun.org.apache.bcel.internal.generic.IFEQ;
  29 import com.sun.org.apache.bcel.internal.generic.IFGE;
  30 import com.sun.org.apache.bcel.internal.generic.IFGT;
  31 import com.sun.org.apache.bcel.internal.generic.IFLE;
  32 import com.sun.org.apache.bcel.internal.generic.IFLT;
  33 import com.sun.org.apache.bcel.internal.generic.IF_ICMPGE;
  34 import com.sun.org.apache.bcel.internal.generic.IF_ICMPGT;
  35 import com.sun.org.apache.bcel.internal.generic.IF_ICMPLE;
  36 import com.sun.org.apache.bcel.internal.generic.IF_ICMPLT;
  37 import com.sun.org.apache.bcel.internal.generic.ILOAD;
  38 import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
  39 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
  40 import com.sun.org.apache.bcel.internal.generic.ISTORE;
  41 import com.sun.org.apache.bcel.internal.generic.Instruction;
  42 import com.sun.org.apache.bcel.internal.generic.InstructionList;
  43 import com.sun.org.apache.bcel.internal.generic.NEW;
  44 import com.sun.org.apache.bcel.internal.generic.PUSH;
  45 import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants;
  46 
  47 /**
  48  * @author Jacek Ambroziak
  49  * @author Santiago Pericas-Geertsen
  50  * @LastModified: Oct 2017
  51  */
  52 public final class BooleanType extends Type {
  53     protected BooleanType() {}
  54 
  55     public String toString() {
  56         return "boolean";
  57     }
  58 
  59     public boolean identicalTo(Type other) {
  60         return this == other;
  61     }
  62 
  63     public String toSignature() {
  64         return "Z";
  65     }
  66 
  67     public boolean isSimple() {
  68         return true;
  69     }
  70 
  71     public com.sun.org.apache.bcel.internal.generic.Type toJCType() {
  72         return com.sun.org.apache.bcel.internal.generic.Type.BOOLEAN;
  73     }
  74 
  75     /**
  76      * Translates a real into an object of internal type <code>type</code>. The
  77      * translation to int is undefined since booleans are always converted to
  78      * reals in arithmetic expressions.
  79      *
  80      * @see     com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
  81      */
  82     public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
  83                             Type type) {
  84         if (type == Type.String) {
  85             translateTo(classGen, methodGen, (StringType) type);
  86         }
  87         else if (type == Type.Real) {
  88             translateTo(classGen, methodGen, (RealType) type);
  89         }
  90         else if (type == Type.Reference) {
  91             translateTo(classGen, methodGen, (ReferenceType) type);
  92         }
  93         else {
  94             ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
  95                                         toString(), type.toString());
  96             classGen.getParser().reportError(Constants.FATAL, err);
  97         }
  98     }
  99 
 100     /**
 101      * Expects a boolean on the stack and pushes a string. If the value on the
 102      * stack is zero, then the string 'false' is pushed. Otherwise, the string
 103      * 'true' is pushed.
 104      *
 105      * @see     com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
 106      */
 107     public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
 108                             StringType type) {
 109         final ConstantPoolGen cpg = classGen.getConstantPool();
 110         final InstructionList il = methodGen.getInstructionList();
 111         final BranchHandle falsec = il.append(new IFEQ(null));
 112         il.append(new PUSH(cpg, "true"));
 113         final BranchHandle truec = il.append(new GOTO(null));
 114         falsec.setTarget(il.append(new PUSH(cpg, "false")));
 115         truec.setTarget(il.append(NOP));
 116     }
 117 
 118     /**
 119      * Expects a boolean on the stack and pushes a real. The value "true" is
 120      * converted to 1.0 and the value "false" to 0.0.
 121      *
 122      * @see     com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
 123      */
 124     public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
 125                             RealType type) {
 126         methodGen.getInstructionList().append(I2D);
 127     }
 128 
 129     /**
 130      * Expects a boolean on the stack and pushes a boxed boolean.
 131      * Boxed booleans are represented by an instance of
 132      * <code>java.lang.Boolean</code>.
 133      *
 134      * @see     com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
 135      */
 136     public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
 137                             ReferenceType type) {
 138         final ConstantPoolGen cpg = classGen.getConstantPool();
 139         final InstructionList il = methodGen.getInstructionList();
 140         il.append(new NEW(cpg.addClass(BOOLEAN_CLASS)));
 141         il.append(DUP_X1);
 142         il.append(SWAP);
 143         il.append(new INVOKESPECIAL(cpg.addMethodref(BOOLEAN_CLASS,
 144                                                      "<init>",
 145                                                      "(Z)V")));
 146     }
 147 
 148     /**
 149      * Translates an internal boolean into an external (Java) boolean.
 150      */
 151     public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
 152                             Class<?> clazz) {
 153         if (clazz == java.lang.Boolean.TYPE) {
 154             methodGen.getInstructionList().append(NOP);
 155         }
 156         // Is Boolean <: clazz? I.e. clazz in { Boolean, Object }
 157         else if (clazz.isAssignableFrom(java.lang.Boolean.class)) {
 158             translateTo(classGen, methodGen, Type.Reference);
 159         }
 160         else {
 161             ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
 162                                         toString(), clazz.getName());
 163             classGen.getParser().reportError(Constants.FATAL, err);
 164         }
 165     }
 166 
 167     /**
 168      * Translates an external (Java) boolean into internal boolean.
 169      */
 170     public void translateFrom(ClassGenerator classGen, MethodGenerator methodGen,
 171                               Class<?> clazz) {
 172         translateTo(classGen, methodGen, clazz);
 173     }
 174 
 175     /**
 176      * Translates an object of this type to its boxed representation.
 177      */
 178     public void translateBox(ClassGenerator classGen,
 179                              MethodGenerator methodGen) {
 180         translateTo(classGen, methodGen, Type.Reference);
 181     }
 182 
 183     /**
 184      * Translates an object of this type to its unboxed representation.
 185      */
 186     public void translateUnBox(ClassGenerator classGen,
 187                                MethodGenerator methodGen) {
 188         final ConstantPoolGen cpg = classGen.getConstantPool();
 189         final InstructionList il = methodGen.getInstructionList();
 190         il.append(new CHECKCAST(cpg.addClass(BOOLEAN_CLASS)));
 191         il.append(new INVOKEVIRTUAL(cpg.addMethodref(BOOLEAN_CLASS,
 192                                                      BOOLEAN_VALUE,
 193                                                      BOOLEAN_VALUE_SIG)));
 194     }
 195 
 196     public Instruction LOAD(int slot) {
 197         return new ILOAD(slot);
 198     }
 199 
 200     public Instruction STORE(int slot) {
 201         return new ISTORE(slot);
 202     }
 203 
 204     public BranchInstruction GT(boolean tozero) {
 205         return tozero ? (BranchInstruction) new IFGT(null) :
 206             (BranchInstruction) new IF_ICMPGT(null);
 207     }
 208 
 209     public BranchInstruction GE(boolean tozero) {
 210         return tozero ? (BranchInstruction) new IFGE(null) :
 211             (BranchInstruction) new IF_ICMPGE(null);
 212     }
 213 
 214     public BranchInstruction LT(boolean tozero) {
 215         return tozero ? (BranchInstruction) new IFLT(null) :
 216             (BranchInstruction) new IF_ICMPLT(null);
 217     }
 218 
 219     public BranchInstruction LE(boolean tozero) {
 220         return tozero ? (BranchInstruction) new IFLE(null) :
 221             (BranchInstruction) new IF_ICMPLE(null);
 222     }
 223 }