KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > ext > jl > ast > Try_c


1 package polyglot.ext.jl.ast;
2
3 import polyglot.ast.*;
4 import polyglot.util.*;
5 import polyglot.types.*;
6 import polyglot.visit.*;
7 import java.util.*;
8
9 /**
10  * An immutable representation of a <code>try</code> block, one or more
11  * <code>catch</code> blocks, and an optional <code>finally</code> block.
12  */

13 public class Try_c extends Stmt_c implements Try
14 {
15     protected Block tryBlock;
16     protected List catchBlocks;
17     protected Block finallyBlock;
18
19     public Try_c(Position pos, Block tryBlock, List catchBlocks, Block finallyBlock) {
20     super(pos);
21     this.tryBlock = tryBlock;
22     this.catchBlocks = TypedList.copyAndCheck(catchBlocks, Catch.class, true);
23     this.finallyBlock = finallyBlock;
24     }
25
26     /** Get the try block of the statement. */
27     public Block tryBlock() {
28     return this.tryBlock;
29     }
30
31     /** Set the try block of the statement. */
32     public Try tryBlock(Block tryBlock) {
33     Try_c n = (Try_c) copy();
34     n.tryBlock = tryBlock;
35     return n;
36     }
37
38     /** Get the catch blocks of the statement. */
39     public List catchBlocks() {
40     return Collections.unmodifiableList(this.catchBlocks);
41     }
42
43     /** Set the catch blocks of the statement. */
44     public Try catchBlocks(List catchBlocks) {
45     Try_c n = (Try_c) copy();
46     n.catchBlocks = TypedList.copyAndCheck(catchBlocks, Catch.class, true);
47     return n;
48     }
49
50     /** Get the finally block of the statement. */
51     public Block finallyBlock() {
52     return this.finallyBlock;
53     }
54
55     /** Set the finally block of the statement. */
56     public Try finallyBlock(Block finallyBlock) {
57     Try_c n = (Try_c) copy();
58     n.finallyBlock = finallyBlock;
59     return n;
60     }
61
62     /** Reconstruct the statement. */
63     protected Try_c reconstruct(Block tryBlock, List catchBlocks, Block finallyBlock) {
64     if (tryBlock != this.tryBlock || ! CollectionUtil.equals(catchBlocks, this.catchBlocks) || finallyBlock != this.finallyBlock) {
65         Try_c n = (Try_c) copy();
66         n.tryBlock = tryBlock;
67         n.catchBlocks = TypedList.copyAndCheck(catchBlocks, Catch.class, true);
68         n.finallyBlock = finallyBlock;
69         return n;
70     }
71
72     return this;
73     }
74
75     /** Visit the children of the statement. */
76     public Node visitChildren(NodeVisitor v) {
77     Block tryBlock = (Block) visitChild(this.tryBlock, v);
78     List catchBlocks = visitList(this.catchBlocks, v);
79     Block finallyBlock = (Block) visitChild(this.finallyBlock, v);
80     return reconstruct(tryBlock, catchBlocks, finallyBlock);
81     }
82
83     /**
84      * Bypass all children when peforming an exception check.
85      * exceptionCheck(), called from ExceptionChecker.leave(),
86      * will handle visiting children.
87      */

88     public NodeVisitor exceptionCheckEnter(ExceptionChecker ec)
89     throws SemanticException
90     {
91         ec = (ExceptionChecker) super.exceptionCheckEnter(ec);
92         return ec.bypassChildren(this);
93     }
94
95     /**
96      * Performs exceptionChecking. This is a special method that is called
97      * via the exceptionChecker's override method (i.e, doesn't follow the
98      * standard model for visitation.
99      *
100      * @param ec The ExceptionChecker that was run against the
101      * child node. It contains the exceptions that can be thrown by the try
102      * block.
103      */

104     public Node exceptionCheck(ExceptionChecker ec)
105     throws SemanticException
106     {
107     TypeSystem ts = ec.typeSystem();
108
109     // Visit the try block.
110
ec = ec.push();
111     Block tryBlock = (Block) visitChild(this.tryBlock, ec);
112     // First, get exceptions from the try block.
113
SubtypeSet thrown = ec.throwsSet();
114         SubtypeSet caught = new SubtypeSet(ts.Throwable());
115         ec = ec.pop();
116
117     // Add the unchecked exceptions.
118
thrown.addAll(ts.uncheckedExceptions());
119
120     // Walk through our catch blocks, making sure that they each can
121
// catch something.
122
for (Iterator i = this.catchBlocks.iterator(); i.hasNext(); ) {
123         Catch cb = (Catch) i.next();
124         Type catchType = cb.catchType();
125
126         // Check if the catch type is a supertype or a subtype of an
127
// exception thrown in the try block.
128

129         boolean match = false;
130         for (Iterator j = thrown.iterator(); j.hasNext(); ) {
131         Type ex = (Type) j.next();
132
133         if (ts.isSubtype(ex, catchType) ||
134                     ts.isSubtype(catchType, ex)) {
135             match = true;
136             break;
137         }
138         }
139
140         if (! match) {
141         throw new SemanticException("The exception \"" +
142             catchType + "\" is not thrown in the try block.",
143             cb.position());
144         }
145
146         // Check if the exception has already been caught.
147
if (caught.contains(catchType)) {
148         throw new SemanticException("The exception \"" +
149             catchType + "\" has been caught by an earlier catch block.",
150             cb.position());
151         }
152
153         caught.add(catchType);
154     }
155
156     // Remove exceptions which have been caught.
157
thrown.removeAll(caught);
158
159     // "thrown" now contains any exceptions which were not caught.
160
// We now visit the catch blocks and finallyBlock to get the
161
// exceptions they throw.
162

163     List catchBlocks = new ArrayList(this.catchBlocks.size());
164
165     for (Iterator i = this.catchBlocks.iterator(); i.hasNext(); ) {
166         Catch cb = (Catch) i.next();
167
168             ec = ec.push();
169
170         cb = (Catch) visitChild(cb, ec);
171         catchBlocks.add(cb);
172
173         thrown.addAll(ec.throwsSet());
174             ec = ec.pop();
175     }
176
177     Block finallyBlock = null;
178
179     if (this.finallyBlock != null) {
180             ec = ec.push();
181
182         finallyBlock = (Block) visitChild(this.finallyBlock, ec);
183
184             // an interesting thing happens here...
185
// if the finally block can complete normally, then all the
186
// exceptions that the try-block and catch-blocks can throw
187
// can be thrown by the try-catch-finally block. HOWEVER, if
188
// the finally block can not complete normally, then the
189
// try-catch-finally block can only throw the exceptions thrown
190
// by the finally block. Examining the finally-block's reachability
191
// will tell us if the finally-block can complete normally.
192
if (!this.finallyBlock.reachable()) {
193
194                 // warn the user, and remove all the exceptions that have
195
// been added by the try and catch blocks.
196

197                 if (false) {
198                       // don't warn the user; javac doesn't
199
ec.errorQueue().enqueue(ErrorInfo.WARNING,
200                             "The finally block cannot complete normally",
201                             finallyBlock.position());
202                 }
203                 
204                 thrown.clear();
205             }
206             thrown.addAll(ec.throwsSet());
207             
208             ec = ec.pop();
209     }
210     
211         // "thrown" now contains any exceptions which were not caught,
212
// and any exceptions thrown by the catch blocks and finallyBlock
213
// Add these exceptions to the exception checker's throw set.
214
ec.throwsSet().addAll(thrown);
215
216     return reconstruct(tryBlock, catchBlocks, finallyBlock).exceptions(ec.throwsSet());
217     }
218
219     public String JavaDoc toString() {
220         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
221         sb.append("try ");
222         sb.append(tryBlock.toString());
223
224         int count = 0;
225
226     for (Iterator it = catchBlocks.iterator(); it.hasNext(); ) {
227         Catch cb = (Catch) it.next();
228
229             if (count++ > 2) {
230               sb.append("...");
231               break;
232             }
233
234             sb.append(" ");
235             sb.append(cb.toString());
236         }
237
238         if (finallyBlock != null) {
239             sb.append(" finally ");
240             sb.append(finallyBlock.toString());
241         }
242
243         return sb.toString();
244     }
245
246     public void prettyPrint(CodeWriter w, PrettyPrinter tr) {
247     w.write("try");
248     printSubStmt(tryBlock, w, tr);
249
250     for (Iterator it = catchBlocks.iterator(); it.hasNext(); ) {
251         Catch cb = (Catch) it.next();
252         w.newline(0);
253         printBlock(cb, w, tr);
254     }
255
256     if (finallyBlock != null) {
257         w.newline(0);
258         w.write ("finally");
259         printSubStmt(finallyBlock, w, tr);
260     }
261     }
262
263     public Term entry() {
264         return tryBlock.entry();
265     }
266
267     public List acceptCFG(CFGBuilder v, List succs) {
268         // Add edges from the try entry to any catch blocks for Error and
269
// RuntimeException.
270
TypeSystem ts = v.typeSystem();
271
272         CFGBuilder v1 = v.push(this, false);
273         CFGBuilder v2 = v.push(this, true);
274
275         for (Iterator i = ts.uncheckedExceptions().iterator(); i.hasNext(); ) {
276             Type type = (Type) i.next();
277             v1.visitThrow(tryBlock.entry(), type);
278         }
279
280         Term next;
281
282         // Handle the normal return case. The throw case will be handled
283
// specially.
284
if (finallyBlock == null) {
285             next = this;
286         }
287         else {
288             next = finallyBlock.entry();
289             v.visitCFG(finallyBlock, this);
290         }
291
292         v1.visitCFG(tryBlock, next);
293
294         for (Iterator it = catchBlocks.iterator(); it.hasNext(); ) {
295             Catch cb = (Catch) it.next();
296             v2.visitCFG(cb, next);
297         }
298
299         return succs;
300     }
301 }
302
Popular Tags