KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > xsltc > compiler > CastExpr


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: CastExpr.java,v 1.21 2004/02/16 22:24:29 minchau Exp $
18  */

19
20 package org.apache.xalan.xsltc.compiler;
21
22 import org.apache.bcel.generic.ConstantPoolGen;
23 import org.apache.bcel.generic.IF_ICMPNE;
24 import org.apache.bcel.generic.INVOKEINTERFACE;
25 import org.apache.bcel.generic.InstructionList;
26 import org.apache.bcel.generic.SIPUSH;
27 import org.apache.xalan.xsltc.compiler.util.BooleanType;
28 import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
29 import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
30 import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
31 import org.apache.xalan.xsltc.compiler.util.MultiHashtable;
32 import org.apache.xalan.xsltc.compiler.util.NodeType;
33 import org.apache.xalan.xsltc.compiler.util.ResultTreeType;
34 import org.apache.xalan.xsltc.compiler.util.Type;
35 import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
36 import org.apache.xalan.xsltc.dom.Axis;
37
38 /**
39  * @author Jacek Ambroziak
40  * @author Santiago Pericas-Geertsen
41  * @author Morten Jorgensen
42  * @author Erwin Bolwidt <ejb@klomp.org>
43  */

44 final class CastExpr extends Expression {
45     private final Expression _left;
46
47     /**
48      * Legal conversions between internal types.
49      */

50     static private MultiHashtable InternalTypeMap = new MultiHashtable();
51
52     static {
53     // Possible type conversions between internal types
54
InternalTypeMap.put(Type.Boolean, Type.Boolean);
55     InternalTypeMap.put(Type.Boolean, Type.Real);
56     InternalTypeMap.put(Type.Boolean, Type.String);
57     InternalTypeMap.put(Type.Boolean, Type.Reference);
58         InternalTypeMap.put(Type.Boolean, Type.Object);
59
60     InternalTypeMap.put(Type.Real, Type.Real);
61     InternalTypeMap.put(Type.Real, Type.Int);
62     InternalTypeMap.put(Type.Real, Type.Boolean);
63     InternalTypeMap.put(Type.Real, Type.String);
64     InternalTypeMap.put(Type.Real, Type.Reference);
65         InternalTypeMap.put(Type.Real, Type.Object);
66
67     InternalTypeMap.put(Type.Int, Type.Int);
68     InternalTypeMap.put(Type.Int, Type.Real);
69     InternalTypeMap.put(Type.Int, Type.Boolean);
70     InternalTypeMap.put(Type.Int, Type.String);
71     InternalTypeMap.put(Type.Int, Type.Reference);
72         InternalTypeMap.put(Type.Int, Type.Object);
73
74     InternalTypeMap.put(Type.String, Type.String);
75     InternalTypeMap.put(Type.String, Type.Boolean);
76     InternalTypeMap.put(Type.String, Type.Real);
77     InternalTypeMap.put(Type.String, Type.Reference);
78         InternalTypeMap.put(Type.String, Type.Object);
79         InternalTypeMap.put(Type.String, Type.ObjectString);
80
81     InternalTypeMap.put(Type.NodeSet, Type.NodeSet);
82     InternalTypeMap.put(Type.NodeSet, Type.Boolean);
83     InternalTypeMap.put(Type.NodeSet, Type.Real);
84     InternalTypeMap.put(Type.NodeSet, Type.String);
85     InternalTypeMap.put(Type.NodeSet, Type.Node);
86     InternalTypeMap.put(Type.NodeSet, Type.Reference);
87     InternalTypeMap.put(Type.NodeSet, Type.Object);
88
89     InternalTypeMap.put(Type.Node, Type.Node);
90     InternalTypeMap.put(Type.Node, Type.Boolean);
91     InternalTypeMap.put(Type.Node, Type.Real);
92     InternalTypeMap.put(Type.Node, Type.String);
93     InternalTypeMap.put(Type.Node, Type.NodeSet);
94     InternalTypeMap.put(Type.Node, Type.Reference);
95     InternalTypeMap.put(Type.Node, Type.Object);
96
97     InternalTypeMap.put(Type.ResultTree, Type.ResultTree);
98     InternalTypeMap.put(Type.ResultTree, Type.Boolean);
99     InternalTypeMap.put(Type.ResultTree, Type.Real);
100     InternalTypeMap.put(Type.ResultTree, Type.String);
101     InternalTypeMap.put(Type.ResultTree, Type.NodeSet);
102     InternalTypeMap.put(Type.ResultTree, Type.Reference);
103     InternalTypeMap.put(Type.ResultTree, Type.Object);
104
105     InternalTypeMap.put(Type.Reference, Type.Reference);
106     InternalTypeMap.put(Type.Reference, Type.Boolean);
107     InternalTypeMap.put(Type.Reference, Type.Int);
108     InternalTypeMap.put(Type.Reference, Type.Real);
109     InternalTypeMap.put(Type.Reference, Type.String);
110     InternalTypeMap.put(Type.Reference, Type.Node);
111     InternalTypeMap.put(Type.Reference, Type.NodeSet);
112     InternalTypeMap.put(Type.Reference, Type.ResultTree);
113     InternalTypeMap.put(Type.Reference, Type.Object);
114
115     InternalTypeMap.put(Type.Object, Type.String);
116     InternalTypeMap.put(Type.ObjectString, Type.String);
117
118     InternalTypeMap.put(Type.Void, Type.String);
119     }
120
121     private boolean _typeTest = false;
122
123     /**
124      * Construct a cast expression and check that the conversion is
125      * valid by calling typeCheck().
126      */

127     public CastExpr(Expression left, Type type) throws TypeCheckError {
128     _left = left;
129     _type = type; // use inherited field
130

131     if ((_left instanceof Step) && (_type == Type.Boolean)) {
132         Step step = (Step)_left;
133         if ((step.getAxis() == Axis.SELF) && (step.getNodeType() != -1))
134         _typeTest = true;
135     }
136     
137     // check if conversion is valid
138
setParser(left.getParser());
139     setParent(left.getParent());
140     left.setParent(this);
141     typeCheck(left.getParser().getSymbolTable());
142     }
143         
144     public Expression getExpr() {
145     return _left;
146     }
147
148     /**
149      * Returns true if this expressions contains a call to position(). This is
150      * needed for context changes in node steps containing multiple predicates.
151      */

152     public boolean hasPositionCall() {
153     return(_left.hasPositionCall());
154     }
155
156     public boolean hasLastCall() {
157     return(_left.hasLastCall());
158     }
159
160     public String JavaDoc toString() {
161     return "cast(" + _left + ", " + _type + ")";
162     }
163
164     /**
165      * Type checking a cast expression amounts to verifying that the
166      * type conversion is legal. Cast expressions are created during
167      * type checking, but typeCheck() is usually not called on them.
168      * As a result, this method is called from the constructor.
169      */

170     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
171     Type tleft = _left.getType();
172     if (tleft == null) {
173         tleft = _left.typeCheck(stable);
174     }
175     if (tleft instanceof NodeType) {
176         tleft = Type.Node; // multiple instances
177
}
178     else if (tleft instanceof ResultTreeType) {
179         tleft = Type.ResultTree; // multiple instances
180
}
181     if (InternalTypeMap.maps(tleft, _type) != null) {
182         return _type;
183     }
184     // throw new TypeCheckError(this);
185
throw new TypeCheckError(new ErrorMsg(
186         ErrorMsg.DATA_CONVERSION_ERR, tleft.toString(), _type.toString()));
187     }
188
189     public void translateDesynthesized(ClassGenerator classGen,
190                        MethodGenerator methodGen) {
191     FlowList fl;
192     final Type ltype = _left.getType();
193
194     // This is a special case for the self:: axis. Instead of letting
195
// the Step object create and iterator that we cast back to a single
196
// node, we simply ask the DOM for the node type.
197
if (_typeTest) {
198         final ConstantPoolGen cpg = classGen.getConstantPool();
199         final InstructionList il = methodGen.getInstructionList();
200
201         final int idx = cpg.addInterfaceMethodref(DOM_INTF,
202                               "getExpandedTypeID",
203                                                       "(I)I");
204         il.append(new SIPUSH((short)((Step)_left).getNodeType()));
205         il.append(methodGen.loadDOM());
206         il.append(methodGen.loadContextNode());
207         il.append(new INVOKEINTERFACE(idx, 2));
208         _falseList.add(il.append(new IF_ICMPNE(null)));
209     }
210     else {
211
212         _left.translate(classGen, methodGen);
213         if (_type != ltype) {
214         _left.startIterator(classGen, methodGen);
215         if (_type instanceof BooleanType) {
216             fl = ltype.translateToDesynthesized(classGen, methodGen,
217                             _type);
218             if (fl != null) {
219             _falseList.append(fl);
220             }
221         }
222         else {
223             ltype.translateTo(classGen, methodGen, _type);
224         }
225         }
226     }
227     }
228
229     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
230     final Type ltype = _left.getType();
231     _left.translate(classGen, methodGen);
232     if (_type.identicalTo(ltype) == false) {
233         _left.startIterator(classGen, methodGen);
234         ltype.translateTo(classGen, methodGen, _type);
235     }
236     }
237 }
238
Popular Tags