KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > ext > coffer > visit > KeyChecker


1 package polyglot.ext.coffer.visit;
2
3 import java.util.*;
4 import java.util.Map.Entry;
5
6 import polyglot.ast.NodeFactory;
7 import polyglot.ast.ProcedureDecl;
8 import polyglot.ast.Term;
9 import polyglot.ext.coffer.Topics;
10 import polyglot.ext.coffer.extension.CofferExt;
11 import polyglot.ext.coffer.extension.ProcedureDeclExt_c;
12 import polyglot.ext.coffer.types.*;
13 import polyglot.ext.coffer.types.CofferClassType;
14 import polyglot.ext.coffer.types.CofferProcedureInstance;
15 import polyglot.ext.coffer.types.CofferTypeSystem;
16 import polyglot.ext.coffer.types.KeySet;
17 import polyglot.frontend.Job;
18 import polyglot.main.Report;
19 import polyglot.types.SemanticException;
20 import polyglot.types.Type;
21 import polyglot.types.TypeSystem;
22 import polyglot.util.InternalCompilerError;
23 import polyglot.util.Position;
24 import polyglot.visit.DataFlow;
25 import polyglot.visit.FlowGraph;
26 import polyglot.visit.FlowGraph.EdgeKey;
27 import polyglot.visit.FlowGraph.ExceptionEdgeKey;
28
29 /**
30  * Data flow analysis to compute and check held key sets.
31  */

