1 24 25 package org.aspectj.compiler.base.ast; 26 27 import org.aspectj.compiler.base.*; 28 29 import org.aspectj.compiler.base.AssignmentCheckerPass; 30 import org.aspectj.compiler.base.JavaCompiler; 31 import org.aspectj.compiler.base.CodeWriter; 32 import org.aspectj.compiler.base.cst.*; 33 34 import org.aspectj.compiler.base.bcg.CodeBuilder; 35 import org.aspectj.compiler.base.bcg.Label; 36 37 import java.util.HashSet ; 38 import java.util.Arrays ; 39 40 45 public class SwitchStmt extends Stmt { 46 47 public boolean isBreakable() { return true; } 48 49 52 public void walkFlow(FlowCheckerPass w) { 53 SwitchClauses c = getClauses(); 54 w.process(getExpr()); 55 FlowCheckerPass.Vars v = w.getVars(); 56 57 for (int i = 0, len = c.size(); i < len; i++) { 58 v = findTopLevelVars(v, c.get(i).getStmts()); 59 } 60 w.setVars(v); 61 w.enterContext(this); 62 boolean hasDefault = false; 63 for (int i = 0, len = c.size(); i < len; i++) { 64 if (c.get(i).getLabel() == null) { hasDefault = true; } 65 w.setLive(true); 66 w.setVars(v.join(w.getVars())); 67 w.process(c.get(i)); 68 w.setVars(w.getVars()); 69 } 70 w.leaveContext(); 71 if (!hasDefault) w.setVars(w.getVars().join(v)); 72 73 FlowCheckerPass.Vars bv = w.getBreakVars(this); 74 75 w.setLive(w.isLive() || ! hasDefault || w.isBroken(this)); 76 w.setVars(w.getVars().join(bv)); 77 } 78 79 private FlowCheckerPass.Vars findTopLevelVars(FlowCheckerPass.Vars v, Stmts ss) { 80 for (int i = 0, len = ss.size(); i < len; i++) { 81 Stmt s = ss.get(i); 82 if (s instanceof VarDec) { 83 v = v.addUnassigned((VarDec) s); 84 } else if (s instanceof Decs) { 85 v = findTopLevelVars(v, (Decs) s); 86 } 87 } 88 return v; 89 } 90 91 private FlowCheckerPass.Vars findTopLevelVars(FlowCheckerPass.Vars v, Decs ds) { 92 for (int i = 0, len = ds.size(); i < len; i++) { 93 Dec d = ds.get(i); 94 if (d instanceof VarDec) { 95 v = v.addUnassigned((VarDec) d); 96 } 97 } 98 return v; 99 } 100 101 public void preScope(ScopeWalker walker) { walker.pushBlock(); } 103 public ASTObject postScope(ScopeWalker walker) { walker.popBlock(); return this; } 104 105 public void checkSpec() { 106 Type exprType = expr.getType(); 107 if (! (exprType instanceof IntishType)) { 108 expr.showTypeError(exprType, getTypeManager().intType); 109 } 110 boolean hasDefault = false; 111 HashSet seenLabels = new HashSet (); 112 113 for (int i = 0, len = clauses.size(); i < len; i++) { 114 SwitchClause c = clauses.get(i); 115 Expr label = c.getLabel(); 116 if (label == null) { 117 if (hasDefault) { 118 c.showError("duplicate default label"); 119 } else { 120 hasDefault = true; 121 } 122 } else { 123 if (label instanceof LiteralExpr) { 124 if (!label.isAssignableTo(exprType)) { 125 label.showTypeError(label.getType(), exprType); 126 } else { 127 if (label instanceof IntLiteralExpr) { 128 Integer intObj = 129 new Integer (((IntLiteralExpr)label).getIntValue()); 130 if (seenLabels.contains(intObj)) { 131 label.showError("duplicate label"); 132 } else { 133 seenLabels.add(intObj); 134 } 135 } else { 136 label.showError("expected int constant"); 137 } 138 } 139 } else { 140 label.showError("constant expression required"); 141 } 142 } 143 } 144 } 145 146 public void unparse(CodeWriter writer) { 147 writer.writeKeyword("switch"); 148 writer.requiredSpace(); 149 writer.parenExpr(expr); 150 writer.openBlock(); 151 writer.writeChildren(clauses); 152 writer.closeBlock(); 153 } 154 155 158 public void walkCleanup(ByteCodeCleanupPass w) { 159 SwitchClauses c = getClauses(); 160 w.enterContext(this); 161 boolean hasDefault = false; 162 for (int i = 0, len = c.size(); i < len; i++) { 163 if (c.get(i).getLabel() == null) { hasDefault = true; } 164 w.setLive(true); 165 c.get(i).getStmts().walkCleanup(w); 166 } 167 w.leaveContext(); 168 w.setLive(w.isLive() || ! hasDefault || w.isBroken(this)); 169 } 170 171 174 protected void cgStmt(CodeBuilder cb) { 175 class Pair implements Comparable { 176 int i; 177 Label l; 178 Pair(int i, Label l) { this.i = i; this.l = l; } 179 public int compareTo(Object o) { 180 int other = ((Pair)o).i; 181 182 return (i > other) ? 1 : (i == other) ? 0 : -1; 183 } 184 public String toString() { 185 return "<" + i + ", " + "l" + ">"; 186 } 187 } 188 189 Label endLab = cb.genLabel(); 190 Label defaultLab = endLab; 191 192 final int len = getClauses().size(); 193 194 boolean hasCases = false; 196 Pair[] table = new Pair[len]; 197 Label[] clauseStarts = new Label[len]; 198 int ti = 0; 199 for (int i = 0; i < len; i++ ) { 200 SwitchClause clause = getClauses().get(i); 201 IntLiteralExpr caseLabel = (IntLiteralExpr) clause.getLabel(); 202 Label caseCodeLabel = cb.genLabel(); 203 clauseStarts[i] = caseCodeLabel; 204 if (caseLabel == null) { 205 defaultLab = caseCodeLabel; 206 } else { 207 hasCases = true; 208 table[ti++] = new Pair(caseLabel.getIntValue(), caseCodeLabel); 209 } 210 } 211 212 214 Arrays.sort(table, 0, ti); 215 216 218 int[] keys = new int[ti]; 219 Label[] labels = new Label[ti]; 220 for (int i = 0; i < ti; i++) { 221 keys[i] = table[i].i; 222 labels[i] = table[i].l; 223 } 224 225 if (hasCases) { 226 getExpr().cgValue(cb); 227 cb.emitSwitch(keys, labels, defaultLab); 228 } else { 229 getExpr().cgEffect(cb); 230 } 231 232 cb.enterNonWindingContext(this, endLab, null); 234 for (int i = 0; i < len; i++ ) { 235 Label caseCodeLabel = clauseStarts[i]; 236 Stmts caseCode = getClauses().get(i).getStmts(); 237 cb.emitLabel(caseCodeLabel); 238 caseCode.cgStmts(cb); 239 } 240 cb.leaveContext(); 241 cb.emitLabel(endLab); 242 } 243 244 247 249 public void walkFrameLoc(FrameLocPass walker) { 250 int start = walker.getfs(); 251 super.walkFrameLoc(walker); 252 walker.setfs(start); 253 } 254 255 258 283 284 protected Expr expr; 286 public Expr getExpr() { return expr; } 287 public void setExpr(Expr _expr) { 288 if (_expr != null) _expr.setParent(this); 289 expr = _expr; 290 } 291 292 protected SwitchClauses clauses; 293 public SwitchClauses getClauses() { return clauses; } 294 public void setClauses(SwitchClauses _clauses) { 295 if (_clauses != null) _clauses.setParent(this); 296 clauses = _clauses; 297 } 298 299 public SwitchStmt(SourceLocation location, Expr _expr, SwitchClauses _clauses) { 300 super(location); 301 setExpr(_expr); 302 setClauses(_clauses); 303 } 304 protected SwitchStmt(SourceLocation source) { 305 super(source); 306 } 307 308 public ASTObject copyWalk(CopyWalker walker) { 309 SwitchStmt ret = new SwitchStmt(getSourceLocation()); 310 ret.preCopy(walker, this); 311 if (expr != null) ret.setExpr( (Expr)walker.process(expr) ); 312 if (clauses != null) ret.setClauses( (SwitchClauses)walker.process(clauses) ); 313 return ret; 314 } 315 316 public ASTObject getChildAt(int childIndex) { 317 switch(childIndex) { 318 case 0: return expr; 319 case 1: return clauses; 320 default: return super.getChildAt(childIndex); 321 } 322 } 323 public String getChildNameAt(int childIndex) { 324 switch(childIndex) { 325 case 0: return "expr"; 326 case 1: return "clauses"; 327 default: return super.getChildNameAt(childIndex); 328 } 329 } 330 public void setChildAt(int childIndex, ASTObject child) { 331 switch(childIndex) { 332 case 0: setExpr((Expr)child); return; 333 case 1: setClauses((SwitchClauses)child); return; 334 default: super.setChildAt(childIndex, child); return; 335 } 336 } 337 public int getChildCount() { 338 return 2; 339 } 340 341 public String getDefaultDisplayName() { 342 return "SwitchStmt()"; 343 } 344 345 } 347 348 349 | Popular Tags |