1 24 25 package org.aspectj.compiler.base; 26 27 import org.aspectj.compiler.base.ast.*; 28 import java.util.*; 29 30 public class LocalClassPass extends AbstractCompilerPass { 31 32 public LocalClassPass(JavaCompiler compiler) { 33 super(compiler); 34 } 35 36 public String getDisplayName() { 37 return "lifting local classes "; 38 } 39 40 public void transform(TypeDec typeDec) { 41 43 AnalysisWalker analysisWalker = new AnalysisWalker(getCompiler()); 45 analysisWalker.process(typeDec); 46 47 50 new LiftWalker(getCompiler()).process(typeDec); 52 53 new ThreadingWalker(getCompiler(), analysisWalker).process(typeDec); 55 56 } 58 59 public static class ThreadingWalker extends Walker { 62 HashMap needsVarTable; 63 HashMap needsFieldTable; 64 65 ThreadingWalker(JavaCompiler compiler, AnalysisWalker analysisWalker) { 66 super(compiler); 67 this.needsVarTable = analysisWalker.needsVarTable; 68 this.needsFieldTable = analysisWalker.needsFieldTable; 69 } 70 public ASTObject process(ASTObject object) { 71 object.preThreading(this); 72 object.walk(this); 73 return object.postThreading(this); 74 } 75 76 Stack typeContext = new Stack(); 77 Stack fieldContext = new Stack(); 78 Stack env = new Stack(); 79 80 { 81 fieldContext.push(new HashMap()); 82 } 83 84 public void pushConstructorEnv(Formals formals) { 85 final AST ast = getAST(); 86 Map envMap = new HashMap(); 87 Set s = (Set) needsVarTable.get(typeContext.peek()); 88 if (s != null) { 89 for (Iterator i = s.iterator(); i.hasNext(); ) { 90 VarDec varDec = (VarDec)i.next(); 91 FormalDec formalDec = 92 ast.makeFormal(varDec.getTypeD().getType(), 93 "val$" + varDec.getId()); 94 formals.add(0, formalDec); 95 envMap.put(varDec, formalDec); 96 } 97 } 98 env.push(envMap); 99 } 100 public void pushNonConstructorEnv() { 101 env.push(fieldContext.peek()); 102 } 103 public void popEnv() { 104 env.pop(); 105 } 106 107 public void pushTypeDec(TypeDec typeDec) { 108 respectOurParentsWishes(typeDec); 109 typeContext.push(typeDec); 110 addFields(typeDec); 111 } 112 public void popTypeDec() { 113 typeContext.pop(); 114 fieldContext.pop(); 115 } 116 117 private void addFields(TypeDec typeDec) { 118 final AST ast = getAST(); 119 Map envMap = new HashMap(); 120 Set s = (Set) needsFieldTable.get(typeContext.peek()); 121 if (s != null) { 122 for (Iterator i = s.iterator(); i.hasNext(); ) { 123 VarDec varDec = (VarDec)i.next(); 124 FieldDec fieldDec = 125 ast.makeField(ast.makeModifiers(Modifiers.FINAL), 126 varDec.getTypeD().getType(), 127 "val$" + varDec.getId()); 128 typeDec.getBody().add(fieldDec); 129 envMap.put(varDec, fieldDec); 130 } 131 } 132 fieldContext.push(envMap); 133 } 134 private void respectOurParentsWishes(TypeDec typeDec) { 135 Set weNeed = (Set) needsVarTable.get(typeDec); 136 Set parentNeeds = (Set) needsVarTable.get(typeDec.getSuperClassType().getTypeDec()); 137 Set enclosingHas; 138 if (typeDec.isInner()) { 139 enclosingHas = (Set) needsVarTable.get(typeDec.getEnclosingInstanceTypeDec()); 140 } else { 141 enclosingHas = null; 142 } 143 144 149 150 151 if (weNeed == null) { 152 if (parentNeeds != null) { 153 weNeed = new HashSet(parentNeeds); 154 if (enclosingHas != null) { 155 weNeed.removeAll(enclosingHas); 156 } 157 needsVarTable.put(typeDec, weNeed); 158 } 159 } else { 160 if (parentNeeds != null) { 161 weNeed.addAll(parentNeeds); 162 } 163 if (enclosingHas != null) { 164 weNeed.removeAll(enclosingHas); 165 } 166 } 167 169 } 170 171 public Object lookup(VarDec varDec) { 172 for (int i = env.size() - 1; i >= 0; i--) { 173 HashMap map = (HashMap) env.get(i); 174 Object o = map.get(varDec); 175 if (o != null) return o; 176 } 177 return null; 178 } 179 180 public void addArgs(Exprs args, TypeDec typeDec) { 181 final AST ast = getAST(); 182 Set s = (Set) needsVarTable.get(typeDec); 183 if (s == null) return; 184 for (Iterator i = s.iterator(); i.hasNext(); ) { 185 args.add(0, ast.makeVar((VarDec)i.next())); 186 } 187 } 188 189 public void addFieldSets(Stmts stmts) { 190 final AST ast = getAST(); 191 for (Iterator i = ((Map)fieldContext.peek()).entrySet().iterator(); 192 i.hasNext(); ) { 193 Map.Entry entry = (Map.Entry) i.next(); 194 VarDec varDec = (VarDec) entry.getKey(); 195 FieldDec fieldDec = (FieldDec) entry.getValue(); 196 stmts.add(0, ast.makeStmt(ast.makeSet(ast.makeDynamicGet(fieldDec), 197 ast.makeVar(varDec)))); 198 } 199 } 200 } 201 202 public static class LiftWalker extends Walker { 204 LiftWalker(JavaCompiler compiler) { 205 super(compiler); 206 } 207 public ASTObject process(ASTObject object) { 208 object.preLift(this); object.walk(this); 210 return object.postLift(this); } 212 private Stack decsStack = new Stack(); 213 214 private Decs decs = getAST().makeDecs(); 215 216 public void pushPendingDecs() { 217 decsStack.push(getAST().makeDecs()); 218 } 219 public void addToPendingDecs(TypeDec dec) { 220 ((Decs) decsStack.peek()).add(dec); 221 } 222 public void popPendingDecsInto(TypeDec dec) { 223 dec.getBody().addAll((Decs) decsStack.pop()); } 225 } 226 227 public static class AnalysisWalker extends Walker { 229 AnalysisWalker(JavaCompiler compiler) { 230 super(compiler); 231 } 232 public ASTObject process(ASTObject object) { 233 final int saved = this.context; 234 object.walkAnalysis(this); 235 this.context = saved; 236 return object; 237 } 238 private static final int NOWHERE = 0; 239 private static final int DYNAMIC = 1; private static final int SEMI_STATIC = 2; private static final int NIGH_STATIC = 3; private static final int STATIC = 4; 244 245 private int context = NOWHERE; 246 public void inType() { context = NOWHERE; } 247 public void inConstructor() { context = SEMI_STATIC; } 248 public void inConstructorCall() { context = NIGH_STATIC; } 249 public void inCode(boolean isStatic) { 250 context = isStatic ? STATIC : DYNAMIC; 251 } 252 253 HashMap needsVarTable = new HashMap(); 254 HashMap needsFieldTable = new HashMap(); 255 256 257 private Stack contextStack = new Stack(); 258 public void enterTypeDec(TypeDec typeDec) { 259 if (context == NIGH_STATIC || context == STATIC) { 260 typeDec.getModifiers().setStatic(true); 261 } 262 contextStack.push(new Integer (context)); 263 contextStack.push(typeDec); 264 } 265 public void leaveTypeDec() { 266 contextStack.pop(); 267 contextStack.pop(); 268 } 269 public void enterCodeDec(CodeDec codeDec) { 270 contextStack.push(codeDec); 271 } 272 public void leaveCodeDec() { 273 contextStack.pop(); 274 } 275 276 public void processVarExpr(VarExpr varExpr) { 277 VarDec varDec = varExpr.getVarDec(); 278 CodeDec referenceContextDec = varDec.getEnclosingCodeDec(); 279 int referenceContext = context; 280 281 if (contextStack.peek() == referenceContextDec) return; 283 284 if (!varDec.isFinal()) { 285 varExpr.showError("local variable " + varDec.getId() + 286 " is referenced from inside inner class; " + 287 " needs to be declared final"); 288 return; 289 } 290 291 for (int i = contextStack.size() - 2; i >= 0; i -= 3) { 292 if (referenceContext == STATIC) { 293 varExpr.showError("Not accessible from static context"); 294 break; 295 } 296 TypeDec typeDec = (TypeDec) contextStack.get(i); 297 int typeDecContext = ((Integer ) contextStack.get(i - 1)).intValue(); 298 CodeDec maybeDeclarationContextDec = (CodeDec) contextStack.get(i - 2); 299 300 if (maybeDeclarationContextDec == referenceContextDec) { 301 addToTable(needsVarTable, typeDec, varDec); 306 addToTable(needsFieldTable, typeDec, varDec); 308 break; 310 } else if (typeDecContext == NIGH_STATIC) { 311 addToTable(needsVarTable, typeDec, varDec); 312 if (referenceContext == DYNAMIC) { 313 addToTable(needsFieldTable, typeDec, varDec); 314 } 315 referenceContext = NIGH_STATIC; 316 } else { 317 referenceContext = DYNAMIC; 318 } 319 } 320 } 321 322 private static void addToTable(HashMap map, 323 Object key, Object elem) { 324 Object o = map.get(key); 326 if (o == null) { 327 Set s = new HashSet(); 328 s.add(elem); 329 map.put(key, s); 330 } else { 331 ((Set) o).add(elem); 332 } 333 } 334 335 private int localCounter = 0; 336 public String makeNewId(TypeDec typeDec) { 339 return typeDec.isAnonymous() ? 340 "_" + ++localCounter + "" : 341 "_" + ++localCounter + "_" + typeDec.getId(); 342 } 343 } 344 } 345 346 429 | Popular Tags |