32 public class KeyChecker extends DataFlow
33 {
34     public KeyChecker(Job job, TypeSystem ts, NodeFactory nf) {
35         super(job, ts, nf, true /* forward analysis */);
36         CofferTypeSystem vts = (CofferTypeSystem) ts;
37         EMPTY = vts.emptyKeySet(Position.COMPILER_GENERATED);
38     }
39
40     public Item createInitialItem(FlowGraph graph, Term node) {
41         ProcedureDecl decl = (ProcedureDecl) graph.root();
42         CofferProcedureInstance pi = (CofferProcedureInstance)
43             decl.procedureInstance();
44
45         CofferClassType t = (CofferClassType) pi.container();
46
47         KeySet held = pi.entryKeys();
48         KeySet stored = EMPTY;
49
50         if (t.key() != null) {
51             stored = stored.add(t.key());
52             stored = stored.retainAll(held);
53         }
54
55         return new DataFlowItem(held, held, stored, stored);
56     }
57
58     KeySet EMPTY;
59
60     class ExitTermItem extends Item {
61         DataFlowItem nonExItem;
62         Map excEdgesToItems; // map from ExceptionEdgeKeys to DataFlowItems
63
public ExitTermItem(DataFlowItem nonExItem, Map excItems) {
64             this.nonExItem = nonExItem;
65             this.excEdgesToItems = excItems;
66         }
67
68         public boolean equals(Object JavaDoc i) {
69             if (i instanceof ExitTermItem) {
70                 ExitTermItem that = (ExitTermItem)i;
71                 return this.excEdgesToItems.equals(that.excEdgesToItems) &&
72                        this.nonExItem.equals(that.nonExItem);
73             }
74             return false;
75         }
76
77         public int hashCode() {
78             return nonExItem.hashCode() + excEdgesToItems.hashCode();
79         }
80     }
81
82     class DataFlowItem extends Item {
83         // keys that must/may be held at this point
84
KeySet must_held;
85         KeySet may_held;
86
87         // keys that must/may be stored at this point
88
KeySet must_stored;
89         KeySet may_stored;
90
91         private DataFlowItem() {
92             this(EMPTY, EMPTY, EMPTY, EMPTY);
93         }
94
95         private DataFlowItem(KeySet must_held, KeySet may_held,
96                              KeySet must_stored, KeySet may_stored) {
97             this.must_held = must_held;
98             this.may_held = may_held;
99             this.must_stored = must_stored;
100             this.may_stored = may_stored;
101         }
102
103         public String JavaDoc toString() {
104             return "held_keys(must_held=" + must_held + ", " +
105                              "may_held=" + may_held + ", " +
106                              "must_stored=" + must_stored + ", " +
107                              "may_stored=" + may_stored + ")";
108         }
109
110         public boolean equals(Object JavaDoc o) {
111             if (o instanceof DataFlowItem) {
112                 DataFlowItem that = (DataFlowItem) o;
113                 return this.must_held.equals(that.must_held)
114                     && this.may_held.equals(that.may_held)
115                     && this.must_stored.equals(that.must_stored)
116                     && this.may_stored.equals(that.may_stored);
117             }
118             return false;
119         }
120
121         public int hashCode() {
122             return must_held.hashCode() + may_held.hashCode() +
123                    must_stored.hashCode() + may_stored.hashCode();
124         }
125     }
126
127     public Map flow(Item in, FlowGraph graph, Term n, Set succEdgeKeys) {
128         if (in instanceof ExitTermItem) {
129             return itemToMap(in, succEdgeKeys);
130         }
131
132         DataFlowItem df = (DataFlowItem) in;
133
134         if (n.ext() instanceof CofferExt) {
135             CofferExt ext = (CofferExt) n.ext();
136
137             Map m = new HashMap();
138
139             for (Iterator i = succEdgeKeys.iterator(); i.hasNext(); ) {
140                 FlowGraph.EdgeKey e = (FlowGraph.EdgeKey) i.next();
141                 Type t = null;
142
143                 if (e instanceof FlowGraph.ExceptionEdgeKey) {
144                     t = ((FlowGraph.ExceptionEdgeKey) e).type();
145                 }
146
147                 KeySet must_held = ext.keyFlow(df.must_held, t);
148                 KeySet may_held = ext.keyFlow(df.may_held, t);
149                 KeySet must_stored = ext.keyAlias(df.must_stored, t);
150                 KeySet may_stored = ext.keyAlias(df.may_stored, t);
151
152                 must_stored = must_stored.retainAll(must_held);
153                 may_stored = may_stored.retainAll(may_held);
154
155                 DataFlowItem newdf = new DataFlowItem(must_held, may_held,
156                                                       must_stored, may_stored);
157
158                 if (Report.should_report(Topics.keycheck, 2)) {
159                     Report.report(2, "flow(" + n + "):");
160                     Report.report(2, " " + df);
161                     Report.report(2, " ->" + newdf);
162                 }
163
164                 m.put(e, newdf);
165             }
166
167             return m;
168         }
169
170         return itemToMap(in, succEdgeKeys);
171     }
172
173     protected Item safeConfluence(List items, List itemKeys, Term node, FlowGraph graph) {
174         if (node == graph.exitNode()) {
175             return confluenceExitTerm(items, itemKeys, graph);
176         }
177         return super.safeConfluence(items, itemKeys, node, graph);
178     }
179
180     protected Item confluence(List items, List itemKeys, Term node, FlowGraph graph) {
181         if (node == graph.exitNode()) {
182             return confluenceExitTerm(items, itemKeys, graph);
183         }
184         return confluence(items, node, graph);
185     }
186
187     protected Item confluenceExitTerm(List items, List itemKeys, FlowGraph graph) {
188         List nonExcItems = filterItemsNonException(items, itemKeys);
189         DataFlowItem nonExc;
190
191         if (nonExcItems.isEmpty()) {
192             nonExc = new DataFlowItem();
193         }
194         else {
195             nonExc = (DataFlowItem)confluence(nonExcItems, graph.exitNode(), graph);
196         }
197
198         Map excItemLists = new HashMap();
199         for (Iterator i = items.iterator(), j = itemKeys.iterator();
200              i.hasNext() && j.hasNext(); ) {
201             FlowGraph.EdgeKey key = (EdgeKey)j.next();
202             DataFlowItem item = (DataFlowItem)i.next();
203             if (key instanceof FlowGraph.ExceptionEdgeKey) {
204                 List l = (List)excItemLists.get(key);
205                 if (l == null) {
206                         l = new ArrayList();
207                         excItemLists.put(key, l);
208                 }
209                 l.add(item);
210             }
211         }
212
213         Map excItems = new HashMap(excItemLists.size());
214         for (Iterator i = excItemLists.entrySet().iterator(); i.hasNext(); ) {
215                 Map.Entry e = (Entry)i.next();
216                 excItems.put(e.getKey(), confluence((List)e.getValue(), graph.exitNode(), graph));
217         }
218         return new ExitTermItem(nonExc, excItems);
219     }
220
221     protected Item confluence(List inItems, Term node, FlowGraph graph) {
222         DataFlowItem outItem = null;
223
224         for (Iterator i = inItems.iterator(); i.hasNext(); ) {
225             DataFlowItem df = (DataFlowItem) i.next();
226
227             if (outItem == null) {
228                 outItem = new DataFlowItem(df.must_held, df.may_held,
229                                            df.must_stored, df.may_stored);
230                 continue;
231             }
232
233             outItem.must_held = outItem.must_held.retainAll(df.must_held);
234             outItem.may_held = outItem.may_held.addAll(df.may_held);
235
236             outItem.must_stored = outItem.must_stored.retainAll(df.must_stored);
237             outItem.may_stored = outItem.may_stored.addAll(df.may_stored);
238
239             outItem.must_stored = outItem.must_stored.retainAll(outItem.must_held);
240             outItem.may_stored = outItem.may_stored.retainAll(outItem.may_held);
241         }
242
243         if (outItem == null)
244             throw new InternalCompilerError("confluence called with insufficient input items.");
245
246         if (Report.should_report(Topics.keycheck, 2)) {
247             Report.report(2, "confluence(" + node + "):");
248
249             for (Iterator i = inItems.iterator(); i.hasNext(); ) {
250                 DataFlowItem df = (DataFlowItem) i.next();
251                 Report.report(2, " " + df);
252             }
253
254             Report.report(2, " ->" + outItem);
255         }
256
257         return outItem;
258     }
259
260     public void check(FlowGraph graph, Term n, Item inItem, Map outItems)
261         throws SemanticException
262     {
263         if (n == graph.exitNode()) {
264             checkExitTerm(graph, (ExitTermItem)inItem);
265         }
266         else {
267             DataFlowItem df = (DataFlowItem) inItem;
268             check(n, df, true);
269         }
270     }
271
272     private void check(Term n, DataFlowItem df, boolean checkHeldKeys) throws SemanticException {
273         if (df == null) {
274             return;
275         }
276
277         if (Report.should_report(Topics.keycheck, 2)) {
278             Report.report(2, "check(" + n + "):");
279             Report.report(2, " " + df);
280         }
281
282         if (! df.must_held.containsAll(df.may_held)) {
283             KeySet s = df.may_held.removeAll(df.must_held);
284             throw new SemanticException("Keys " + s + " may not be held.",
285                                         n.position());
286         }
287
288         if (! df.must_stored.containsAll(df.may_stored)) {
289             KeySet s = df.may_stored.removeAll(df.must_stored);
290             throw new SemanticException("Keys " + s + " may not be saved" +
291                                         " in a local variable.", n.position());
292         }
293
294         if (checkHeldKeys && n.ext() instanceof CofferExt) {
295             CofferExt ext = (CofferExt) n.ext();
296             ext.checkHeldKeys(df.must_held, df.must_stored);
297         }
298     }
299
300     private void checkExitTerm(FlowGraph graph, ExitTermItem item)
301         throws SemanticException
302     {
303         check(graph.exitNode(), item.nonExItem, true);
304
305         List excepts;
306         ProcedureDeclExt_c ext = null;
307         
308         if (graph.exitNode() instanceof ProcedureDecl) {
309             ProcedureDecl pd = (ProcedureDecl)graph.exitNode();
310             CofferProcedureInstance pi = (CofferProcedureInstance)pd.procedureInstance();
311             excepts = pi.throwConstraints();
312             ext = (ProcedureDeclExt_c)pd.ext();
313         }
314         else {
315             excepts = new ArrayList();
316             for (Iterator i = item.excEdgesToItems.keySet().iterator(); i.hasNext(); ) {
317                 FlowGraph.ExceptionEdgeKey key = (ExceptionEdgeKey)i.next();
318                 excepts.add(key.type());
319             }
320         }
321
322         List excKeys = new ArrayList();
323         List excItems = new ArrayList();
324
325         for (Iterator i = item.excEdgesToItems.entrySet().iterator(); i.hasNext(); ) {
326             Entry e = (Entry)i.next();
327             excKeys.add(e.getKey());
328             excItems.add(e.getValue());
329         }
330
331         for (Iterator i = excepts.iterator(); i.hasNext(); ) {
332             Object JavaDoc o = i.next();
333             ThrowConstraint tc = null;
334             Type excType = null;
335             if (o instanceof ThrowConstraint) {
336                 tc = (ThrowConstraint)o;
337                 excType = tc.throwType();
338             }
339             else {
340                 excType = (Type)o;
341             }
342             List matchingExc = filterItemsExceptionSubclass(excItems, excKeys, excType);
343             if (!matchingExc.isEmpty()) {
344                 DataFlowItem df = (DataFlowItem)confluence(matchingExc, graph.exitNode(), graph);
345                 check(graph.exitNode(), df, false);
346
347                 if (ext != null && tc != null) {
348                     ext.checkHeldKeysThrowConstraint(tc, df.must_held, df.must_stored);
349                 }
350
351             }
352         }
353
354     }
355 }
356
Popular Tags