KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > aspectj > compiler > base > ast > SwitchStmt


1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * This file is part of the compiler and core tools for the AspectJ(tm)
4  * programming language; see http://aspectj.org
5  *
6  * The contents of this file are subject to the Mozilla Public License
7  * Version 1.1 (the "License"); you may not use this file except in
8  * compliance with the License. You may obtain a copy of the License at
9  * either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/.
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is AspectJ.
17  *
18  * The Initial Developer of the Original Code is Xerox Corporation. Portions
19  * created by Xerox Corporation are Copyright (C) 1999-2002 Xerox Corporation.
20  * All Rights Reserved.
21  *
22  * Contributor(s):
23  */

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 JavaDoc;
38 import java.util.Arrays JavaDoc;
39
40 /**
41  * @grammar switch (expr) (clauses)
42  * @child Expr expr
43  * @child SwitchClauses clauses
44  */

45 public class SwitchStmt extends Stmt {
46
47     public boolean isBreakable() { return true; }
48
49     // ------------------------------
50
// INTRO from FlowCheckerPass
51

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     //INTRO from ScopePass
102
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 JavaDoc seenLabels = new HashSet JavaDoc();
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 JavaDoc intObj =
129                                 new Integer JavaDoc(((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     // ------------------------------
156
// Intro: ByteCodeCleanupPass
157

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     // ------------------------------
172
// bcg
173

174     protected void cgStmt(CodeBuilder cb) {
175         class Pair implements Comparable JavaDoc {
176             int i;
177             Label l;
178             Pair(int i, Label l) { this.i = i; this.l = l; }
179             public int compareTo(Object JavaDoc o) {
180                 int other = ((Pair)o).i;
181                 
182                 return (i > other) ? 1 : (i == other) ? 0 : -1;
183             }
184             public String JavaDoc 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         // do some analysis to build the switch stmt
195
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         //System.err.println("Pre-sort " + Arrays.asList(table));
213

214         Arrays.sort(table, 0, ti);
215
216         //System.err.println("Post-sort " + Arrays.asList(table));
217

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         // and do the body, finally
233
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     // ------------------------------
245
// Intro: FrameLocPass
246

247     // we might allocate something, so we must clean up.
248

249     public void walkFrameLoc(FrameLocPass walker) {
250         int start = walker.getfs();
251         super.walkFrameLoc(walker);
252         walker.setfs(start);
253     }
254
255     // ------------------------------
256
// INTRO from AssignmentCheckerPass
257

258     /*
259     public ASTObject postAssignmentCheck(AssignmentCheckerPass walker) {
260         boolean seenDefault = false;
261         final int len = clauses.size();
262         SwitchClause[] clauses = getClauses().children;
263         for (int i = 0; i < len; i++ ) {
264             SwitchClause clause = clauses[i];
265             Expr key = clause.getLabel();
266             if (key == null) {
267                 if (seenDefault) showError("Duplicate default clause");
268                 else seenDefault = true;
269             } else if (! (key instanceof IntLiteralExpr)) {
270                 key.showError("Must be an integer constant");
271             } else {
272                 Integer keyObj = new Integer(((IntLiteralExpr)key).getIntValue());
273                 if (seenKeys.contains(keyObj)) {
274                     key.showError("Duplicate case clause");
275                 } else {
276                     seenKeys.add(keyObj);
277                 }
278             }
279         }
280         return this;
281     }
282     */

283
284     //BEGIN: Generated from @child and @property
285
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 JavaDoc 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 JavaDoc getDefaultDisplayName() {
342         return "SwitchStmt()";
343     }
344
345     //END: Generated from @child and @property
346
}
347
348
349
Popular Tags