KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > groovy > ast > expr > BinaryExpression


1 /*
2  $Id: BinaryExpression.java,v 1.6 2004/07/10 03:31:37 bran Exp $
3
4  Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
5
6  Redistribution and use of this software and associated documentation
7  ("Software"), with or without modification, are permitted provided
8  that the following conditions are met:
9
10  1. Redistributions of source code must retain copyright
11     statements and notices. Redistributions must also contain a
12     copy of this document.
13
14  2. Redistributions in binary form must reproduce the
15     above copyright notice, this list of conditions and the
16     following disclaimer in the documentation and/or other
17     materials provided with the distribution.
18
19  3. The name "groovy" must not be used to endorse or promote
20     products derived from this Software without prior written
21     permission of The Codehaus. For written permission,
22     please contact info@codehaus.org.
23
24  4. Products derived from this Software may not be called "groovy"
25     nor may "groovy" appear in their names without prior written
26     permission of The Codehaus. "groovy" is a registered
27     trademark of The Codehaus.
28
29  5. Due credit should be given to The Codehaus -
30     http://groovy.codehaus.org/
31
32  THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
33  ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
34  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
35  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
36  THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
37  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
43  OF THE POSSIBILITY OF SUCH DAMAGE.
44
45  */

46 package org.codehaus.groovy.ast.expr;
47
48 import java.io.OutputStream JavaDoc;
49 import java.io.Writer JavaDoc;
50 import java.math.BigDecimal JavaDoc;
51 import java.math.BigInteger JavaDoc;
52 import java.util.Collection JavaDoc;
53 import java.util.Date JavaDoc;
54 import java.util.List JavaDoc;
55 import java.util.Map JavaDoc;
56 import java.util.regex.Matcher JavaDoc;
57
58 import org.codehaus.groovy.ast.GroovyCodeVisitor;
59 import org.codehaus.groovy.ast.Type;
60 import org.codehaus.groovy.classgen.AsmClassGenerator2;
61 import org.codehaus.groovy.syntax.Token;
62 import org.codehaus.groovy.syntax.Types;
63 import groovy.lang.GString;
64
65 /**
66  * Represents two expressions and an operation
67  *
68  * @author <a HREF="mailto:james@coredevelopers.net">James Strachan</a>
69  * @version $Revision: 1.6 $
70  */

