KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > dev > jjs > impl > CatchBlockNormalizer


1 /*
2  * Copyright 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package com.google.gwt.dev.jjs.impl;
17
18 import com.google.gwt.dev.jjs.SourceInfo;
19 import com.google.gwt.dev.jjs.ast.Context;
20 import com.google.gwt.dev.jjs.ast.JBlock;
21 import com.google.gwt.dev.jjs.ast.JExpression;
22 import com.google.gwt.dev.jjs.ast.JExpressionStatement;
23 import com.google.gwt.dev.jjs.ast.JIfStatement;
24 import com.google.gwt.dev.jjs.ast.JInstanceOf;
25 import com.google.gwt.dev.jjs.ast.JLocal;
26 import com.google.gwt.dev.jjs.ast.JLocalRef;
27 import com.google.gwt.dev.jjs.ast.JMethod;
28 import com.google.gwt.dev.jjs.ast.JMethodCall;
29 import com.google.gwt.dev.jjs.ast.JModVisitor;
30 import com.google.gwt.dev.jjs.ast.JProgram;
31 import com.google.gwt.dev.jjs.ast.JReferenceType;
32 import com.google.gwt.dev.jjs.ast.JStatement;
33 import com.google.gwt.dev.jjs.ast.JThrowStatement;
34 import com.google.gwt.dev.jjs.ast.JTryStatement;
35
36 import java.util.ArrayList JavaDoc;
37 import java.util.List JavaDoc;
38
39 /**
40  * Merge multi-catch blocks into a single catch block that uses instanceof tests
41  * to determine which user block to run.
42  */

43 public class CatchBlockNormalizer {
44
45   /**
46    * Collapses all multi-catch blocks into a single catch block.
47    */

48   private class CollapseCatchBlocks extends JModVisitor {
49
50     // @Override
51
public void endVisit(JMethod x, Context ctx) {
52       clearLocals();
53       currentMethod = null;
54     }
55
56     // @Override
57
public void endVisit(JTryStatement x, Context ctx) {
58       if (x.getCatchBlocks().isEmpty()) {
59         return;
60       }
61
62       SourceInfo catchInfo = ((JBlock) x.getCatchBlocks().get(0)).getSourceInfo();
63
64       JLocal exObj = popTempLocal();
65       JLocalRef exRef = new JLocalRef(program, catchInfo, exObj);
66       JBlock newCatchBlock = new JBlock(program, catchInfo);
67       // $e = Exceptions.caught($e)
68
JMethod caughtMethod = program.getSpecialMethod("Exceptions.caught");
69       JMethodCall call = new JMethodCall(program, catchInfo, null, caughtMethod);
70       call.getArgs().add(exRef);
71       JExpressionStatement asg = program.createAssignmentStmt(catchInfo, exRef,
72           call);
73       newCatchBlock.statements.add(asg);
74
75       /*
76        * Build up a series of if, else if statements to test the type of the
77        * exception object against the type of the user's catch block.
78        *
79        * Go backwards so we can nest the else statements in the correct order!
80        */

81       // rethrow the current exception if no one caught it
82
JStatement cur = new JThrowStatement(program, null, exRef);
83       for (int i = x.getCatchBlocks().size() - 1; i >= 0; --i) {
84         JBlock block = (JBlock) x.getCatchBlocks().get(i);
85         JLocalRef arg = (JLocalRef) x.getCatchArgs().get(i);
86         catchInfo = block.getSourceInfo();
87         JReferenceType argType = (JReferenceType) arg.getType();
88         // if ($e instanceof Argtype) { userVar = $e; <user code> }
89
JExpression ifTest = new JInstanceOf(program, catchInfo, argType, exRef);
90         asg = program.createAssignmentStmt(catchInfo, arg, exRef);
91         if (!block.statements.isEmpty()) {
92           // Only bother adding the assingment if the block is non-empty
93
block.statements.add(0, asg);
94         }
95         // nest the previous as an else for me
96
cur = new JIfStatement(program, catchInfo, ifTest, block, cur);
97       }
98
99       newCatchBlock.statements.add(cur);
100       x.getCatchArgs().clear();
101       x.getCatchArgs().add(exRef);
102       x.getCatchBlocks().clear();
103       x.getCatchBlocks().add(newCatchBlock);
104     }
105
106     // @Override
107
public boolean visit(JMethod x, Context ctx) {
108       currentMethod = x;
109       clearLocals();
110       return true;
111     }
112
113     // @Override
114
public boolean visit(JTryStatement x, Context ctx) {
115       if (!x.getCatchBlocks().isEmpty()) {
116         pushTempLocal();
117       }
118       return true;
119     }
120   }
121
122   public static void exec(JProgram program) {
123     new CatchBlockNormalizer(program).execImpl();
124   }
125
126   private JMethod currentMethod;
127   private int localIndex;
128   private final JProgram program;
129   private final List JavaDoc/* <JLocal> */tempLocals = new ArrayList JavaDoc/* <JLocal> */();
130
131   private CatchBlockNormalizer(JProgram program) {
132     this.program = program;
133   }
134
135   private void clearLocals() {
136     tempLocals.clear();
137     localIndex = 0;
138   }
139
140   private void execImpl() {
141     CollapseCatchBlocks collapser = new CollapseCatchBlocks();
142     collapser.accept(program);
143   }
144
145   private JLocal popTempLocal() {
146     return (JLocal) tempLocals.get(--localIndex);
147   }
148
149   private void pushTempLocal() {
150     if (localIndex == tempLocals.size()) {
151       JLocal newTemp = program.createLocal(null,
152           ("$e" + localIndex).toCharArray(), program.getTypeJavaLangObject(),
153           false, currentMethod);
154       tempLocals.add(newTemp);
155     }
156     ++localIndex;
157   }
158
159 }
160
Popular Tags