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    }