71 public class BinaryExpression extends Expression {
72     
73     private Expression leftExpression;
74     private Expression rightExpression;
75     private Token operation;
76     
77     public BinaryExpression(Expression leftExpression,
78                             Token operation,
79                             Expression rightExpression) {
80         this.leftExpression = leftExpression;
81         this.operation = operation;
82         this.rightExpression = rightExpression;
83
84     }
85
86     public Class JavaDoc getTypeClass() {
87         typeClass = resolveThisType(operation);
88         return typeClass;
89     }
90
91     public boolean isDynamic() {
92         return false; //To change body of implemented methods use File | Settings | File Templates.
93
}
94
95     private Class JavaDoc resolveThisType(Token operation) {
96         switch (operation.getType()) {
97             case Types.EQUAL : // = assignment
98
if (!leftExpression.isDynamic())
99                     return leftExpression.getTypeClass();
100                 else
101                     return rightExpression.getTypeClass();
102             case Types.COMPARE_IDENTICAL :
103             case Types.COMPARE_EQUAL :
104             case Types.COMPARE_NOT_EQUAL :
105             case Types.COMPARE_GREATER_THAN :
106             case Types.COMPARE_GREATER_THAN_EQUAL :
107             case Types.COMPARE_LESS_THAN :
108             case Types.COMPARE_LESS_THAN_EQUAL :
109             case Types.KEYWORD_INSTANCEOF :
110             case Types.MATCH_REGEX :
111                 return boolean.class;
112             case Types.LOGICAL_AND :
113             case Types.LOGICAL_OR :
114                 return Boolean JavaDoc.class;
115             case Types.COMPARE_TO :
116                 return Integer JavaDoc.class;
117             case Types.PLUS :
118             case Types.PLUS_EQUAL :{
119                 if (leftExpression.getTypeClass() == String JavaDoc.class && rightExpression.getTypeClass() == String JavaDoc.class) {
120                     return String JavaDoc.class;
121                 }
122                 else if (leftExpression.getTypeClass() == GString.class &&
123                         (rightExpression.getTypeClass() == GString.class || rightExpression.getTypeClass() == String JavaDoc.class)) {
124                     return GString.class;
125                 }
126                 else if (isNumber(leftExpression.getType()) && isNumber(rightExpression.getType())) {
127                     return chooseWiderNumberType(leftExpression.getType(), rightExpression.getType());
128                 }
129                 else if (leftExpression.getTypeClass() == Date JavaDoc.class && Number JavaDoc.class.isAssignableFrom(rightExpression.getTypeClass()) ) {
130                     return Date JavaDoc.class;
131                 }
132                 else if (leftExpression.getTypeClass() != null && Collection JavaDoc.class.isAssignableFrom(leftExpression.getTypeClass() )) {
133                     return List JavaDoc.class;
134                 }
135                 else {
136                     return null;
137                 }
138             }
139             case Types.MINUS :
140             case Types.MINUS_EQUAL :{
141                 if (leftExpression.getTypeClass() == String JavaDoc.class) {
142                     return String JavaDoc.class;
143                 } else if (leftExpression instanceof GStringExpression && isNumber(rightExpression.getType())) {
144                     return String JavaDoc.class;
145                 } else if (isNumber(leftExpression.getType()) && isNumber(rightExpression.getType())) {
146                     return chooseWiderNumberType(leftExpression.getType(), rightExpression.getType());
147                 }
148                 else if (leftExpression.getTypeClass() != null && List JavaDoc.class.isAssignableFrom(leftExpression.getTypeClass() )) {
149                     return List JavaDoc.class;
150                 }
151                 else if (leftExpression.getTypeClass() == Date JavaDoc.class && Number JavaDoc.class.isAssignableFrom(rightExpression.getTypeClass()) ) {
152                     return Date JavaDoc.class;
153                 }
154                 else {
155                     return null;
156                 }
157             }
158             case Types.MULTIPLY :
159             case Types.MULTIPLY_EQUAL : {
160                 if (leftExpression.getTypeClass() == String JavaDoc.class && isNumber(rightExpression.getType())) {
161                     return String JavaDoc.class;
162                 } else if (leftExpression instanceof GStringExpression && isNumber(rightExpression.getType())) {
163                     return String JavaDoc.class;
164                 } else if (isNumber(leftExpression.getType()) && isNumber(rightExpression.getType())) {
165                     return chooseWiderNumberType(leftExpression.getType(), rightExpression.getType());
166                 }
167                 else if (leftExpression.getTypeClass() != null && Collection JavaDoc.class.isAssignableFrom(leftExpression.getTypeClass() )) {
168                     return List JavaDoc.class;
169                 }
170                 else {
171                     return null;
172                 }
173             }
174
175             case Types.DIVIDE :
176             case Types.DIVIDE_EQUAL :
177             case Types.MOD :
178             case Types.MOD_EQUAL :
179                 if (isNumber(leftExpression.getType()) && isNumber(rightExpression.getType())) {
180                     return chooseWiderNumberType(leftExpression.getType(), rightExpression.getType());
181                 }
182                 return null;
183             case Types.LEFT_SHIFT :
184                 if (isNumber(leftExpression.getType()) && isNumber(rightExpression.getType())) {
185                     return leftExpression.getTypeClass();
186                 }
187                 else if (leftExpression.getTypeClass() != null && Collection JavaDoc.class.isAssignableFrom(leftExpression.getTypeClass() )) {
188                     return Collection JavaDoc.class;
189                 }
190                 else if (leftExpression.getTypeClass() != null && OutputStream JavaDoc.class.isAssignableFrom(leftExpression.getTypeClass())) {
191                     return Writer JavaDoc.class;
192                 }
193                 else if (leftExpression.getTypeClass() != null && StringBuffer JavaDoc.class.isAssignableFrom(leftExpression.getTypeClass())) {
194                     return Writer JavaDoc.class;
195                 }
196                 return null;
197             case Types.RIGHT_SHIFT :
198             case Types.RIGHT_SHIFT_UNSIGNED :
199                 if (isNumber(leftExpression.getType()) && isNumber(rightExpression.getType())) {
200                     return leftExpression.getTypeClass();
201                 }
202                 return null;
203             case Types.FIND_REGEX :
204                 return Matcher JavaDoc.class;
205             case Types.LEFT_SQUARE_BRACKET :
206                 Class JavaDoc cls = leftExpression.getTypeClass();
207                 if (cls != null) {
208                     if (cls.isArray()) {
209                         Class JavaDoc elemType = cls.getComponentType();
210                         //setTypeClass(elemType);
211
return elemType;
212                     }
213                     else if (leftExpression instanceof ListExpression) {
214                         Class JavaDoc elemType = ((ListExpression)leftExpression).getComponentTypeClass();
215                         //setTypeClass(elemType);
216
return elemType;
217                     }
218                     else if (leftExpression instanceof MapExpression) {
219                         return Object JavaDoc.class;
220                     }
221                     else if (List JavaDoc.class.isAssignableFrom(cls)) {
222                         return (Object JavaDoc.class);
223                     }
224                     else if (Map JavaDoc.class.isAssignableFrom(cls)) {
225                         return (Object JavaDoc.class);
226                     }
227                 }
228                 break;
229         }
230         return null;
231     }
232
233     private static boolean isNumber(String JavaDoc type) {
234         if (type!= null) {
235             if ( type.equals("int") ||
236                     type.equals("short") ||
237                     type.equals("byte") ||
238                     type.equals("char") ||
239                     type.equals("float") ||
240                     type.equals("long") ||
241                     type.equals("double") ||
242                     type.equals("java.lang.Short") ||
243                     type.equals("java.lang.Byte") ||
244                     type.equals("java.lang.Character") ||
245                     type.equals("java.lang.Integer") ||
246                     type.equals("java.lang.Float") ||
247                     type.equals("java.lang.Long") ||
248                     type.equals("java.lang.Double") ||
249                     type.equals("java.math.BigInteger") ||
250                     type.equals("java.math.BigDecimal"))
251             {
252                 return true;
253             }
254         }
255         return false;
256     }
257
258     private static Class JavaDoc getObjectClassForNumber(String JavaDoc type) {
259         if (type.equals("boolean") || type.equals("java.lang.Boolean")) {
260             return Boolean JavaDoc.class;
261         }
262         else if (type.equals("short") || type.equals("java.lang.Short")) {
263             return Short JavaDoc.class;
264         }
265         else if (type.equals("int") || type.equals("java.lang.Integer")) {
266                     return Integer JavaDoc.class;
267         }
268         else if (type.equals("char") || type.equals("java.lang.Character")) {
269                     return Integer JavaDoc.class;
270         }
271         else if (type.equals("long") || type.equals("java.lang.Long")) {
272             return Long JavaDoc.class;
273         }
274         else if (type.equals("float") || type.equals("java.lang.Float")) {
275             return Float JavaDoc.class;
276         }
277         else if (type.equals("double") || type.equals("java.lang.Double")) {
278             return Double JavaDoc.class;
279         }
280         else if (type.equals("java.math.BigInteger")) {
281             return BigInteger JavaDoc.class;
282         }
283         else if (type.equals("java.math.BigDecimal")) {
284             return BigDecimal JavaDoc.class;
285         }
286         else {
287             return null;
288         }
289     }
290
291     private static boolean isFloatingPoint(Class JavaDoc cls) {
292         return cls == Double JavaDoc.class || cls == Float JavaDoc.class;
293     }
294
295     private static boolean isInteger(Class JavaDoc cls) {
296         return cls == Integer JavaDoc.class || cls == Byte JavaDoc.class || cls == Short JavaDoc.class || cls == Character JavaDoc.class;
297     }
298
299     private static boolean isLong(Class JavaDoc cls) {
300         return cls == Long JavaDoc.class;
301     }
302
303     private static boolean isBigDecimal(Class JavaDoc cls) {
304         return cls == BigDecimal JavaDoc.class;
305     }
306
307     private static boolean isBigInteger(Class JavaDoc cls) {
308         return cls == BigInteger JavaDoc.class;
309     }
310
311     private static Class JavaDoc chooseWiderNumberType(String JavaDoc lefts, String JavaDoc rights) {
312         Class JavaDoc left = getObjectClassForNumber(lefts);
313         Class JavaDoc right = getObjectClassForNumber(rights);
314         if (isFloatingPoint(left) || isFloatingPoint(right)) {
315             return Double JavaDoc.class;
316         }
317         else if (isBigDecimal(left) || isBigDecimal(right)) {
318             return BigDecimal JavaDoc.class;
319         }
320         else if (isBigInteger(left) || isBigInteger(right)) {
321             return BigInteger JavaDoc.class;
322         }
323         else if (isLong(left) || isLong(right)){
324             return Long JavaDoc.class;
325         }
326         return Integer JavaDoc.class;
327
328         // see NumberMath for full Groovy math promotion
329
}
330     public String JavaDoc toString() {
331         return super.toString() +"[" + leftExpression + operation + rightExpression + "]";
332     }
333
334     public void visit(GroovyCodeVisitor visitor) {
335         visitor.visitBinaryExpression(this);
336     }
337
338     public Expression transformExpression(ExpressionTransformer transformer) {
339         return new BinaryExpression(transformer.transform(leftExpression), operation, transformer.transform(rightExpression));
340     }
341
342     public Expression getLeftExpression() {
343         return leftExpression;
344     }
345
346     public void setLeftExpression(Expression leftExpression) {
347         this.leftExpression = leftExpression;
348     }
349
350     public void setRightExpression(Expression rightExpression) {
351         this.rightExpression = rightExpression;
352     }
353
354     public Token getOperation() {
355         return operation;
356     }
357
358     public Expression getRightExpression() {
359         return rightExpression;
360     }
361
362     public String JavaDoc getText() {
363         if (operation.getType() == Types.LEFT_SQUARE_BRACKET) {
364             return leftExpression.getText() + "[" + rightExpression.getText() + "]";
365         }
366         return "(" + leftExpression.getText() + " " + operation.getText() + " " + rightExpression.getText() + ")";
367     }
368     
369     
370    /**
371     * Creates an assignment expression in which the specified expression
372     * is written into the specified variable name.
373     */

374     
375     public static BinaryExpression newAssignmentExpression( String JavaDoc variable, Expression rhs ) {
376         VariableExpression lhs = new VariableExpression( variable );
377         Token operator = Token.newPlaceholder( Types.ASSIGN );
378     
379         return new BinaryExpression( lhs, operator, rhs );
380     }
381
382
383     /**
384      * Creates variable initialization expression in which the specified expression
385      * is written into the specified variable name.
386      */

387      
388      public static BinaryExpression newInitializationExpression( String JavaDoc variable, Type type, Expression rhs ) {
389         VariableExpression lhs = new VariableExpression( variable );
390      
391         if( type != null ) {
392             lhs.setType( type.getName() );
393         }
394      
395         Token operator = Token.newPlaceholder( Types.ASSIGN );
396      
397         return new BinaryExpression( lhs, operator, rhs );
398      }
399
400     protected void resolveType(AsmClassGenerator2 resolver) {
401         leftExpression.resolve(resolver);
402         rightExpression.resolve(resolver);
403         Class JavaDoc cls = resolveThisType(operation);
404         if (cls != null) {
405             setTypeClass(cls);
406         }
407         else {
408              setResolveFailed(true);
409             setFailure("unknown. the right expression may have not been resolved");
410         }
411     }
412 }
413
Popular Tags