1 24 25 package org.aspectj.compiler.crosscuts.ast; 26 27 import org.aspectj.compiler.base.ast.*; 28 import org.aspectj.compiler.base.*; 29 import org.aspectj.compiler.crosscuts.joinpoints.*; 30 31 32 import java.util.*; 33 34 import org.aspectj.util.*; 35 36 41 42 public class CFlowPcd extends Pcd { 43 public String toShortString() { 44 return "cflow" + (includesRoot ? CFlowPlanner.NO_ROOT_NAME : "") 45 + "(" + getPcd().toShortString() + ")"; 46 } 47 48 public void checkStatic() { showNonStaticError(); } 49 50 public JpPlanner makePlanner(PlanData planData) { 51 findFlowState(); 52 Map extraPlanners = planData.inAspect.getExtraPlanners(); 53 if (!extraPlanners.containsKey(this)) { 54 extraPlanners.put(this, 55 makeEntryPointInitializer(planData)); 56 } 57 58 final CflowField field = getCflowField(planData.inAspect); 59 return new JpPlanner() { 60 public FuzzyBoolean fastMatch(JoinPoint jp) { 61 return FuzzyBoolean.MAYBE; 62 } 63 public JpPlan makePlan(JoinPoint jp) { 64 JpPlan plan = new JpPlan(jp); 65 plan.test = field.testStackExpr(); 66 plan.addDependency(field); 67 field.remapExprs(plan); 68 return plan; 69 } 70 }; 71 } 72 73 private JpPlanner makeEntryPointInitializer(PlanData planData) { 74 findFlowState(); 75 76 final JpPlanner planner = getPcd().makePlanner(planData); 77 78 final CflowField field = getCflowField(planData.inAspect); 79 return new WrappedJpPlanner(planner) { 80 public JpPlan makePlan(JoinPoint jp) { 81 JpPlan plan = super.makePlan(jp); 82 if (!plan.isPossible()) return plan; 83 return new CFlowEntryPlan(plan, field); } 85 }; 86 } 87 88 public ASTObject postScope(ScopeWalker walker) { 90 if (walker.walkBodies()) { 91 findFlowState(); 92 } 94 return this; 95 } 96 97 List flowState = null; 98 99 void findFlowState() { 100 if (flowState != null) return; 101 102 flowState = new ArrayList(); 103 104 new Walker(getCompiler()) { 105 public void postProcess(ASTObject node) { 106 if (node instanceof VarTypeName) { 107 VarTypeName varTypeName = (VarTypeName)node; 108 if (varTypeName.getFormalDec() != null) { 109 addFlowState(varTypeName); 110 } 111 } 112 } 113 }.process(getPcd()); 114 } 115 116 void addFlowState(VarTypeName varTypeName) { 117 flowState.add(varTypeName); 118 } 119 120 Map cflowFields = new HashMap(); 121 122 public CflowField getCflowField(TypeDec inTypeDec) { 123 CflowField ret = (CflowField)cflowFields.get(inTypeDec); 124 if (ret == null) { 125 ret = new CflowField(inTypeDec); 126 cflowFields.put(inTypeDec, ret); 127 } 128 return ret; 129 } 130 131 private static int counter=0; 132 private static int ecounter = 0; 133 134 class CflowField implements CFlowPlanner { 135 private TypeDec declaringTypeDec = null; 136 private FieldDec stack; 137 138 public CflowField(TypeDec inTypeDec) { 139 this.declaringTypeDec = inTypeDec; 140 } 141 142 public boolean getIncludesRoot() { 143 return CFlowPcd.this.getIncludesRoot(); 144 } 145 146 FieldDec getStackField() { 147 if (stack != null) return stack; 148 149 final AST ast = getAST(); 150 String name = "cflow$ajc" + counter++; 151 Type type = getTypeManager().getType("org.aspectj.runtime.internal", "CFlowStack"); 152 153 Modifiers modifiers = 154 ast.makeModifiers(Modifiers.PUBLIC | Modifiers.STATIC | Modifiers.FINAL); 155 stack = ast.makeField(modifiers, type, name, ast.makeNew(type)); 156 158 declaringTypeDec.getBody().add(0, stack); 160 return stack; 161 } 162 163 164 Expr getStackVar() { 165 return getAST().makeGet(getStackField()); 166 } 167 168 Expr testStackExpr() { 169 return getAST().makeCall(getStackVar(), "isValid"); 170 } 171 172 Expr pushStackExpr(Expr expr) { 173 return getAST().makeCall(getStackVar(), "push", expr); 174 } 175 176 Expr popStackExpr() { 177 return getAST().makeCall(getStackVar(), "pop"); 178 } 179 180 Expr peekStackExpr() { 181 return getAST().makeCall(getStackVar(), "peekCFlow"); 182 } 183 184 void remapExprs(JpPlan plan) { 185 int index = 0; 186 for (Iterator i = flowState.iterator(); i.hasNext(); ) { 187 VarTypeName varTypeName = (VarTypeName)i.next(); 188 FormalDec formal = varTypeName.getFormalDec(); 189 190 Expr expr = makeFlowStateExpr(formal.getType(), index++); 191 plan.bindExpr(varTypeName.getFormalDec(), expr); 192 } 193 } 194 195 public Stmts wrapPushPop(JpPlan plan, Stmts body) { 197 final AST ast = getAST(); 198 199 Expr newCFlowExpr = makeNewCFlowExpr(plan); 200 201 Expr test = plan.getDynamicTest(); 202 if (test == null) { 203 return ast.makeStmts( 204 ast.makeStmt(pushStackExpr(newCFlowExpr)), 205 ast.makeTryFinally(ast.makeBlock(body), 206 ast.makeBlock(popStackExpr()))); 207 } else { 208 VarDec tmp = ast.makeFinalVar(getTypeManager().booleanType, 209 "ajc_enter_cflow_" + ecounter++, test); 210 return ast.makeStmts( 211 tmp, 212 ast.makeIf(ast.makeVar(tmp), 213 ast.makeStmt(pushStackExpr(newCFlowExpr))), 214 ast.makeTryFinally(ast.makeBlock(body), 215 ast.makeBlock(ast.makeIf(ast.makeVar(tmp), 216 ast.makeStmt(popStackExpr()))))); 217 } 218 } 219 220 Exprs initializeFlowState(JpPlan plan) { 221 final AST ast = getAST(); 222 223 int index = 0; 224 Exprs stateExprs = ast.makeExprs(); 226 227 for (Iterator i = flowState.iterator(); i.hasNext(); ) { 228 VarTypeName varTypeName = (VarTypeName)i.next(); 229 FormalDec formal = varTypeName.getFormalDec(); 230 Expr expr = (Expr)plan.bindings.get(formal); 231 if (expr == null) { 232 varTypeName.showError("no binding for this variable in enclosing cflow"); 233 } 234 235 expr = expr.getType().makeObject(expr); 237 stateExprs.add(expr); 238 } 239 240 Exprs ret = ast.makeExprs(); 241 if (stateExprs.size() != 0) { 242 ret.add(ast.makeObjectArray(stateExprs)); 243 } else { 244 return null; 245 } 246 return ret; 247 } 248 249 Expr makeFlowStateExpr(Type desiredType, int index) { 250 Expr objectExpr = 251 getAST().makeCall(peekStackExpr(), "get", getAST().makeLiteral(index)); 252 return desiredType.fromObject(objectExpr); 253 } 254 255 public Expr makeNewCFlow(Exprs baseExprs) { 256 Type cflowType; 257 if (baseExprs == null) { 258 baseExprs = getAST().makeExprs(); 259 cflowType = getTypeManager().getType("org.aspectj.runtime", "CFlow"); 260 } else { 261 cflowType = getTypeManager().getType("org.aspectj.runtime.internal", "CFlowPlusState"); 262 } 263 264 return getAST().makeNew(cflowType, baseExprs); 265 } 266 267 public Expr makeNewCFlowExpr(JpPlan plan) { 268 return makeNewCFlow(initializeFlowState(plan)); 269 } 270 271 272 273 } 274 275 276 277 278 280 protected Pcd pcd; 282 public Pcd getPcd() { return pcd; } 283 public void setPcd(Pcd _pcd) { 284 if (_pcd != null) _pcd.setParent(this); 285 pcd = _pcd; 286 } 287 288 protected boolean includesRoot; 289 public boolean getIncludesRoot() { return includesRoot; } 290 public void setIncludesRoot(boolean _includesRoot) { includesRoot = _includesRoot; } 291 292 public CFlowPcd(SourceLocation location, Pcd _pcd, boolean _includesRoot) { 293 super(location); 294 setPcd(_pcd); 295 setIncludesRoot(_includesRoot); 296 } 297 protected CFlowPcd(SourceLocation source) { 298 super(source); 299 } 300 301 public ASTObject copyWalk(CopyWalker walker) { 302 CFlowPcd ret = new CFlowPcd(getSourceLocation()); 303 ret.preCopy(walker, this); 304 if (pcd != null) ret.setPcd( (Pcd)walker.process(pcd) ); 305 ret.includesRoot = includesRoot; 306 return ret; 307 } 308 309 public ASTObject getChildAt(int childIndex) { 310 switch(childIndex) { 311 case 0: return pcd; 312 default: return super.getChildAt(childIndex); 313 } 314 } 315 public String getChildNameAt(int childIndex) { 316 switch(childIndex) { 317 case 0: return "pcd"; 318 default: return super.getChildNameAt(childIndex); 319 } 320 } 321 public void setChildAt(int childIndex, ASTObject child) { 322 switch(childIndex) { 323 case 0: setPcd((Pcd)child); return; 324 default: super.setChildAt(childIndex, child); return; 325 } 326 } 327 public int getChildCount() { 328 return 1; 329 } 330 331 public String getDefaultDisplayName() { 332 return "CFlowPcd(includesRoot: "+includesRoot+")"; 333 } 334 335 } 337 338 | Popular Tags |