1 46 package org.codehaus.groovy.ast.expr; 47 48 import java.io.OutputStream ; 49 import java.io.Writer ; 50 import java.math.BigDecimal ; 51 import java.math.BigInteger ; 52 import java.util.Collection ; 53 import java.util.Date ; 54 import java.util.List ; 55 import java.util.Map ; 56 import java.util.regex.Matcher ; 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 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 getTypeClass() { 87 typeClass = resolveThisType(operation); 88 return typeClass; 89 } 90 91 public boolean isDynamic() { 92 return false; } 94 95 private Class resolveThisType(Token operation) { 96 switch (operation.getType()) { 97 case Types.EQUAL : 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 .class; 115 case Types.COMPARE_TO : 116 return Integer .class; 117 case Types.PLUS : 118 case Types.PLUS_EQUAL :{ 119 if (leftExpression.getTypeClass() == String .class && rightExpression.getTypeClass() == String .class) { 120 return String .class; 121 } 122 else if (leftExpression.getTypeClass() == GString.class && 123 (rightExpression.getTypeClass() == GString.class || rightExpression.getTypeClass() == String .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 .class && Number .class.isAssignableFrom(rightExpression.getTypeClass()) ) { 130 return Date .class; 131 } 132 else if (leftExpression.getTypeClass() != null && Collection .class.isAssignableFrom(leftExpression.getTypeClass() )) { 133 return List .class; 134 } 135 else { 136 return null; 137 } 138 } 139 case Types.MINUS : 140 case Types.MINUS_EQUAL :{ 141 if (leftExpression.getTypeClass() == String .class) { 142 return String .class; 143 } else if (leftExpression instanceof GStringExpression && isNumber(rightExpression.getType())) { 144 return String .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 .class.isAssignableFrom(leftExpression.getTypeClass() )) { 149 return List .class; 150 } 151 else if (leftExpression.getTypeClass() == Date .class && Number .class.isAssignableFrom(rightExpression.getTypeClass()) ) { 152 return Date .class; 153 } 154 else { 155 return null; 156 } 157 } 158 case Types.MULTIPLY : 159 case Types.MULTIPLY_EQUAL : { 160 if (leftExpression.getTypeClass() == String .class && isNumber(rightExpression.getType())) { 161 return String .class; 162 } else if (leftExpression instanceof GStringExpression && isNumber(rightExpression.getType())) { 163 return String .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 .class.isAssignableFrom(leftExpression.getTypeClass() )) { 168 return List .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 .class.isAssignableFrom(leftExpression.getTypeClass() )) { 188 return Collection .class; 189 } 190 else if (leftExpression.getTypeClass() != null && OutputStream .class.isAssignableFrom(leftExpression.getTypeClass())) { 191 return Writer .class; 192 } 193 else if (leftExpression.getTypeClass() != null && StringBuffer .class.isAssignableFrom(leftExpression.getTypeClass())) { 194 return Writer .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 .class; 205 case Types.LEFT_SQUARE_BRACKET : 206 Class cls = leftExpression.getTypeClass(); 207 if (cls != null) { 208 if (cls.isArray()) { 209 Class elemType = cls.getComponentType(); 210 return elemType; 212 } 213 else if (leftExpression instanceof ListExpression) { 214 Class elemType = ((ListExpression)leftExpression).getComponentTypeClass(); 215 return elemType; 217 } 218 else if (leftExpression instanceof MapExpression) { 219 return Object .class; 220 } 221 else if (List .class.isAssignableFrom(cls)) { 222 return (Object .class); 223 } 224 else if (Map .class.isAssignableFrom(cls)) { 225 return (Object .class); 226 } 227 } 228 break; 229 } 230 return null; 231 } 232 233 private static boolean isNumber(String 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 getObjectClassForNumber(String type) { 259 if (type.equals("boolean") || type.equals("java.lang.Boolean")) { 260 return Boolean .class; 261 } 262 else if (type.equals("short") || type.equals("java.lang.Short")) { 263 return Short .class; 264 } 265 else if (type.equals("int") || type.equals("java.lang.Integer")) { 266 return Integer .class; 267 } 268 else if (type.equals("char") || type.equals("java.lang.Character")) { 269 return Integer .class; 270 } 271 else if (type.equals("long") || type.equals("java.lang.Long")) { 272 return Long .class; 273 } 274 else if (type.equals("float") || type.equals("java.lang.Float")) { 275 return Float .class; 276 } 277 else if (type.equals("double") || type.equals("java.lang.Double")) { 278 return Double .class; 279 } 280 else if (type.equals("java.math.BigInteger")) { 281 return BigInteger .class; 282 } 283 else if (type.equals("java.math.BigDecimal")) { 284 return BigDecimal .class; 285 } 286 else { 287 return null; 288 } 289 } 290 291 private static boolean isFloatingPoint(Class cls) { 292 return cls == Double .class || cls == Float .class; 293 } 294 295 private static boolean isInteger(Class cls) { 296 return cls == Integer .class || cls == Byte .class || cls == Short .class || cls == Character .class; 297 } 298 299 private static boolean isLong(Class cls) { 300 return cls == Long .class; 301 } 302 303 private static boolean isBigDecimal(Class cls) { 304 return cls == BigDecimal .class; 305 } 306 307 private static boolean isBigInteger(Class cls) { 308 return cls == BigInteger .class; 309 } 310 311 private static Class chooseWiderNumberType(String lefts, String rights) { 312 Class left = getObjectClassForNumber(lefts); 313 Class right = getObjectClassForNumber(rights); 314 if (isFloatingPoint(left) || isFloatingPoint(right)) { 315 return Double .class; 316 } 317 else if (isBigDecimal(left) || isBigDecimal(right)) { 318 return BigDecimal .class; 319 } 320 else if (isBigInteger(left) || isBigInteger(right)) { 321 return BigInteger .class; 322 } 323 else if (isLong(left) || isLong(right)){ 324 return Long .class; 325 } 326 return Integer .class; 327 328 } 330 public String 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 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 374 375 public static BinaryExpression newAssignmentExpression( String 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 387 388 public static BinaryExpression newInitializationExpression( String 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 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 |