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: IntType.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.INVOKESTATIC;
041    import org.apache.bcel.generic.INVOKEVIRTUAL;
042    import org.apache.bcel.generic.ISTORE;
043    import org.apache.bcel.generic.Instruction;
044    import org.apache.bcel.generic.InstructionConstants;
045    import org.apache.bcel.generic.InstructionList;
046    import org.apache.bcel.generic.NEW;
047    import org.apache.xalan.xsltc.compiler.Constants;
048    import org.apache.xalan.xsltc.compiler.FlowList;
049    
050    /**
051     * @author Jacek Ambroziak
052     * @author Santiago Pericas-Geertsen
053     */
054    public final class IntType extends NumberType {
055        protected IntType() {}
056    
057        public String toString() {
058            return "int";
059        }
060    
061        public boolean identicalTo(Type other) {
062            return this == other;
063        }
064    
065        public String toSignature() {
066            return "I";
067        }
068    
069        public org.apache.bcel.generic.Type toJCType() {
070            return org.apache.bcel.generic.Type.INT;
071        }
072    
073        /**
074         * @see     org.apache.xalan.xsltc.compiler.util.Type#distanceTo
075         */
076        public int distanceTo(Type type) {
077            if (type == this) {
078                return 0;
079            }
080            else if (type == Type.Real) {
081                return 1;
082            }
083            else
084                return Integer.MAX_VALUE;
085        }
086        
087        /**
088         * Translates an integer into an object of internal type <code>type</code>.
089         *
090         * @see     org.apache.xalan.xsltc.compiler.util.Type#translateTo
091         */
092        public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
093                                final Type type) {
094            if (type == Type.Real) {
095                translateTo(classGen, methodGen, (RealType) type);
096            }
097            else if (type == Type.String) {
098                translateTo(classGen, methodGen, (StringType) type);
099            }
100            else if (type == Type.Boolean) {
101                translateTo(classGen, methodGen, (BooleanType) type);
102            }
103            else if (type == Type.Reference) {
104                translateTo(classGen, methodGen, (ReferenceType) type);
105            }
106            else {
107                ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
108                                            toString(), type.toString());
109                classGen.getParser().reportError(Constants.FATAL, err);
110            }
111        }
112    
113        /**
114         * Expects an integer on the stack and pushes a real.
115         *
116         * @see     org.apache.xalan.xsltc.compiler.util.Type#translateTo
117         */
118        public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
119                                RealType type) {
120            methodGen.getInstructionList().append(I2D);
121        }
122    
123        /**
124         * Expects an integer on the stack and pushes its string value by calling
125         * <code>Integer.toString(int i)</code>.
126         *
127         * @see     org.apache.xalan.xsltc.compiler.util.Type#translateTo
128         */
129        public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
130                                StringType type) {
131            final ConstantPoolGen cpg = classGen.getConstantPool();
132            final InstructionList il = methodGen.getInstructionList();
133            il.append(new INVOKESTATIC(cpg.addMethodref(INTEGER_CLASS,
134                                                        "toString",
135                                                        "(I)" + STRING_SIG)));
136        }
137    
138        /**
139         * Expects an integer on the stack and pushes a 0 if its value is 0 and
140         * a 1 otherwise.
141         *
142         * @see     org.apache.xalan.xsltc.compiler.util.Type#translateTo
143         */
144        public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
145                                BooleanType type) {
146            final InstructionList il = methodGen.getInstructionList();
147            final BranchHandle falsec = il.append(new IFEQ(null));
148            il.append(ICONST_1);
149            final BranchHandle truec = il.append(new GOTO(null));
150            falsec.setTarget(il.append(ICONST_0));
151            truec.setTarget(il.append(NOP));
152        }
153    
154        /**
155         * Expects an integer on the stack and translates it to a non-synthesized
156         * boolean. It does not push a 0 or a 1 but instead returns branchhandle 
157         * list to be appended to the false list.
158         *
159         * @see     org.apache.xalan.xsltc.compiler.util.Type#translateToDesynthesized
160         */
161        public FlowList translateToDesynthesized(ClassGenerator classGen, 
162                                                 MethodGenerator methodGen, 
163                                                 BooleanType type) {
164            final InstructionList il = methodGen.getInstructionList();
165            return new FlowList(il.append(new IFEQ(null)));
166        }
167    
168        /**
169         * Expects an integer on the stack and pushes a boxed integer.
170         * Boxed integers are represented by an instance of
171         * <code>java.lang.Integer</code>.
172         *
173         * @see     org.apache.xalan.xsltc.compiler.util.Type#translateTo
174         */
175        public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
176                                ReferenceType type) {
177            final ConstantPoolGen cpg = classGen.getConstantPool();
178            final InstructionList il = methodGen.getInstructionList();
179            il.append(new NEW(cpg.addClass(INTEGER_CLASS)));
180            il.append(DUP_X1);
181            il.append(SWAP);
182            il.append(new INVOKESPECIAL(cpg.addMethodref(INTEGER_CLASS,
183                                                         "<init>", "(I)V")));
184        }
185    
186        /**
187         * Translates an integer into the Java type denoted by <code>clazz</code>. 
188         * Expects an integer on the stack and pushes a number of the appropriate
189         * type after coercion.
190         */
191        public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
192                                Class clazz) {
193            final InstructionList il = methodGen.getInstructionList();
194            if (clazz == Character.TYPE) {
195                il.append(I2C);
196            }
197            else if (clazz == Byte.TYPE) {
198                il.append(I2B);
199            }
200            else if (clazz == Short.TYPE) {
201                il.append(I2S);
202            }
203            else if (clazz == Integer.TYPE) {
204                il.append(NOP);
205            }
206            else if (clazz == Long.TYPE) {
207                il.append(I2L);
208            }
209            else if (clazz == Float.TYPE) {
210                il.append(I2F);
211            }
212            else if (clazz == Double.TYPE) {
213                il.append(I2D);
214            }
215             // Is Double <: clazz? I.e. clazz in { Double, Number, Object }
216           else if (clazz.isAssignableFrom(java.lang.Double.class)) {
217               il.append(I2D);
218               Type.Real.translateTo(classGen, methodGen, Type.Reference);
219            }
220            else {
221                ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
222                                            toString(), clazz.getName());
223                classGen.getParser().reportError(Constants.FATAL, err);
224            }
225        }
226    
227        /**
228         * Translates an object of this type to its boxed representation.
229         */ 
230        public void translateBox(ClassGenerator classGen,
231                                 MethodGenerator methodGen) {
232            translateTo(classGen, methodGen, Type.Reference);
233        }
234    
235        /**
236         * Translates an object of this type to its unboxed representation.
237         */ 
238        public void translateUnBox(ClassGenerator classGen,
239                                   MethodGenerator methodGen) {
240            final ConstantPoolGen cpg = classGen.getConstantPool();
241            final InstructionList il = methodGen.getInstructionList();
242            il.append(new CHECKCAST(cpg.addClass(INTEGER_CLASS)));
243            final int index = cpg.addMethodref(INTEGER_CLASS,
244                                               INT_VALUE, 
245                                               INT_VALUE_SIG);
246            il.append(new INVOKEVIRTUAL(index));
247        }
248    
249        public Instruction ADD() {
250            return InstructionConstants.IADD;
251        }
252    
253        public Instruction SUB() {
254            return InstructionConstants.ISUB;
255        }
256    
257        public Instruction MUL() {
258            return InstructionConstants.IMUL;
259        }
260    
261        public Instruction DIV() {
262            return InstructionConstants.IDIV;
263        }
264    
265        public Instruction REM() {
266            return InstructionConstants.IREM;
267        }
268    
269        public Instruction NEG() {
270            return InstructionConstants.INEG;
271        }
272    
273        public Instruction LOAD(int slot) {
274            return new ILOAD(slot);
275        }
276            
277        public Instruction STORE(int slot) {
278            return new ISTORE(slot);
279        }
280    
281        public BranchInstruction GT(boolean tozero) {
282            return tozero ? (BranchInstruction) new IFGT(null) : 
283                (BranchInstruction) new IF_ICMPGT(null);
284        }
285    
286        public BranchInstruction GE(boolean tozero) {
287            return tozero ? (BranchInstruction) new IFGE(null) : 
288                (BranchInstruction) new IF_ICMPGE(null);
289        }
290    
291        public BranchInstruction LT(boolean tozero) {
292            return tozero ? (BranchInstruction) new IFLT(null) : 
293                (BranchInstruction) new IF_ICMPLT(null);
294        }
295    
296        public BranchInstruction LE(boolean tozero) {
297            return tozero ? (BranchInstruction) new IFLE(null) : 
298                (BranchInstruction) new IF_ICMPLE(null);
299        }
300    }