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
22package com.sun.org.apache.xalan.internal.xsltc.compiler.util;
23
24import com.sun.org.apache.bcel.internal.generic.BranchHandle;
25import com.sun.org.apache.bcel.internal.generic.BranchInstruction;
26import com.sun.org.apache.bcel.internal.generic.CHECKCAST;
27import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
28import com.sun.org.apache.bcel.internal.generic.GOTO;
29import com.sun.org.apache.bcel.internal.generic.IFEQ;
30import com.sun.org.apache.bcel.internal.generic.IFGE;
31import com.sun.org.apache.bcel.internal.generic.IFGT;
32import com.sun.org.apache.bcel.internal.generic.IFLE;
33import com.sun.org.apache.bcel.internal.generic.IFLT;
34import com.sun.org.apache.bcel.internal.generic.IF_ICMPGE;
35import com.sun.org.apache.bcel.internal.generic.IF_ICMPGT;
36import com.sun.org.apache.bcel.internal.generic.IF_ICMPLE;
37import com.sun.org.apache.bcel.internal.generic.IF_ICMPLT;
38import com.sun.org.apache.bcel.internal.generic.ILOAD;
39import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
40import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
41import com.sun.org.apache.bcel.internal.generic.ISTORE;
42import com.sun.org.apache.bcel.internal.generic.Instruction;
43import com.sun.org.apache.bcel.internal.generic.InstructionList;
44import com.sun.org.apache.bcel.internal.generic.NEW;
45import com.sun.org.apache.bcel.internal.generic.PUSH;
46import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants;
47
48/**
49 * @author Jacek Ambroziak
50 * @author Santiago Pericas-Geertsen
51 */
52public 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}
224