KickJava   Java API By Example, From Geeks To Geeks.

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


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: RelationalExpr.java,v 1.19 2004/02/16 22:24:28 minchau Exp $
18  */

19
20 package org.apache.xalan.xsltc.compiler;
21
22 import org.apache.bcel.generic.BranchInstruction;
23 import org.apache.bcel.generic.ConstantPoolGen;
24 import org.apache.bcel.generic.INVOKESTATIC;
25 import org.apache.bcel.generic.InstructionList;
26 import org.apache.bcel.generic.PUSH;
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.IntType;
31 import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
32 import org.apache.xalan.xsltc.compiler.util.MethodType;
33 import org.apache.xalan.xsltc.compiler.util.NodeSetType;
34 import org.apache.xalan.xsltc.compiler.util.NodeType;
35 import org.apache.xalan.xsltc.compiler.util.RealType;
36 import org.apache.xalan.xsltc.compiler.util.ReferenceType;
37 import org.apache.xalan.xsltc.compiler.util.ResultTreeType;
38 import org.apache.xalan.xsltc.compiler.util.Type;
39 import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
40 import org.apache.xalan.xsltc.runtime.Operators;
41
42 /**
43  * @author Jacek Ambroziak
44  * @author Santiago Pericas-Geertsen
45  */

46 final class RelationalExpr extends Expression implements Operators {
47     private int _op;
48     private Expression _left, _right;
49         
50     public RelationalExpr(int op, Expression left, Expression right) {
51     _op = op;
52     (_left = left).setParent(this);
53     (_right = right).setParent(this);
54     }
55
56     public void setParser(Parser parser) {
57     super.setParser(parser);
58     _left.setParser(parser);
59     _right.setParser(parser);
60     }
61
62     /**
63      * Returns true if this expressions contains a call to position(). This is
64      * needed for context changes in node steps containing multiple predicates.
65      */

66     public boolean hasPositionCall() {
67     if (_left.hasPositionCall()) return true;
68     if (_right.hasPositionCall()) return true;
69     return false;
70     }
71
72     /**
73      * Returns true if this expressions contains a call to last()
74      */

75     public boolean hasLastCall() {
76             return (_left.hasLastCall() || _right.hasLastCall());
77     }
78     
79     public boolean hasReferenceArgs() {
80     return _left.getType() instanceof ReferenceType ||
81         _right.getType() instanceof ReferenceType;
82     }
83
84     public boolean hasNodeArgs() {
85     return _left.getType() instanceof NodeType ||
86         _right.getType() instanceof NodeType;
87     }
88
89     public boolean hasNodeSetArgs() {
90     return _left.getType() instanceof NodeSetType ||
91         _right.getType() instanceof NodeSetType;
92     }
93
94     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
95     Type tleft = _left.typeCheck(stable);
96     Type tright = _right.typeCheck(stable);
97
98     //bug fix # 2838, cast to reals if both are result tree fragments
99
if (tleft instanceof ResultTreeType &&
100         tright instanceof ResultTreeType )
101     {
102         _right = new CastExpr(_right, Type.Real);
103         _left = new CastExpr(_left, Type.Real);
104         return _type = Type.Boolean;
105     }
106
107     // If one is of reference type, then convert the other too
108
if (hasReferenceArgs()) {
109         Type type = null;
110         Type typeL = null;
111         Type typeR = null;
112         if (tleft instanceof ReferenceType) {
113         if (_left instanceof VariableRefBase) {
114             VariableRefBase ref = (VariableRefBase)_left;
115             VariableBase var = ref.getVariable();
116             typeL = var.getType();
117         }
118         }
119         if (tright instanceof ReferenceType) {
120         if (_right instanceof VariableRefBase) {
121             VariableRefBase ref = (VariableRefBase)_right;
122             VariableBase var = ref.getVariable();
123             typeR = var.getType();
124         }
125         }
126         // bug fix # 2838
127
if (typeL == null)
128         type = typeR;
129         else if (typeR == null)
130         type = typeL;
131         else {
132         type = Type.Real;
133         }
134         if (type == null) type = Type.Real;
135
136         _right = new CastExpr(_right, type);
137             _left = new CastExpr(_left, type);
138         return _type = Type.Boolean;
139     }
140
141     if (hasNodeSetArgs()) {
142         // Ensure that the node-set is the left argument
143
if (tright instanceof NodeSetType) {
144         final Expression temp = _right; _right = _left; _left = temp;
145         _op = (_op == Operators.GT) ? Operators.LT :
146             (_op == Operators.LT) ? Operators.GT :
147             (_op == Operators.GE) ? Operators.LE : Operators.GE;
148         tright = _right.getType();
149         }
150
151         // Promote nodes to node sets
152
if (tright instanceof NodeType) {
153         _right = new CastExpr(_right, Type.NodeSet);
154         }
155         // Promote integer to doubles to have fewer compares
156
if (tright instanceof IntType) {
157         _right = new CastExpr(_right, Type.Real);
158         }
159         // Promote result-trees to strings
160
if (tright instanceof ResultTreeType) {
161         _right = new CastExpr(_right, Type.String);
162         }
163         return _type = Type.Boolean;
164     }
165
166     // In the node-boolean case, convert node to boolean first
167
if (hasNodeArgs()) {
168         if (tleft instanceof BooleanType) {
169         _right = new CastExpr(_right, Type.Boolean);
170         tright = Type.Boolean;
171         }
172         if (tright instanceof BooleanType) {
173         _left = new CastExpr(_left, Type.Boolean);
174         tleft = Type.Boolean;
175         }
176     }
177
178     // Lookup the table of primops to find the best match
179
MethodType ptype = lookupPrimop(stable, Operators.names[_op],
180                     new MethodType(Type.Void,
181                                tleft, tright));
182
183     if (ptype != null) {
184         Type arg1 = (Type) ptype.argsType().elementAt(0);
185         if (!arg1.identicalTo(tleft)) {
186         _left = new CastExpr(_left, arg1);
187         }
188         Type arg2 = (Type) ptype.argsType().elementAt(1);
189         if (!arg2.identicalTo(tright)) {
190         _right = new CastExpr(_right, arg1);
191         }
192         return _type = ptype.resultType();
193     }
194     throw new TypeCheckError(this);
195     }
196
197     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
198     if (hasNodeSetArgs() || hasReferenceArgs()) {
199         final ConstantPoolGen cpg = classGen.getConstantPool();
200         final InstructionList il = methodGen.getInstructionList();
201
202         // Call compare() from the BasisLibrary
203
_left.translate(classGen, methodGen);
204         _left.startIterator(classGen, methodGen);
205         _right.translate(classGen, methodGen);
206         _right.startIterator(classGen, methodGen);
207
208         il.append(new PUSH(cpg, _op));
209         il.append(methodGen.loadDOM());
210
211         int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "compare",
212                      "("
213                      + _left.getType().toSignature()
214                      + _right.getType().toSignature()
215                      + "I"
216                      + DOM_INTF_SIG
217                      + ")Z");
218         il.append(new INVOKESTATIC(index));
219     }
220     else {
221         translateDesynthesized(classGen, methodGen);
222         synthesize(classGen, methodGen);
223     }
224     }
225
226     public void translateDesynthesized(ClassGenerator classGen,
227                        MethodGenerator methodGen) {
228     if (hasNodeSetArgs() || hasReferenceArgs()) {
229         translate(classGen, methodGen);
230         desynthesize(classGen, methodGen);
231     }
232     else {
233         BranchInstruction bi = null;
234         final InstructionList il = methodGen.getInstructionList();
235
236         _left.translate(classGen, methodGen);
237         _right.translate(classGen, methodGen);
238
239         // TODO: optimize if one of the args is 0
240

241         boolean tozero = false;
242         Type tleft = _left.getType();
243
244         if (tleft instanceof RealType) {
245         il.append(tleft.CMP(_op == LT || _op == LE));
246         tleft = Type.Int;
247         tozero = true;
248         }
249
250         switch (_op) {
251         case LT:
252         bi = tleft.GE(tozero);
253         break;
254         
255         case GT:
256         bi = tleft.LE(tozero);
257         break;
258         
259         case LE:
260         bi = tleft.GT(tozero);
261         break;
262         
263         case GE:
264         bi = tleft.LT(tozero);
265         break;
266         
267         default:
268         ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_RELAT_OP_ERR,this);
269         getParser().reportError(Constants.FATAL, msg);
270         }
271
272         _falseList.add(il.append(bi)); // must be backpatched
273
}
274     }
275
276     public String JavaDoc toString() {
277     return Operators.names[_op] + '(' + _left + ", " + _right + ')';
278     }
279 }
280
Popular Tags