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: Type.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.BranchInstruction;
025    import org.apache.bcel.generic.Instruction;
026    import org.apache.xalan.xsltc.compiler.Constants;
027    import org.apache.xalan.xsltc.compiler.FlowList;
028    import org.apache.xalan.xsltc.compiler.NodeTest;
029    
030    /**
031     * @author Jacek Ambroziak
032     * @author Santiago Pericas-Geertsen
033     * @author Morten Jorgensen
034     */
035    public abstract class Type implements Constants {
036        public static final Type Int        = new IntType();
037        public static final Type Real       = new RealType();
038        public static final Type Boolean    = new BooleanType();
039        public static final Type NodeSet    = new NodeSetType();
040        public static final Type String     = new StringType();
041        public static final Type ResultTree = new ResultTreeType();
042        public static final Type Reference  = new ReferenceType();
043        public static final Type Void       = new VoidType();    
044        public static final Type Object     = new ObjectType(java.lang.Object.class);
045    
046        public static final Type Node       = new NodeType(NodeTest.ANODE);
047        public static final Type Root       = new NodeType(NodeTest.ROOT);
048        public static final Type Element    = new NodeType(NodeTest.ELEMENT);
049        public static final Type Attribute  = new NodeType(NodeTest.ATTRIBUTE);
050        public static final Type Text       = new NodeType(NodeTest.TEXT);
051        public static final Type Comment    = new NodeType(NodeTest.COMMENT);
052        public static final Type Processing_Instruction = new NodeType(NodeTest.PI);
053    
054        /**
055         * Factory method to instantiate object types. Returns a pre-defined
056         * instance for "java.lang.Object" and "java.lang.String".
057         */
058        public static Type newObjectType(String javaClassName) {
059            if (javaClassName == "java.lang.Object") {
060                return Type.Object;
061            }
062            else if (javaClassName == "java.lang.String") {
063                return Type.String;
064            } 
065            else {
066                return new ObjectType(javaClassName);
067            }
068        }
069        
070       /**
071         * Factory method to instantiate object types. Returns a pre-defined
072         * instance for java.lang.Object.class and java.lang.String.class.
073         */
074        public static Type newObjectType(Class clazz) {
075            if (clazz == java.lang.Object.class) {
076                return Type.Object;
077            }
078            else if (clazz == java.lang.String.class) {
079                return Type.String;
080            }
081            else {
082                return new ObjectType(clazz);
083            }
084        }
085        
086        /**
087         * Returns a string representation of this type.    
088         */
089        public abstract String toString();
090    
091        /**
092         * Returns true if this and other are identical types.
093         */
094        public abstract boolean identicalTo(Type other);
095    
096        /**
097         * Returns true if this type is a numeric type. Redefined in NumberType.
098         */
099        public boolean isNumber() {
100            return false;
101        }
102    
103        /**
104         * Returns true if this type has no object representaion. Redefined in
105         * ResultTreeType.
106         */
107        public boolean implementedAsMethod() {
108            return false;
109        }
110    
111        /**
112         * Returns true if this type is a simple type. Redefined in NumberType,
113         * BooleanType and StringType.
114         */
115        public boolean isSimple() {
116            return false;
117        }
118    
119        public abstract org.apache.bcel.generic.Type toJCType();
120    
121        /**
122         * Returns the distance between two types. This measure is used to select
123         * overloaded functions/operators. This method is typically redefined by
124         * the subclasses.
125         */
126        public int distanceTo(Type type) {
127            return type == this ? 0 : Integer.MAX_VALUE;
128        }
129    
130        /**
131         * Returns the signature of an internal type's external representation.
132         */
133        public abstract String toSignature();
134    
135        /**
136         * Translates an object of this type to an object of type
137         * <code>type</code>. 
138         * Expects an object of the former type and pushes an object of the latter.
139         */
140        public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
141                                Type type) {
142            ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
143                                        toString(), type.toString());
144            classGen.getParser().reportError(Constants.FATAL, err);
145        }
146    
147        /**
148         * Translates object of this type to an object of type <code>type</code>. 
149         * Expects an object of the former type and pushes an object of the latter
150         * if not boolean. If type <code>type</code> is boolean then a branchhandle
151         * list (to be appended to the false list) is returned.
152         */
153        public FlowList translateToDesynthesized(ClassGenerator classGen, 
154                                                 MethodGenerator methodGen, 
155                                                 Type type) {
156            FlowList fl = null;
157            if (type == Type.Boolean) {
158                fl = translateToDesynthesized(classGen, methodGen,
159                                              (BooleanType)type);
160            }
161            else {
162                translateTo(classGen, methodGen, type);
163            }
164            return fl;
165        }
166    
167        /**
168         * Translates an object of this type to an non-synthesized boolean. It
169         * does not push a 0 or a 1 but instead returns branchhandle list to be
170         * appended to the false list.
171         */ 
172        public FlowList translateToDesynthesized(ClassGenerator classGen, 
173                                                 MethodGenerator methodGen, 
174                                                 BooleanType type) {
175            ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
176                                        toString(), type.toString());
177            classGen.getParser().reportError(Constants.FATAL, err);
178            return null;
179        }
180    
181        /**
182         * Translates an object of this type to the external (Java) type denoted
183         * by <code>clazz</code>. This method is used to translate parameters 
184         * when external functions are called.
185         */ 
186        public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
187                                Class clazz) {
188            ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
189                                        toString(), clazz.getClass().toString());
190            classGen.getParser().reportError(Constants.FATAL, err);
191        }
192    
193        /**
194         * Translates an external (Java) type denoted by <code>clazz</code> to 
195         * an object of this type. This method is used to translate return values 
196         * when external functions are called.
197         */ 
198        public void translateFrom(ClassGenerator classGen, MethodGenerator methodGen,
199                                  Class clazz) {
200            ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
201                                        clazz.getClass().toString(), toString());
202            classGen.getParser().reportError(Constants.FATAL, err);
203        }
204    
205        /**
206         * Translates an object of this type to its boxed representation.
207         */ 
208        public void translateBox(ClassGenerator classGen,
209                                 MethodGenerator methodGen) {
210            ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
211                                        toString(), "["+toString()+"]");
212            classGen.getParser().reportError(Constants.FATAL, err);
213        }
214    
215        /**
216         * Translates an object of this type to its unboxed representation.
217         */ 
218        public void translateUnBox(ClassGenerator classGen,
219                                   MethodGenerator methodGen) {
220            ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
221                                        "["+toString()+"]", toString());
222            classGen.getParser().reportError(Constants.FATAL, err);
223        }
224    
225        /**
226         * Returns the class name of an internal type's external representation.
227         */
228        public String getClassName() {
229            return(EMPTYSTRING);
230        }
231    
232        public Instruction ADD() {
233            return null;            // should never be called
234        }
235    
236        public Instruction SUB() {
237            return null;            // should never be called
238        }
239    
240        public Instruction MUL() {
241            return null;            // should never be called
242        }
243    
244        public Instruction DIV() {
245            return null;            // should never be called
246        }
247    
248        public Instruction REM() {
249            return null;            // should never be called
250        }
251    
252        public Instruction NEG() {
253            return null;            // should never be called
254        }
255    
256        public Instruction LOAD(int slot) {
257            return null;            // should never be called
258        }
259            
260        public Instruction STORE(int slot) {
261            return null;            // should never be called
262        }
263    
264        public Instruction POP() {
265            return POP;
266        }
267    
268        public BranchInstruction GT(boolean tozero) {
269            return null;            // should never be called
270        }
271    
272        public BranchInstruction GE(boolean tozero) {
273            return null;            // should never be called
274        }
275    
276        public BranchInstruction LT(boolean tozero) {
277            return null;            // should never be called
278        }
279    
280        public BranchInstruction LE(boolean tozero) {
281            return null;            // should never be called
282        }
283    
284        public Instruction CMP(boolean less) {
285            return null;            // should never be called
286        }
287            
288        public Instruction DUP() {
289            return DUP;     // default
290        }
291    }