KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > dev > jjs > ast > JModVisitor


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.ast;
17
18 import com.google.gwt.dev.jjs.InternalCompilerException;
19
20 import java.util.ArrayList JavaDoc;
21 import java.util.List JavaDoc;
22
23 /**
24  * A visitor for iterating through and modifying an AST.
25  */

26 public class JModVisitor extends JVisitor {
27
28   private interface ContextFactory {
29     Context create();
30   }
31
32   private class ContextPool extends ArrayList JavaDoc {
33
34     private ContextFactory factory;
35     private int pos = 0;
36
37     public ContextPool(ContextFactory factory) {
38       this.factory = factory;
39     }
40
41     public void release(Context ctx) {
42       if (get(--pos) != ctx) {
43         throw new InternalCompilerException(
44             "Tried to release the wrong context");
45       }
46     }
47
48     public Context take() {
49       if (pos == size()) {
50         add(factory.create());
51       }
52       return (Context) get(pos++);
53     }
54   }
55
56   private class ListContext implements Context {
57     private int index;
58     private List JavaDoc list;
59     private boolean removed;
60     private boolean replaced;
61
62     public boolean canInsert() {
63       return true;
64     }
65
66     public boolean canRemove() {
67       return true;
68     }
69
70     public void insertAfter(JNode node) {
71       checkRemoved();
72       list.add(index + 1, node);
73       didChange = true;
74     }
75
76     public void insertBefore(JNode node) {
77       checkRemoved();
78       list.add(index++, node);
79       didChange = true;
80     }
81
82     public void removeMe() {
83       checkState();
84       list.remove(index--);
85       didChange = removed = true;
86     }
87
88     public void replaceMe(JNode node) {
89       checkState();
90       checkReplacement((JNode) list.get(index), node);
91       list.set(index, node);
92       didChange = replaced = true;
93     }
94
95     protected void doReplace(Class JavaDoc targetClass, JNode x) {
96       checkState();
97       checkReplacement((JNode) list.get(index), x);
98       list.set(index, x);
99       didChange = replaced = true;
100     }
101
102     protected void traverse(List JavaDoc list) {
103       this.list = list;
104       for (index = 0; index < list.size(); ++index) {
105         removed = replaced = false;
106         doTraverse((JNode) list.get(index), this);
107       }
108     }
109
110     private void checkRemoved() {
111       if (removed) {
112         throw new InternalCompilerException("Node was already removed");
113       }
114     }
115
116     private void checkState() {
117       checkRemoved();
118       if (replaced) {
119         throw new InternalCompilerException("Node was already replaced");
120       }
121     }
122   }
123
124   private class NodeContext implements Context {
125     private JNode node;
126     private boolean replaced;
127
128     public boolean canInsert() {
129       return false;
130     }
131
132     public boolean canRemove() {
133       return false;
134     }
135
136     public void insertAfter(JNode node) {
137       throw new UnsupportedOperationException JavaDoc();
138     }
139
140     public void insertBefore(JNode node) {
141       throw new UnsupportedOperationException JavaDoc();
142     }
143
144     public void removeMe() {
145       throw new UnsupportedOperationException JavaDoc();
146     }
147
148     public void replaceMe(JNode node) {
149       if (replaced) {
150         throw new InternalCompilerException("Node was already replaced");
151       }
152       checkReplacement(this.node, node);
153       this.node = node;
154       didChange = replaced = true;
155     }
156
157     protected JNode traverse(JNode node) {
158       this.node = node;
159       replaced = false;
160       doTraverse(node, this);
161       return this.node;
162     }
163   }
164
165   protected static void checkReplacement(JNode origNode, JNode newNode) {
166     if (newNode == null) {
167       throw new InternalCompilerException("Cannot replace with null");
168     }
169     if (newNode == origNode) {
170       throw new InternalCompilerException(
171           "The replacement is the same as the original");
172     }
173   }
174
175   protected boolean didChange = false;
176
177   private final ContextPool listContextPool = new ContextPool(
178       new ContextFactory() {
179         public Context create() {
180           return new ListContext();
181         }
182       });
183
184   private final ContextPool nodeContextPool = new ContextPool(
185       new ContextFactory() {
186         public Context create() {
187           return new NodeContext();
188         }
189       });
190
191   public boolean didChange() {
192     return didChange;
193   }
194
195   protected JNode doAccept(JNode node) {
196     NodeContext ctx = (NodeContext) nodeContextPool.take();
197     try {
198       return ctx.traverse(node);
199     } finally {
200       nodeContextPool.release(ctx);
201     }
202   }
203
204   protected void doAccept(List JavaDoc list) {
205     NodeContext ctx = (NodeContext) nodeContextPool.take();
206     try {
207       for (int i = 0, c = list.size(); i < c; ++i) {
208         list.set(i, ctx.traverse((JNode) list.get(i)));
209       }
210     } finally {
211       nodeContextPool.release(ctx);
212     }
213   }
214
215   protected void doAcceptWithInsertRemove(List JavaDoc list) {
216     ListContext ctx = (ListContext) listContextPool.take();
217     try {
218       ctx.traverse(list);
219     } finally {
220       listContextPool.release(ctx);
221     }
222   }
223
224 }
225
Popular Tags