1 21 package com.db4o.nativequery.analysis; 22 23 import java.util.*; 24 25 import EDU.purdue.cs.bloat.cfg.*; 26 import EDU.purdue.cs.bloat.editor.*; 27 import EDU.purdue.cs.bloat.tree.*; 28 29 import com.db4o.nativequery.*; 30 import com.db4o.nativequery.bloat.*; 31 import com.db4o.nativequery.expr.*; 32 import com.db4o.nativequery.expr.build.*; 33 import com.db4o.nativequery.expr.cmp.*; 34 import com.db4o.nativequery.expr.cmp.field.*; 35 36 public class BloatExprBuilderVisitor extends TreeVisitor { 37 38 private final static int MAX_DEPTH = 10; 40 41 private final static String [] PRIMITIVE_WRAPPER_NAMES = { 42 Boolean .class.getName(), Byte .class.getName(), 43 Short .class.getName(), Character .class.getName(), 44 Integer .class.getName(), Long .class.getName(), 45 Double .class.getName(), Float .class.getName(), 46 String .class.getName(), }; 47 48 static { 49 Arrays.sort(PRIMITIVE_WRAPPER_NAMES); 50 } 51 52 private final static ExpressionBuilder BUILDER = new ExpressionBuilder(); 53 54 private final static Map BUILDERS = new HashMap(); 55 56 private final static Map OP_SYMMETRY = new HashMap(); 57 58 private static class ComparisonBuilder { 59 private ComparisonOperator op; 60 61 public ComparisonBuilder(ComparisonOperator op) { 62 this.op = op; 63 } 64 65 public Expression buildComparison(FieldValue fieldValue, 66 ComparisonOperand valueExpr) { 67 return new ComparisonExpression(fieldValue, valueExpr, op); 68 } 69 } 70 71 private static class NegateComparisonBuilder extends ComparisonBuilder { 72 public NegateComparisonBuilder(ComparisonOperator op) { 73 super(op); 74 } 75 76 public Expression buildComparison(FieldValue fieldValue, 77 ComparisonOperand valueExpr) { 78 return BUILDER.not(super.buildComparison(fieldValue, valueExpr)); 79 } 80 } 81 82 static { 83 BUILDERS.put(new Integer (IfStmt.EQ), new ComparisonBuilder( 84 ComparisonOperator.EQUALS)); 85 BUILDERS.put(new Integer (IfStmt.NE), new NegateComparisonBuilder( 86 ComparisonOperator.EQUALS)); 87 BUILDERS.put(new Integer (IfStmt.LT), new ComparisonBuilder( 88 ComparisonOperator.SMALLER)); 89 BUILDERS.put(new Integer (IfStmt.GT), new ComparisonBuilder( 90 ComparisonOperator.GREATER)); 91 BUILDERS.put(new Integer (IfStmt.LE), new NegateComparisonBuilder( 92 ComparisonOperator.GREATER)); 93 BUILDERS.put(new Integer (IfStmt.GE), new NegateComparisonBuilder( 94 ComparisonOperator.SMALLER)); 95 96 OP_SYMMETRY.put(new Integer (IfStmt.EQ), new Integer (IfStmt.EQ)); 97 OP_SYMMETRY.put(new Integer (IfStmt.NE), new Integer (IfStmt.NE)); 98 OP_SYMMETRY.put(new Integer (IfStmt.LT), new Integer (IfStmt.GT)); 99 OP_SYMMETRY.put(new Integer (IfStmt.GT), new Integer (IfStmt.LT)); 100 OP_SYMMETRY.put(new Integer (IfStmt.LE), new Integer (IfStmt.GE)); 101 OP_SYMMETRY.put(new Integer (IfStmt.GE), new Integer (IfStmt.LE)); 102 } 103 104 private Expression expr; 105 106 private Object retval; 107 108 private Map seenBlocks = new HashMap(); 109 110 private BloatUtil bloatUtil; 111 112 private LinkedList methodStack = new LinkedList(); 113 114 private LinkedList localStack = new LinkedList(); 115 116 private int retCount = 0; 117 118 private int blockCount = 0; 119 120 public BloatExprBuilderVisitor(BloatUtil bloatUtil) { 121 this.bloatUtil = bloatUtil; 122 localStack.addLast(new ComparisonOperand[] { 123 PredicateFieldRoot.INSTANCE, CandidateFieldRoot.INSTANCE }); 124 } 125 126 private Object purgeReturnValue() { 127 Object expr = this.retval; 128 retval(null); 129 return expr; 130 } 131 132 private void expression(Expression expr) { 133 retval(expr); 134 this.expr = expr; 135 } 136 137 private void retval(Object expr) { 138 this.retval = expr; 139 } 140 141 private ComparisonBuilder builder(int op) { 142 return (ComparisonBuilder) BUILDERS.get(new Integer (op)); 143 } 144 145 public Expression expression() { 146 if (expr == null && isSingleReturn() && retval instanceof ConstValue) { 147 expression(asExpression(retval)); 148 } 149 return (checkComparisons(expr) ? expr : null); 150 } 151 152 private boolean isSingleReturn() { 153 return retCount == 1 && blockCount == 4; } 155 156 private boolean checkComparisons(Expression expr) { 157 if (expr == null) { 158 return true; 159 } 160 final boolean[] result = { true }; 161 ExpressionVisitor visitor = new TraversingExpressionVisitor() { 162 public void visit(ComparisonExpression expression) { 163 if (expression.left().root() != CandidateFieldRoot.INSTANCE) { 164 result[0] = false; 165 } 166 } 167 }; 168 expr.accept(visitor); 169 return result[0]; 170 } 171 172 public void visitIfZeroStmt(IfZeroStmt stmt) { 173 stmt.expr().visit(this); 174 Object retval = purgeReturnValue(); 175 boolean cmpNull = false; 176 if (retval instanceof FieldValue) { 177 Expression forced = identityOrBoolComparisonOrNull(retval); 179 if (forced != null) { 180 retval = forced; 181 } else { 182 FieldValue fieldVal = (FieldValue) retval; 183 String fieldType = (String )fieldVal.tag(); 184 Object constVal=null; 185 if(fieldType.length()==1) { 186 constVal=new Integer (0); 187 } 188 retval = new ComparisonExpression(fieldVal, 189 new ConstValue(constVal), ComparisonOperator.EQUALS); 190 cmpNull = true; 191 } 192 } 193 if (retval instanceof Expression) { 194 Expression expr = (Expression) retval; 195 if (stmt.comparison() == IfStmt.EQ && !cmpNull 196 || stmt.comparison() == IfStmt.NE && cmpNull) { 197 expr = BUILDER.not(expr); 198 } 199 expression(buildComparison(stmt, expr)); 200 return; 201 } 202 if (!(retval instanceof ThreeWayComparison)) { 203 expression(null); 204 return; 205 } 206 ThreeWayComparison cmp = (ThreeWayComparison) retval; 207 Expression expr = null; 208 int comparison = stmt.comparison(); 209 if (cmp.swapped()) { 210 comparison = ((Integer ) OP_SYMMETRY.get(new Integer (comparison))) 211 .intValue(); 212 } 213 switch (comparison) { 214 case IfStmt.EQ: 215 expr = new ComparisonExpression(cmp.left(), cmp.right(), 216 ComparisonOperator.EQUALS); 217 break; 218 case IfStmt.NE: 219 expr = BUILDER.not(new ComparisonExpression(cmp.left(), 220 cmp.right(), ComparisonOperator.EQUALS)); 221 break; 222 case IfStmt.LT: 223 expr = new ComparisonExpression(cmp.left(), cmp.right(), 224 ComparisonOperator.SMALLER); 225 break; 226 case IfStmt.GT: 227 expr = new ComparisonExpression(cmp.left(), cmp.right(), 228 ComparisonOperator.GREATER); 229 break; 230 case IfStmt.LE: 231 expr = BUILDER.not(new ComparisonExpression(cmp.left(), 232 cmp.right(), ComparisonOperator.GREATER)); 233 break; 234 case IfStmt.GE: 235 expr = BUILDER.not(new ComparisonExpression(cmp.left(), 236 cmp.right(), ComparisonOperator.SMALLER)); 237 break; 238 default: 239 break; 240 } 241 expression(buildComparison(stmt, expr)); 242 } 243 244 public void visitIfCmpStmt(IfCmpStmt stmt) { 245 stmt.left().visit(this); 246 Object left = purgeReturnValue(); 247 stmt.right().visit(this); 248 Object right = purgeReturnValue(); 249 int op = stmt.comparison(); 250 if ((left instanceof ComparisonOperand) 251 && (right instanceof FieldValue)) { 252 FieldValue rightField = (FieldValue) right; 253 if (rightField.root() == CandidateFieldRoot.INSTANCE) { 254 Object swap = left; 255 left = right; 256 right = swap; 257 op = ((Integer ) OP_SYMMETRY.get(new Integer (op))).intValue(); 258 } 259 } 260 if (!(left instanceof FieldValue) 261 || !(right instanceof ComparisonOperand)) { 262 expression(null); 263 return; 264 } 265 FieldValue fieldExpr = (FieldValue) left; 266 ComparisonOperand valueExpr = (ComparisonOperand) right; 267 268 Expression cmp = buildComparison(stmt, builder(op).buildComparison( 269 fieldExpr, valueExpr)); 270 expression(cmp); 271 } 272 273 public void visitExprStmt(ExprStmt stmt) { 274 super.visitExprStmt(stmt); 275 } 276 277 private boolean isPrimitiveWrapper(Type type) { 278 String typeName=bloatUtil.normalizedClassName(type); 279 for (int idx = 0; idx < PRIMITIVE_WRAPPER_NAMES.length; idx++) { 280 if(typeName.equals(PRIMITIVE_WRAPPER_NAMES[idx])) { 281 return true; 282 } 283 } 284 return false; 285 } 286 287 public void visitCallExpr(CallExpr expr) { 288 boolean isStatic = (expr instanceof CallStaticExpr); 289 if (!isStatic && expr.method().name().equals("<init>")) { 290 retval(null); 291 return; 292 } 293 if (!isStatic && expr.method().name().equals("equals")) { 294 CallMethodExpr call = (CallMethodExpr) expr; 295 if (isPrimitive(call.receiver().type())) { 296 processEqualsCall(call, ComparisonOperator.EQUALS); 297 } 298 return; 299 } 300 if(expr.method().declaringClass().equals(Type.STRING)) { 301 if(applyStringHandling(expr)) { 302 return; 303 } 304 } 305 ComparisonOperandAnchor rcvRetval = null; 306 if (!isStatic) { 307 ((CallMethodExpr) expr).receiver().visit(this); 308 rcvRetval = (ComparisonOperandAnchor) purgeReturnValue(); 309 } 310 if(isPrimitiveWrapper(expr.method().declaringClass())) { 311 if(applyPrimitiveWrapperHandling(expr,rcvRetval)) { 312 return; 313 } 314 } 315 MemberRef methodRef = expr.method(); 316 if (methodStack.contains(methodRef) || methodStack.size() > MAX_DEPTH) { 317 return; 318 } 319 methodStack.addLast(methodRef); 320 boolean addedLocals=false; 321 try { 322 List params = new ArrayList(expr.params().length + 1); 323 params.add(rcvRetval); 324 for (int idx = 0; idx < expr.params().length; idx++) { 325 expr.params()[idx].visit(this); 326 ComparisonOperand curparam = (ComparisonOperand) purgeReturnValue(); 327 if ((curparam instanceof ComparisonOperandAnchor) 328 && (((ComparisonOperandAnchor) curparam).root() == CandidateFieldRoot.INSTANCE)) { 329 retval(null); 330 return; 331 } 332 params.add(curparam); 333 } 334 addedLocals=true; 335 localStack.addLast(params.toArray(new ComparisonOperand[params 336 .size()])); 337 338 if (rcvRetval == null 339 || rcvRetval.root() != CandidateFieldRoot.INSTANCE) { 340 if (rcvRetval == null) { 341 rcvRetval = new StaticFieldRoot(bloatUtil.normalizedClassName(expr 342 .method().declaringClass())); 343 } 344 params.remove(0); 345 Type[] paramTypes = expr.method().nameAndType().type() 346 .paramTypes(); 347 Class [] javaParamTypes = new Class [paramTypes.length]; 348 for (int paramIdx = 0; paramIdx < paramTypes.length; paramIdx++) { 349 String className = bloatUtil.normalizedClassName(paramTypes[paramIdx]); 350 javaParamTypes[paramIdx] = (PRIMITIVE_CLASSES 351 .containsKey(className) ? (Class ) PRIMITIVE_CLASSES 352 .get(className) : Class.forName(className)); 353 } 354 retval(new MethodCallValue(rcvRetval, expr.method().name(), 355 javaParamTypes, (ComparisonOperand[]) params 356 .toArray(new ComparisonOperand[params.size()]))); 357 return; 358 } 359 360 FlowGraph flowGraph = bloatUtil.flowGraph(methodRef 361 .declaringClass().className(), methodRef.name()); 362 if (flowGraph == null) { 363 return; 364 } 365 if (NQDebug.LOG) { 366 System.out 367 .println("METHOD:" + flowGraph.method().nameAndType()); 368 flowGraph.visit(new PrintVisitor()); 369 } 370 flowGraph.visit(this); 371 Object methodRetval = purgeReturnValue(); 372 retval(methodRetval); 373 } catch (ClassNotFoundException e) { 374 e.printStackTrace(); 375 } finally { 376 if(addedLocals) { 377 localStack.removeLast(); 378 } 379 Object last = methodStack.removeLast(); 380 if (!last.equals(methodRef)) { 381 throw new RuntimeException ("method stack inconsistent: push=" 382 + methodRef + " , pop=" + last); 383 } 384 } 385 } 386 387 private boolean applyPrimitiveWrapperHandling(CallExpr expr,ComparisonOperandAnchor rcvRetval) { 388 String methodName = expr.method().name(); 389 if(methodName.endsWith("Value")) { 390 return handlePrimitiveWrapperValueCall(rcvRetval); 391 } 392 if(methodName.equals("compareTo")) { 393 return handlePrimitiveWrapperCompareToCall(expr, rcvRetval); 394 } 395 return false; 396 } 397 398 private boolean handlePrimitiveWrapperCompareToCall(CallExpr expr, ComparisonOperandAnchor rcvRetval) { 399 ComparisonOperand left=rcvRetval; 400 expr.params()[0].visit(this); 401 ComparisonOperand right=(ComparisonOperand) purgeReturnValue(); 402 retval(new ThreeWayComparison((FieldValue)left,right,false)); 403 return true; 404 } 405 406 private boolean handlePrimitiveWrapperValueCall(ComparisonOperandAnchor rcvRetval) { 407 retval(rcvRetval); 408 if(rcvRetval instanceof FieldValue) { 409 FieldValue fieldval=(FieldValue)rcvRetval; 410 if(isBooleanField(fieldval)) { 411 retval(new ComparisonExpression(fieldval,new ConstValue(Boolean.TRUE),ComparisonOperator.EQUALS)); 412 } 413 if(fieldval.root().equals(CandidateFieldRoot.INSTANCE)) { 414 return true; 415 } 416 } 417 return false; 418 } 419 420 private boolean applyStringHandling(CallExpr expr) { 421 if (expr.method().name().equals("contains")) { 422 processEqualsCall((CallMethodExpr) expr, 423 ComparisonOperator.CONTAINS); 424 return true; 425 } 426 if (expr.method().name().equals("startsWith")) { 427 processEqualsCall((CallMethodExpr) expr, 428 ComparisonOperator.STARTSWITH); 429 return true; 430 } 431 if (expr.method().name().equals("endsWith")) { 432 processEqualsCall((CallMethodExpr) expr, 433 ComparisonOperator.ENDSWITH); 434 return true; 435 } 436 return false; 437 } 438 439 private final static Map PRIMITIVE_CLASSES; 440 441 static { 442 PRIMITIVE_CLASSES = new HashMap(); 443 PRIMITIVE_CLASSES.put("Z", Boolean.TYPE); 444 PRIMITIVE_CLASSES.put("B", Byte.TYPE); 445 PRIMITIVE_CLASSES.put("S", Short.TYPE); 446 PRIMITIVE_CLASSES.put("C", Character.TYPE); 447 PRIMITIVE_CLASSES.put("I", Integer.TYPE); 448 PRIMITIVE_CLASSES.put("J", Long.TYPE); 449 PRIMITIVE_CLASSES.put("F", Float.TYPE); 450 PRIMITIVE_CLASSES.put("D", Double.TYPE); 451 } 452 453 private boolean isPrimitive(Type type) { 454 return Arrays.binarySearch(PRIMITIVE_WRAPPER_NAMES, 455 bloatUtil.normalizedClassName(type)) >= 0; 456 } 457 458 private void processEqualsCall(CallMethodExpr expr, ComparisonOperator op) { 459 Expr left = expr.receiver(); 460 Expr right = expr.params()[0]; 461 if (!isComparableExprOperand(left) || !isComparableExprOperand(right)) { 462 throw new EarlyExitException(); 463 } 464 left.visit(this); 465 Object leftObj = purgeReturnValue(); 466 if (!(leftObj instanceof ComparisonOperand)) { 467 expression(null); 468 return; 469 } 470 ComparisonOperand leftOp = (ComparisonOperand) leftObj; 471 right.visit(this); 472 ComparisonOperand rightOp = (ComparisonOperand) purgeReturnValue(); 473 if (op.isSymmetric() && isCandidateFieldValue(rightOp) 474 && !isCandidateFieldValue(leftOp)) { 475 ComparisonOperand swap = leftOp; 476 leftOp = rightOp; 477 rightOp = swap; 478 } 479 if (!isCandidateFieldValue(leftOp) || rightOp == null) { 480 throw new EarlyExitException(); 481 } 482 expression(new ComparisonExpression((FieldValue) leftOp, rightOp, op)); 483 } 484 485 private boolean isCandidateFieldValue(ComparisonOperand op) { 486 return ((op instanceof FieldValue) && ((FieldValue) op).root() == CandidateFieldRoot.INSTANCE); 487 } 488 489 private boolean isComparableExprOperand(Expr expr) { 490 return (expr instanceof FieldExpr) || (expr instanceof StaticFieldExpr) 491 || (expr instanceof CallMethodExpr) 492 || (expr instanceof CallStaticExpr) 493 || (expr instanceof ConstantExpr) 494 || (expr instanceof LocalExpr); 495 } 496 497 public void visitFieldExpr(FieldExpr expr) { 498 expr.object().visit(this); 499 Object fieldObj = purgeReturnValue(); 500 String fieldName = expr.field().name(); 501 if (fieldObj instanceof ComparisonOperandAnchor) { 502 retval(new FieldValue((ComparisonOperandAnchor) fieldObj, 503 fieldName, bloatUtil.normalizedClassName(expr.field().type()))); 504 } 505 } 506 507 public void visitStaticFieldExpr(StaticFieldExpr expr) { 508 MemberRef field = expr.field(); 509 retval(new FieldValue(new StaticFieldRoot(bloatUtil.normalizedClassName(field 510 .declaringClass())), field.name(), bloatUtil.normalizedClassName(field 511 .type()))); 512 } 513 514 public void visitConstantExpr(ConstantExpr expr) { 515 super.visitConstantExpr(expr); 516 retval(new ConstValue(expr.value())); 517 } 518 519 public void visitLocalExpr(LocalExpr expr) { 520 super.visitLocalExpr(expr); 521 ComparisonOperand[] locals = (ComparisonOperand[]) localStack.getLast(); 522 if (expr.index() >= locals.length) { 523 retval(null); 524 return; 525 } 526 retval(locals[expr.index()]); 527 } 528 529 public void visitBlock(Block block) { 530 if (!seenBlocks.containsKey(block)) { 531 super.visitBlock(block); 532 seenBlocks.put(block, retval); 533 blockCount++; 534 } else { 535 retval(seenBlocks.get(block)); 536 } 537 } 538 539 public void visitFlowGraph(FlowGraph graph) { 540 try { 541 super.visitFlowGraph(graph); 542 if (expr == null) { 543 Expression forced = identityOrBoolComparisonOrNull(retval); 544 if (forced != null) { 545 expression(forced); 546 } 547 } 548 } catch (EarlyExitException exc) { 549 expr=null; 550 } 551 } 552 553 private Expression identityOrBoolComparisonOrNull(Object val) { 554 if (val instanceof Expression) { 555 return (Expression) val; 556 } 557 if (!(val instanceof FieldValue)) { 558 return null; 559 } 560 FieldValue fieldVal = (FieldValue) val; 561 if (fieldVal.root() != CandidateFieldRoot.INSTANCE) { 562 return null; 563 } 564 String fieldType = ((String ) fieldVal.tag()); 565 if (fieldType.length() != 1) { 566 return null; 567 } 568 Object constVal = null; 569 switch (fieldType.charAt(0)) { 570 case 'Z': 571 constVal = Boolean.TRUE; 572 break; 573 default: 577 return null; 578 } 579 return new ComparisonExpression(fieldVal, new ConstValue(constVal), 580 ComparisonOperator.EQUALS); 581 } 582 583 private boolean isBooleanField(FieldValue fieldVal) { 584 return isFieldType(fieldVal, "Z")||isFieldType(fieldVal, Boolean .class.getName()); 585 } 586 587 private boolean isIntField(FieldValue fieldVal) { 588 return isFieldType(fieldVal, "I"); 589 } 590 591 private boolean isFieldType(FieldValue fieldVal, String expType) { 592 return expType.equals(fieldVal.tag()); 593 } 594 595 public void visitArithExpr(ArithExpr expr) { 596 expr.left().visit(this); 597 Object leftObj = purgeReturnValue(); 598 if (!(leftObj instanceof ComparisonOperand)) { 599 return; 600 } 601 ComparisonOperand left = (ComparisonOperand) leftObj; 602 expr.right().visit(this); 603 Object rightObj = purgeReturnValue(); 604 if (!(rightObj instanceof ComparisonOperand)) { 605 return; 606 } 607 ComparisonOperand right = (ComparisonOperand) rightObj; 608 boolean swapped = false; 609 if (right instanceof FieldValue) { 610 FieldValue rightField = (FieldValue) right; 611 if (rightField.root() == CandidateFieldRoot.INSTANCE) { 612 ComparisonOperand swap = left; 613 left = right; 614 right = swap; 615 swapped = true; 616 } 617 } 618 switch (expr.operation()) { 619 case ArithExpr.ADD: 620 case ArithExpr.SUB: 621 case ArithExpr.MUL: 622 case ArithExpr.DIV: 623 retval(new ArithmeticExpression(left, right, 624 arithmeticOperator(expr.operation()))); 625 break; 626 case ArithExpr.CMP: 627 case ArithExpr.CMPG: 628 case ArithExpr.CMPL: 629 if (left instanceof FieldValue) { 630 retval(new ThreeWayComparison((FieldValue) left, right, swapped)); 631 } 632 break; 633 case ArithExpr.XOR: 634 if (left instanceof FieldValue) { 635 retval(BUILDER.not(new ComparisonExpression((FieldValue) left, 636 right, ComparisonOperator.EQUALS))); 637 } 638 break; 639 default: 640 break; 641 } 642 } 643 644 public void visitArrayRefExpr(ArrayRefExpr expr) { 645 expr.array().visit(this); 646 ComparisonOperandAnchor arrayOp = (ComparisonOperandAnchor) purgeReturnValue(); 647 expr.index().visit(this); 648 ComparisonOperand idxOp = (ComparisonOperand) purgeReturnValue(); 649 if (arrayOp == null || idxOp == null 650 || arrayOp.root() == CandidateFieldRoot.INSTANCE) { 651 retval(null); 652 return; 653 } 654 retval(new ArrayAccessValue(arrayOp, idxOp)); 655 } 656 657 public void visitReturnExprStmt(ReturnExprStmt stat) { 658 stat.expr().visit(this); 659 retCount++; 660 } 661 662 private ArithmeticOperator arithmeticOperator(int bloatOp) { 663 switch (bloatOp) { 664 case ArithExpr.ADD: 665 return ArithmeticOperator.ADD; 666 case ArithExpr.SUB: 667 return ArithmeticOperator.SUBTRACT; 668 case ArithExpr.MUL: 669 return ArithmeticOperator.MULTIPLY; 670 case ArithExpr.DIV: 671 return ArithmeticOperator.DIVIDE; 672 default: 673 return null; 674 } 675 } 676 677 private Expression buildComparison(IfStmt stmt, Expression cmp) { 678 stmt.trueTarget().visit(this); 679 Object trueVal = purgeReturnValue(); 680 stmt.falseTarget().visit(this); 681 Object falseVal = purgeReturnValue(); 682 Expression trueExpr = asExpression(trueVal); 683 Expression falseExpr = asExpression(falseVal); 684 if (trueExpr == null || falseExpr == null) { 685 return null; 686 } 687 return BUILDER.ifThenElse(cmp, trueExpr, falseExpr); 688 } 689 690 private Expression asExpression(Object obj) { 691 if (obj instanceof Expression) { 692 return (Expression) obj; 693 } 694 if (obj instanceof ConstValue) { 695 Object val = ((ConstValue) obj).value(); 696 return asExpression(val); 697 } 698 if (obj instanceof Boolean ) { 699 return BoolConstExpression.expr(((Boolean ) obj).booleanValue()); 700 } 701 if (obj instanceof Integer ) { 702 int exprval = ((Integer ) obj).intValue(); 703 if (exprval == 0 || exprval == 1) { 704 return BoolConstExpression.expr(exprval == 1); 705 } 706 } 707 return null; 708 } 709 710 private static class EarlyExitException extends RuntimeException { 711 } 712 } 713 | Popular Tags |