1 package polyglot.ext.jl.ast; 2 3 import polyglot.ast.*; 4 import polyglot.util.*; 5 import polyglot.visit.*; 6 import polyglot.types.*; 7 8 import java.util.*; 9 10 14 public class Binary_c extends Expr_c implements Binary 15 { 16 protected Expr left; 17 protected Operator op; 18 protected Expr right; 19 protected Precedence precedence; 20 21 public Binary_c(Position pos, Expr left, Operator op, Expr right) { 22 super(pos); 23 this.left = left; 24 this.op = op; 25 this.right = right; 26 this.precedence = op.precedence(); 27 } 28 29 30 public Expr left() { 31 return this.left; 32 } 33 34 35 public Binary left(Expr left) { 36 Binary_c n = (Binary_c) copy(); 37 n.left = left; 38 return n; 39 } 40 41 42 public Operator operator() { 43 return this.op; 44 } 45 46 47 public Binary operator(Operator op) { 48 Binary_c n = (Binary_c) copy(); 49 n.op = op; 50 return n; 51 } 52 53 54 public Expr right() { 55 return this.right; 56 } 57 58 59 public Binary right(Expr right) { 60 Binary_c n = (Binary_c) copy(); 61 n.right = right; 62 return n; 63 } 64 65 66 public Precedence precedence() { 67 return this.precedence; 68 } 69 70 public Binary precedence(Precedence precedence) { 71 Binary_c n = (Binary_c) copy(); 72 n.precedence = precedence; 73 return n; 74 } 75 76 77 protected Binary_c reconstruct(Expr left, Expr right) { 78 if (left != this.left || right != this.right) { 79 Binary_c n = (Binary_c) copy(); 80 n.left = left; 81 n.right = right; 82 return n; 83 } 84 85 return this; 86 } 87 88 89 public Node visitChildren(NodeVisitor v) { 90 Expr left = (Expr) visitChild(this.left, v); 91 Expr right = (Expr) visitChild(this.right, v); 92 return reconstruct(left, right); 93 } 94 95 public boolean isConstant() { 96 return left.isConstant() && right.isConstant(); 97 } 98 99 public Object constantValue() { 100 Object lv = left.constantValue(); 101 Object rv = right.constantValue(); 102 103 if (! isConstant()) { 104 return null; 105 } 106 107 if (op == ADD && (lv instanceof String || rv instanceof String )) { 108 if (lv == null) lv = "null"; 110 if (rv == null) rv = "null"; 111 return lv.toString() + rv.toString(); 112 } 113 114 if (op == EQ && (lv instanceof String && rv instanceof String )) { 115 return Boolean.valueOf(((String ) lv).intern() == ((String ) rv).intern()); 116 } 117 118 if (op == NE && (lv instanceof String && rv instanceof String )) { 119 return Boolean.valueOf(((String ) lv).intern() != ((String ) rv).intern()); 120 } 121 122 if (lv instanceof Character ) { 124 lv = new Integer (((Character ) lv).charValue()); 125 } 126 127 if (rv instanceof Character ) { 128 rv = new Integer (((Character ) rv).charValue()); 129 } 130 131 try { 132 if (lv instanceof Number && rv instanceof Number ) { 133 if (lv instanceof Double || rv instanceof Double ) { 134 double l = ((Number ) lv).doubleValue(); 135 double r = ((Number ) rv).doubleValue(); 136 if (op == ADD) return new Double (l + r); 137 if (op == SUB) return new Double (l - r); 138 if (op == MUL) return new Double (l * r); 139 if (op == DIV) return new Double (l / r); 140 if (op == MOD) return new Double (l % r); 141 if (op == EQ) return Boolean.valueOf(l == r); 142 if (op == NE) return Boolean.valueOf(l != r); 143 if (op == LT) return Boolean.valueOf(l < r); 144 if (op == LE) return Boolean.valueOf(l <= r); 145 if (op == GE) return Boolean.valueOf(l >= r); 146 if (op == GT) return Boolean.valueOf(l > r); 147 return null; 148 } 149 150 if (lv instanceof Float || rv instanceof Float ) { 151 float l = ((Number ) lv).floatValue(); 152 float r = ((Number ) rv).floatValue(); 153 if (op == ADD) return new Float (l + r); 154 if (op == SUB) return new Float (l - r); 155 if (op == MUL) return new Float (l * r); 156 if (op == DIV) return new Float (l / r); 157 if (op == MOD) return new Float (l % r); 158 if (op == EQ) return Boolean.valueOf(l == r); 159 if (op == NE) return Boolean.valueOf(l != r); 160 if (op == LT) return Boolean.valueOf(l < r); 161 if (op == LE) return Boolean.valueOf(l <= r); 162 if (op == GE) return Boolean.valueOf(l >= r); 163 if (op == GT) return Boolean.valueOf(l > r); 164 return null; 165 } 166 167 if (lv instanceof Long && rv instanceof Number ) { 168 long l = ((Long ) lv).longValue(); 169 long r = ((Number ) rv).longValue(); 170 if (op == SHL) return new Long (l << r); 171 if (op == SHR) return new Long (l >> r); 172 if (op == USHR) return new Long (l >>> r); 173 } 174 175 if (lv instanceof Long || rv instanceof Long ) { 176 long l = ((Number ) lv).longValue(); 177 long r = ((Number ) rv).longValue(); 178 if (op == ADD) return new Long (l + r); 179 if (op == SUB) return new Long (l - r); 180 if (op == MUL) return new Long (l * r); 181 if (op == DIV) return new Long (l / r); 182 if (op == MOD) return new Long (l % r); 183 if (op == EQ) return Boolean.valueOf(l == r); 184 if (op == NE) return Boolean.valueOf(l != r); 185 if (op == LT) return Boolean.valueOf(l < r); 186 if (op == LE) return Boolean.valueOf(l <= r); 187 if (op == GE) return Boolean.valueOf(l >= r); 188 if (op == GT) return Boolean.valueOf(l > r); 189 if (op == BIT_AND) return new Long (l & r); 190 if (op == BIT_OR) return new Long (l | r); 191 if (op == BIT_XOR) return new Long (l ^ r); 192 return null; 193 } 194 195 int l = ((Number ) lv).intValue(); 197 int r = ((Number ) rv).intValue(); 198 199 if (op == ADD) return new Integer (l + r); 200 if (op == SUB) return new Integer (l - r); 201 if (op == MUL) return new Integer (l * r); 202 if (op == DIV) return new Integer (l / r); 203 if (op == MOD) return new Integer (l % r); 204 if (op == EQ) return Boolean.valueOf(l == r); 205 if (op == NE) return Boolean.valueOf(l != r); 206 if (op == LT) return Boolean.valueOf(l < r); 207 if (op == LE) return Boolean.valueOf(l <= r); 208 if (op == GE) return Boolean.valueOf(l >= r); 209 if (op == GT) return Boolean.valueOf(l > r); 210 if (op == BIT_AND) return new Integer (l & r); 211 if (op == BIT_OR) return new Integer (l | r); 212 if (op == BIT_XOR) return new Integer (l ^ r); 213 if (op == SHL) return new Integer (l << r); 214 if (op == SHR) return new Integer (l >> r); 215 if (op == USHR) return new Integer (l >>> r); 216 return null; 217 } 218 } 219 catch (ArithmeticException e) { 220 return null; 222 } 223 224 if (lv instanceof Boolean && rv instanceof Boolean ) { 225 boolean l = ((Boolean ) lv).booleanValue(); 226 boolean r = ((Boolean ) rv).booleanValue(); 227 228 if (op == EQ) return Boolean.valueOf(l == r); 229 if (op == NE) return Boolean.valueOf(l != r); 230 if (op == BIT_AND) return Boolean.valueOf(l & r); 231 if (op == BIT_OR) return Boolean.valueOf(l | r); 232 if (op == BIT_XOR) return Boolean.valueOf(l ^ r); 233 if (op == COND_AND) return Boolean.valueOf(l && r); 234 if (op == COND_OR) return Boolean.valueOf(l || r); 235 } 236 237 return null; 238 } 239 240 241 public Node typeCheck(TypeChecker tc) throws SemanticException { 242 Type l = left.type(); 243 Type r = right.type(); 244 245 TypeSystem ts = tc.typeSystem(); 246 247 if (op == GT || op == LT || op == GE || op == LE) { 248 if (! l.isNumeric()) { 249 throw new SemanticException("The " + op + 250 " operator must have numeric operands.", left.position()); 251 } 252 253 if (! r.isNumeric()) { 254 throw new SemanticException("The " + op + 255 " operator must have numeric operands.", right.position()); 256 } 257 258 return type(ts.Boolean()); 259 } 260 261 if (op == EQ || op == NE) { 262 if (! ts.isCastValid(l, r) && ! ts.isCastValid(r, l)) { 263 throw new SemanticException("The " + op + 264 " operator must have operands of similar type.", 265 position()); 266 } 267 268 return type(ts.Boolean()); 269 } 270 271 if (op == COND_OR || op == COND_AND) { 272 if (! l.isBoolean()) { 273 throw new SemanticException("The " + op + 274 " operator must have boolean operands.", left.position()); 275 } 276 277 if (! r.isBoolean()) { 278 throw new SemanticException("The " + op + 279 " operator must have boolean operands.", right.position()); 280 } 281 282 return type(ts.Boolean()); 283 } 284 285 if (op == ADD) { 286 if (ts.equals(l, ts.String()) || ts.equals(r, ts.String())) { 287 if (!ts.canCoerceToString(r, tc.context())) { 288 throw new SemanticException("Cannot coerce an expression " + 289 "of type " + r + " to a String.", 290 right.position()); 291 } 292 if (!ts.canCoerceToString(l, tc.context())) { 293 throw new SemanticException("Cannot coerce an expression " + 294 "of type " + l + " to a String.", 295 left.position()); 296 } 297 return precedence(Precedence.STRING_ADD).type(ts.String()); 298 } 299 } 300 301 if (op == BIT_AND || op == BIT_OR || op == BIT_XOR) { 302 if (l.isBoolean() && r.isBoolean()) { 303 return type(ts.Boolean()); 304 } 305 } 306 307 if (op == ADD) { 308 if (! l.isNumeric()) { 309 throw new SemanticException("The " + op + 310 " operator must have numeric or String operands.", 311 left.position()); 312 } 313 314 if (! r.isNumeric()) { 315 throw new SemanticException("The " + op + 316 " operator must have numeric or String operands.", 317 right.position()); 318 } 319 } 320 321 if (op == BIT_AND || op == BIT_OR || op == BIT_XOR) { 322 if (! ts.isImplicitCastValid(l, ts.Long())) { 323 throw new SemanticException("The " + op + 324 " operator must have numeric or boolean operands.", 325 left.position()); 326 } 327 328 if (! ts.isImplicitCastValid(r, ts.Long())) { 329 throw new SemanticException("The " + op + 330 " operator must have numeric or boolean operands.", 331 right.position()); 332 } 333 } 334 335 if (op == SUB || op == MUL || op == DIV || op == MOD) { 336 if (! l.isNumeric()) { 337 throw new SemanticException("The " + op + 338 " operator must have numeric operands.", left.position()); 339 } 340 341 if (! r.isNumeric()) { 342 throw new SemanticException("The " + op + 343 " operator must have numeric operands.", right.position()); 344 } 345 } 346 347 if (op == SHL || op == SHR || op == USHR) { 348 if (! ts.isImplicitCastValid(l, ts.Long())) { 349 throw new SemanticException("The " + op + 350 " operator must have numeric operands.", left.position()); 351 } 352 353 if (! ts.isImplicitCastValid(r, ts.Long())) { 354 throw new SemanticException("The " + op + 355 " operator must have numeric operands.", right.position()); 356 } 357 } 358 359 if (op == SHL || op == SHR || op == USHR) { 360 return type(ts.promote(l)); 362 } 363 364 return type(ts.promote(l, r)); 365 } 366 367 public Type childExpectedType(Expr child, AscriptionVisitor av) { 368 Expr other; 369 370 if (child == left) { 371 other = right; 372 } 373 else if (child == right) { 374 other = left; 375 } 376 else { 377 return child.type(); 378 } 379 380 TypeSystem ts = av.typeSystem(); 381 382 try { 383 if (op == EQ || op == NE) { 384 if ((child.type().isReference() || child.type().isNull()) && 386 (other.type().isReference() || other.type().isNull())) { 387 return ts.leastCommonAncestor(child.type(), other.type()); 388 } 389 390 if (child.type().isBoolean() && other.type().isBoolean()) { 391 return ts.Boolean(); 392 } 393 394 if (child.type().isNumeric() && other.type().isNumeric()) { 395 return ts.promote(child.type(), other.type()); 396 } 397 398 if (child.type().isImplicitCastValid(other.type())) { 399 return other.type(); 400 } 401 402 return child.type(); 403 } 404 405 if (op == ADD && ts.equals(type, ts.String())) { 406 return ts.String(); 408 } 409 410 if (op == GT || op == LT || op == GE || op == LE) { 411 if (child.type().isNumeric() && other.type().isNumeric()) { 412 return ts.promote(child.type(), other.type()); 413 } 414 415 return child.type(); 416 } 417 418 if (op == COND_OR || op == COND_AND) { 419 return ts.Boolean(); 420 } 421 422 if (op == BIT_AND || op == BIT_OR || op == BIT_XOR) { 423 if (other.type().isBoolean()) { 424 return ts.Boolean(); 425 } 426 427 if (child.type().isNumeric() && other.type().isNumeric()) { 428 return ts.promote(child.type(), other.type()); 429 } 430 431 return child.type(); 432 } 433 434 if (op == ADD || op == SUB || op == MUL || op == DIV || op == MOD) { 435 if (child.type().isNumeric() && other.type().isNumeric()) { 436 Type t = ts.promote(child.type(), other.type()); 437 438 if (ts.isImplicitCastValid(t, av.toType())) { 439 return t; 440 } 441 else { 442 return av.toType(); 443 } 444 } 445 446 return child.type(); 447 } 448 449 if (op == SHL || op == SHR || op == USHR) { 450 if (child.type().isNumeric() && other.type().isNumeric()) { 451 if (child == left) { 452 Type t = ts.promote(child.type()); 453 454 if (ts.isImplicitCastValid(t, av.toType())) { 455 return t; 456 } 457 else { 458 return av.toType(); 459 } 460 } 461 else { 462 return ts.promote(child.type()); 463 } 464 } 465 466 return child.type(); 467 } 468 469 return child.type(); 470 } 471 catch (SemanticException e) { 472 } 473 474 return child.type(); 475 } 476 477 478 public boolean throwsArithmeticException() { 479 return op == DIV || op == MOD; 483 } 484 485 public String toString() { 486 return left + " " + op + " " + right; 487 } 488 489 490 public void prettyPrint(CodeWriter w, PrettyPrinter tr) { 491 printSubExpr(left, true, w, tr); 492 w.write(" "); 493 w.write(op.toString()); 494 w.allowBreak(type() == null || type().isPrimitive() ? 2 : 0, " "); 495 printSubExpr(right, false, w, tr); 496 } 497 498 public void dump(CodeWriter w) { 499 super.dump(w); 500 501 if (type != null) { 502 w.allowBreak(4, " "); 503 w.begin(0); 504 w.write("(type " + type + ")"); 505 w.end(); 506 } 507 508 w.allowBreak(4, " "); 509 w.begin(0); 510 w.write("(operator " + op + ")"); 511 w.end(); 512 } 513 514 public Term entry() { 515 return left.entry(); 516 } 517 518 public List acceptCFG(CFGBuilder v, List succs) { 519 if (op == COND_AND || op == COND_OR) { 520 if (left instanceof BooleanLit) { 522 BooleanLit b = (BooleanLit) left; 523 if ((b.value() && op == COND_OR) || (! b.value() && op == COND_AND)) { 524 v.visitCFG(left, this); 525 } 526 else { 527 v.visitCFG(left, right.entry()); 528 v.visitCFG(right, this); 529 } 530 } 531 else { 532 if (op == COND_AND) { 533 v.visitCFG(left, FlowGraph.EDGE_KEY_TRUE, right.entry(), 536 FlowGraph.EDGE_KEY_FALSE, this); 537 } 538 else { 539 v.visitCFG(left, FlowGraph.EDGE_KEY_FALSE, right.entry(), 542 FlowGraph.EDGE_KEY_TRUE, this); 543 } 544 v.visitCFG(right, FlowGraph.EDGE_KEY_TRUE, this, 545 FlowGraph.EDGE_KEY_FALSE, this); 546 } 547 } 548 else { 549 if (left.type().isBoolean() && right.type().isBoolean()) { 550 v.visitCFG(left, FlowGraph.EDGE_KEY_TRUE, right.entry(), 551 FlowGraph.EDGE_KEY_FALSE, right.entry()); 552 v.visitCFG(right, FlowGraph.EDGE_KEY_TRUE, this, 553 FlowGraph.EDGE_KEY_FALSE, this); 554 } 555 else { 556 v.visitCFG(left, right.entry()); 557 v.visitCFG(right, this); 558 } 559 } 560 561 return succs; 562 } 563 564 public List throwTypes(TypeSystem ts) { 565 if (throwsArithmeticException()) { 566 return Collections.singletonList(ts.ArithmeticException()); 567 } 568 569 return Collections.EMPTY_LIST; 570 } 571 } 572 | Popular Tags |