KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > visit > ExitChecker


1 package polyglot.visit;
2
3 import java.util.*;
4
5 import polyglot.ast.*;
6 import polyglot.frontend.Job;
7 import polyglot.types.SemanticException;
8 import polyglot.types.TypeSystem;
9
10 /**
11  * Visitor which checks that all (terminating) paths through a
12  * method must return.
13  */

14 public class ExitChecker extends DataFlow
15 {
16     protected CodeDecl code;
17
18     public ExitChecker(Job job, TypeSystem ts, NodeFactory nf) {
19     super(job, ts, nf, false /* backward analysis */);
20     }
21
22     protected FlowGraph initGraph(CodeDecl code, Term root) {
23         boolean returnsValue;
24
25         this.code = code;
26
27         if (code instanceof MethodDecl) {
28             MethodDecl d = (MethodDecl) code;
29             if (! d.methodInstance().returnType().isVoid()) {
30                 return super.initGraph(code, root);
31             }
32         }
33
34         return null;
35     }
36
37     public Item createInitialItem(FlowGraph graph, Term node) {
38         return DataFlowItem.EXITS;
39     }
40
41     protected static class DataFlowItem extends Item {
42         final boolean exits; // whether all paths leaving this node lead to an exit
43

44         protected DataFlowItem(boolean exits) {
45             this.exits = exits;
46         }
47         
48         public static final DataFlowItem EXITS = new DataFlowItem(true);
49         public static final DataFlowItem DOES_NOT_EXIT = new DataFlowItem(false);
50
51         public String JavaDoc toString() {
52             return "exits=" + exits;
53         }
54         public boolean equals(Object JavaDoc o) {
55             if (o instanceof DataFlowItem) {
56                 return this.exits == ((DataFlowItem)o).exits;
57             }
58             return false;
59         }
60         public int hashCode() {
61             return (exits ? 5235 : 8673);
62         }
63         
64     }
65     
66     public Map flow(Item in, FlowGraph graph, Term n, Set succEdgeKeys) {
67         // If every path from the exit node to the entry goes through a return,
68
// we're okay. So make the exit bit false at exit and true at every return;
69
// the confluence operation is &&.
70
// We deal with exceptions specially, and assume that any exception
71
// edge to the exit node is OK.
72
if (n instanceof Return) {
73             return itemToMap(DataFlowItem.EXITS, succEdgeKeys);
74         }
75
76         if (n == graph.exitNode()) {
77             // all exception edges to the exit node are regarded as exiting
78
// correctly. Make sure non-exception edges have the
79
// exit bit false.
80
Map m = itemToMap(DataFlowItem.EXITS, succEdgeKeys);
81             if (succEdgeKeys.contains(FlowGraph.EDGE_KEY_OTHER)) {
82                 m.put(FlowGraph.EDGE_KEY_OTHER, DataFlowItem.DOES_NOT_EXIT);
83             }
84             if (succEdgeKeys.contains(FlowGraph.EDGE_KEY_TRUE)) {
85                 m.put(FlowGraph.EDGE_KEY_TRUE, DataFlowItem.DOES_NOT_EXIT);
86             }
87             if (succEdgeKeys.contains(FlowGraph.EDGE_KEY_FALSE)) {
88                 m.put(FlowGraph.EDGE_KEY_FALSE, DataFlowItem.DOES_NOT_EXIT);
89             }
90             
91             return m;
92         }
93
94         return itemToMap(in, succEdgeKeys);
95     }
96
97
98     public Item confluence(List inItems, Term node, FlowGraph graph) {
99         // all paths must have an exit
100
for (Iterator i = inItems.iterator(); i.hasNext(); ) {
101             if (!((DataFlowItem)i.next()).exits) {
102                 return DataFlowItem.DOES_NOT_EXIT;
103             }
104         }
105         return DataFlowItem.EXITS;
106     }
107
108     public void check(FlowGraph graph, Term n, Item inItem, Map outItems) throws SemanticException {
109         // Check for statements not on the path to exit; compound
110
// statements are allowed to be off the path. (e.g., "{ return; }"
111
// or "while (true) S"). If a compound statement is truly
112
// unreachable, one of its sub-statements will be also and we will
113
// report an error there.
114
if (n == graph.entryNode()) {
115             if (outItems != null && !outItems.isEmpty()) {
116                 // due to the flow equations, all DataFlowItems in the outItems map
117
// are the same, so just take the first one.
118
DataFlowItem outItem = (DataFlowItem)outItems.values().iterator().next();
119                 if (outItem != null && !outItem.exits) {
120                     throw new SemanticException("Missing return statement.",
121                             code.position());
122                 }
123             }
124         }
125     }
126 }
127
Popular Tags