1 24 25 package org.aspectj.compiler.crosscuts.joinpoints; 26 27 import org.aspectj.compiler.crosscuts.ast.*; 28 import org.aspectj.compiler.base.ast.*; 29 import org.aspectj.compiler.base.*; 30 31 import org.aspectj.compiler.crosscuts.AspectJCompiler; 32 33 import org.aspectj.util.PartialOrder; 34 35 import java.util.*; 36 37 39 40 public class JpPlan extends CompilerObject implements PartialOrder.PartialComparable { 41 public static final int CFLOWENTRY_ROOT = 0; 43 public static final int EACHOBJECT = 0; 44 public static final int AROUND = 1; 45 public static final int AFTER = 1; 46 public static final int BEFORE = 1; 47 public static final int CFLOWENTRY_NOROOT = 2; 48 public static final int SOFT_THROWABLE = 0; 49 50 public JoinPoint joinPoint; 51 52 53 57 public Map bindings = new HashMap(); 58 public Expr test; 59 public Expr ifTest; 60 public Expr instance; 61 62 public static final JpPlan NO_PLAN = new JpPlan(null) { 63 public boolean isPossible() { return false; } 64 public JpPlan or(JpPlan other) { 65 return other; 66 } 67 68 public JpPlan and(JpPlan other) { 69 return NO_PLAN; 70 } 71 72 public JpPlan not() { 73 return JpPlan.ANY_PLAN; 74 } 75 public String toString() { return "NO_PLAN"; } 76 }; 77 78 79 public static final JpPlan NEVER_PLAN = new JpPlan(null) { 80 public boolean isPossible() { return false; } 81 public JpPlan or(JpPlan other) { 82 return this; 83 } 84 85 public JpPlan and(JpPlan other) { 86 return this; 87 } 88 89 public JpPlan not() { 90 return this; 91 } 92 public String toString() { return "NEVER_PLAN"; } 93 }; 94 95 public static final JpPlan ANY_PLAN = new JpPlan(null) { 96 public JpPlan or(JpPlan other) { 97 if (other == JpPlan.ANY_PLAN) return JpPlan.ANY_PLAN; 98 else return other.or(JpPlan.ANY_PLAN); 99 } 100 101 public JpPlan and(JpPlan other) { 102 return other; 103 } 104 105 public JpPlan not() { 106 return NO_PLAN; 107 } 108 109 public String toString() { return "ANY_PLAN"; } 110 }; 111 112 public JpPlan(JoinPoint jp) { 113 super(jp == null ? null : jp.getCompiler()); 114 this.joinPoint = jp; 115 } 116 117 public boolean isPossible() { 118 if (ifTest == null) { 119 return test == null || !isAlwaysFalse(test); 120 } 121 122 if (test == null) { 123 return ifTest == null || !isAlwaysFalse(ifTest); 124 } 125 126 return !(isAlwaysFalse(test) || isAlwaysFalse(ifTest)); 127 } 128 129 public JoinPoint getJoinPoint() { return joinPoint; } 130 public Expr getInstance() { 131 return instance; 132 } 135 136 public void wrapJoinPoint(JoinPoint jp) { 137 System.err.println("shouldn't be making this JpPlan concrete!"); 138 } 139 140 protected List dependencies = new LinkedList(); 143 public boolean dependsOn(Object o) { 144 return dependencies.contains(o); 146 } 147 148 public void addDependency(Object o) { 149 dependencies.add(o); 150 } 151 152 public int getPreSortOrder() { return 0; } 153 154 158 public int compareTo(Object o) { 159 if (!(o instanceof JpPlan) || this == o) return 0; 160 161 JpPlan otherPlan = (JpPlan)o; 162 163 if (getPreSortOrder() < otherPlan.getPreSortOrder()) return -1; 164 if (getPreSortOrder() > otherPlan.getPreSortOrder()) return +1; 165 166 return 0; 167 } 168 169 public int fallbackCompareTo(Object o) { return 0; } 170 171 public boolean matches(JpPlan other) { 172 return this == other; } 182 183 public JpPlan or(JpPlan other) { 184 if (other == NEVER_PLAN) return other; 185 186 if (!other.isPossible()) return this; 187 188 JpPlan plan = new JpPlan(joinPoint); 189 190 plan.test = orExprs(test, other.test); 191 plan.ifTest = orExprs(ifTest, other.ifTest); 192 plan.instance = mergeInstance(instance, other.instance); 193 plan.bindings = mergeBindings(bindings, other.bindings); 194 plan.dependencies.addAll(other.dependencies); 195 196 return plan; 197 } 198 199 public JpPlan and(JpPlan other) { 200 if (other == NEVER_PLAN) return other; 201 202 if (!other.isPossible()) return NO_PLAN; 203 204 JpPlan plan = new JpPlan(joinPoint); 205 206 plan.test = andExprs(test, other.test); 207 plan.ifTest = andExprs(ifTest, other.ifTest); 208 plan.instance = mergeInstance(instance, other.instance); 209 plan.bindings = mergeBindings(bindings, other.bindings); 210 plan.dependencies.addAll(other.dependencies); 211 212 return plan; 213 } 214 215 public JpPlan not() { 216 if (!isPossible()) return JpPlan.ANY_PLAN; 217 218 if (test == null && ifTest == null) return JpPlan.NO_PLAN; 220 221 JpPlan newPlan = new JpPlan(joinPoint); 222 newPlan.test = notExpr(this.test); 223 newPlan.ifTest = notExpr(this.ifTest); 224 newPlan.dependencies = dependencies; 225 return newPlan; 226 } 227 228 public void setInstanceExpr(Expr i) { 229 instance = i; 230 } 231 232 public void addExprTest(Expr t1) { 233 test = andExprs(test, t1); 234 } 235 236 public void addIfTest(Expr t1) { 237 ifTest = andExprs(ifTest, t1); 238 } 239 240 Expr andExprs(Expr e1, Expr e2) { 241 if (e1 == null) return e2; 242 if (e2 == null) return e1; 243 return getAST().makeBinop("&&", e1, e2); 244 } 245 246 Expr orExprs(Expr e1, Expr e2) { 247 if (e1 == null) return e2; 248 if (e2 == null) return e1; 249 return getAST().makeBinop("||", e1, e2); 250 } 251 252 Expr notExpr(Expr e) { 253 255 if (e == null) return null; 256 return getAST().makeUnop("!", e); 257 } 258 259 void checkEquivalent(FormalDec fd, Expr e1, Expr e2) { 261 if (!e1.equals(e2)) { 262 joinPoint.showError(fd, "incompatible bindings for this formal: both " + 263 e1.unparse() + " and " + e2.unparse()); 264 } 265 } 266 267 Map mergeBindings(Map b1, Map b2) { 268 Map ret = new HashMap(b1); 269 for (Iterator i = b2.entrySet().iterator(); i.hasNext(); ) { 270 Map.Entry entry = (Map.Entry)i.next(); 271 Object key = entry.getKey(); 272 if (ret.containsKey(key)) { 273 checkEquivalent((FormalDec)key, (Expr)ret.get(key), (Expr)entry.getValue()); 274 } else { 275 ret.put(key, entry.getValue()); 276 } 277 } 278 return ret; 279 } 280 281 Expr mergeInstance(Expr i1, Expr i2) { 282 if (i1 == null) return i2; 284 else return i1; 285 } 286 287 public void bindInstance(Expr expr) { 289 instance = expr; 290 } 291 292 public void bindExpr(FormalDec formalDec, Expr expr) { 293 if (bindings.containsKey(formalDec)) { 295 checkEquivalent(formalDec, expr, (Expr)bindings.get(formalDec)); 296 } else { 297 bindings.put(formalDec, expr); 298 } 299 } 300 301 302 305 public Stmt wrapDynamicTest(Stmt trueStmt) { 306 Expr dynamicTest = getDynamicTest(); 307 if (dynamicTest != null) { 308 final AST ast = getAST(); 309 return ast.makeBlock(ast.makeIf(dynamicTest, trueStmt)); 310 } else { 311 return trueStmt; 312 } 313 } 314 315 private Expr makeDynamicTest(Expr expr, boolean keepTypes) { 316 if (expr == null) return null; 317 if (expr != null) { 318 expr = (Expr)new ExprMover(getCompiler(), keepTypes).process(expr); 319 expr = simplify(expr); 320 if (isAlwaysTrue(expr)) expr = null; 321 } 322 return expr; 323 } 324 325 326 private Expr getBasicDynamicTest() { 327 return makeDynamicTest(test, false); 328 } 329 330 331 private Expr getIfDynamicTest() { 332 return makeDynamicTest(ifTest, true); 333 } 334 335 336 public Expr getDynamicTest() { 337 return andExprs(getBasicDynamicTest(), getIfDynamicTest()); 338 } 339 340 boolean isAlwaysFalse(Expr expr) { 341 return expr instanceof BooleanLiteralExpr && 342 !((BooleanLiteralExpr)expr).getBooleanValue(); 343 } 344 boolean isAlwaysTrue(Expr expr) { 345 return expr instanceof BooleanLiteralExpr && 346 ((BooleanLiteralExpr)expr).getBooleanValue(); 347 } 348 349 Expr simplify(Expr expr) { 350 if (expr == null) return null; 351 return (Expr)new BooleanExprSimplifier(getCompiler()).process(expr); 352 } 353 354 private class BooleanExprSimplifier extends Walker { 355 public BooleanExprSimplifier(JavaCompiler compiler) { super(compiler); } 356 357 public ASTObject process(ASTObject node) { 358 node.walk(this); 359 360 if (node instanceof InstanceofExpr) { 361 return ((InstanceofExpr)node).simplify(); 362 } else if (node instanceof AndAndOpExpr) { 363 AndAndOpExpr e = (AndAndOpExpr)node; 364 if (isAlwaysFalse(e.getRand1()) || isAlwaysFalse(e.getRand2())) { 365 return node.getAST().makeLiteral(false); 366 } 367 if (isAlwaysTrue(e.getRand1())) return e.getRand2(); 368 if (isAlwaysTrue(e.getRand2())) return e.getRand1(); 369 return node; 370 } else if (node instanceof OrOrOpExpr) { 371 OrOrOpExpr e = (OrOrOpExpr)node; 372 if (isAlwaysTrue(e.getRand1()) || isAlwaysTrue(e.getRand2())) { 373 return node.getAST().makeLiteral(true); 374 } 375 if (isAlwaysFalse(e.getRand1())) return e.getRand2(); 376 if (isAlwaysFalse(e.getRand2())) return e.getRand1(); 377 return node; 378 } else if (node instanceof ParenExpr) { 379 ParenExpr e = (ParenExpr)node; 380 if (isAlwaysFalse(e.getExpr())) return e.getExpr(); 381 if (isAlwaysTrue(e.getExpr())) return e.getExpr(); 382 return node; 383 } else if (node instanceof LogNotOpExpr) { 384 LogNotOpExpr e = (LogNotOpExpr)node; 385 if (isAlwaysTrue(e.getRand1())) return node.getAST().makeLiteral(false); 386 if (isAlwaysFalse(e.getRand1())) return node.getAST().makeLiteral(true); 387 return node; 388 } else { 389 return node; 390 } 391 } 392 } 393 394 397 public void moveBindings(final Map remap) { 398 test = getBasicDynamicTest(); 400 ifTest = getIfDynamicTest(); 401 402 for (Iterator i = remap.entrySet().iterator(); i.hasNext(); ) { 403 Map.Entry entry = (Map.Entry)i.next(); 404 Object key = entry.getKey(); 405 if (bindings.containsKey(key)) { 406 bindings.put(entry.getValue(), bindings.get(key)); 407 } else { 409 } 411 } 412 } 413 414 415 private class ExprMover extends Walker { 416 private boolean keepTypes; 417 public ExprMover(JavaCompiler compiler, boolean keepTypes) { 418 super(compiler); 419 this.keepTypes = keepTypes; 420 } 421 422 public ASTObject process(ASTObject object) { 423 object.walk(this); 424 if (object instanceof VarExpr) { 425 VarExpr var = (VarExpr)object; 426 if (var.getId().equals("thisJoinPoint")) { 427 return joinPoint.makeDynamicJoinPointVarExpr(); 428 } else if (var.getId().equals("thisJoinPointStaticPart")) { 429 return joinPoint.makeStaticJoinPointVarExpr(); 430 } else if (var.getId().equals("aspect$instance")) { 431 if (instance != null) return instance.copy(); 433 } 434 435 VarDec varDec = var.getVarDec(); 436 Expr expr = (Expr)bindings.get(varDec); 437 if (expr != null) { 438 expr = (Expr)expr.copy(); 439 if (keepTypes) { 440 return getAST().forceCast(varDec.getType(), expr); 441 } else { 442 return expr; 443 } 444 } else { 445 return var; 446 } 447 } 448 return object; 449 } 450 } 451 452 void showFormalNotBound(FormalDec formalDec) { 453 formalDec.showError("formal not bound on " + joinPoint); 454 } 455 456 public Exprs getCallExprs(Formals formals) { 457 final AST ast = getAST(); 458 459 461 Exprs exprs = ast.makeExprs(); 462 for (int i=0; i<formals.size(); i++) { 463 Expr expr = (Expr)bindings.get(formals.get(i)); 464 if (expr == null) { 465 showFormalNotBound(formals.get(i)); 466 break; 467 } 468 exprs.add(makeLegalExpr(expr, formals.get(i).getType())); 469 } 471 return exprs; 472 } 473 474 Expr makeLegalExpr(Expr expr, Type type) { 475 Type exprType = expr.getType(); 476 if (type.isObject()) { 477 return exprType.makeObject(expr); 478 } else { 479 return getAST().makeCast(type, expr); 480 } 481 } 482 483 public String toString() { 484 if (joinPoint != null) return "plan(" + joinPoint.toString() + ")"; 485 else return super.toString(); 486 } 487 } 488 | Popular Tags |