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: BooleanType.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.BranchHandle; 025 import org.apache.bcel.generic.BranchInstruction; 026 import org.apache.bcel.generic.CHECKCAST; 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.IFGE; 031 import org.apache.bcel.generic.IFGT; 032 import org.apache.bcel.generic.IFLE; 033 import org.apache.bcel.generic.IFLT; 034 import org.apache.bcel.generic.IF_ICMPGE; 035 import org.apache.bcel.generic.IF_ICMPGT; 036 import org.apache.bcel.generic.IF_ICMPLE; 037 import org.apache.bcel.generic.IF_ICMPLT; 038 import org.apache.bcel.generic.ILOAD; 039 import org.apache.bcel.generic.INVOKESPECIAL; 040 import org.apache.bcel.generic.INVOKEVIRTUAL; 041 import org.apache.bcel.generic.ISTORE; 042 import org.apache.bcel.generic.Instruction; 043 import org.apache.bcel.generic.InstructionList; 044 import org.apache.bcel.generic.NEW; 045 import org.apache.bcel.generic.PUSH; 046 import org.apache.xalan.xsltc.compiler.Constants; 047 048 /** 049 * @author Jacek Ambroziak 050 * @author Santiago Pericas-Geertsen 051 */ 052 public final class BooleanType extends Type { 053 protected BooleanType() {} 054 055 public String toString() { 056 return "boolean"; 057 } 058 059 public boolean identicalTo(Type other) { 060 return this == other; 061 } 062 063 public String toSignature() { 064 return "Z"; 065 } 066 067 public boolean isSimple() { 068 return true; 069 } 070 071 public org.apache.bcel.generic.Type toJCType() { 072 return org.apache.bcel.generic.Type.BOOLEAN; 073 } 074 075 /** 076 * Translates a real into an object of internal type <code>type</code>. The 077 * translation to int is undefined since booleans are always converted to 078 * reals in arithmetic expressions. 079 * 080 * @see org.apache.xalan.xsltc.compiler.util.Type#translateTo 081 */ 082 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 083 Type type) { 084 if (type == Type.String) { 085 translateTo(classGen, methodGen, (StringType) type); 086 } 087 else if (type == Type.Real) { 088 translateTo(classGen, methodGen, (RealType) type); 089 } 090 else if (type == Type.Reference) { 091 translateTo(classGen, methodGen, (ReferenceType) type); 092 } 093 else { 094 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 095 toString(), type.toString()); 096 classGen.getParser().reportError(Constants.FATAL, err); 097 } 098 } 099 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 org.apache.xalan.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 org.apache.xalan.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 org.apache.xalan.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 }