KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > visit > ContextVisitor


1 package polyglot.visit;
2
3 import polyglot.ast.*;
4 import polyglot.types.*;
5 import polyglot.util.*;
6 import polyglot.frontend.Job;
7 import polyglot.main.Report;
8 import java.util.*;
9
10 /**
11  * A visitor which maintains a context throughout the visitor's pass. This is
12  * the base class of the disambiguation and type checking visitors.
13  *
14  * TODO: update this documentation.
15  * For a node <code>n</code> methods are called in this order:
16  * <pre>
17  * v.enter(n)
18  * v.enterScope(n);
19  * c' = n.enterScope(c)
20  * v' = copy(v) with c' for c
21  * n' = n.visitChildren(v')
22  * v.leave(n, n', v')
23  * v.addDecls(n')
24  * n.addDecls(c)
25  * </pre>
26  */

27 public class ContextVisitor extends ErrorHandlingVisitor
28 {
29     protected ContextVisitor outer;
30
31     /** The current context of this visitor. */
32     protected Context context;
33
34     public ContextVisitor(Job job, TypeSystem ts, NodeFactory nf) {
35         super(job, ts, nf);
36         this.outer = null;
37         this.context = null;
38     }
39
40     public NodeVisitor begin() {
41         context = job.context();
42
43         if (context == null) {
44             context = ts.createContext();
45         }
46
47         outer = null;
48
49         return super.begin();
50     }
51
52     /** Returns the context for this visitor.
53      *
54      * @return Returns the context that is currently in use by this visitor.
55      * @see polyglot.types.Context
56      */

57     public Context context() {
58         return context;
59     }
60
61     /** Returns a new ContextVisitor that is a copy of the current visitor,
62      * except with an updated context.
63      *
64      * @param c The new context that is to be used.
65      * @return Returns a copy of this visitor with the new context
66      * <code>c</code>.
67      */

68     public ContextVisitor context(Context c) {
69         ContextVisitor v = (ContextVisitor) this.copy();
70         v.context = c;
71         return v;
72     }
73
74     /**
75      * Returns a new context based on the current context, the Node current
76      * being visited (<code>parent</code>), and the Node that is being
77      * entered (<code>n</code>). This new context is to be used
78      * for visiting <code>n</code>.
79      *
80      * @return The new context after entering Node <code>n</code>.
81      */

82     protected Context enterScope(Node parent, Node n) {
83         if (parent != null) {
84             return parent.del().enterScope(n, context);
85         }
86         // no parent node yet.
87
return n.del().enterScope(context);
88     }
89
90     /**
91      * Imperatively update the context with declarations to be added after
92      * visiting the node.
93      */

94     protected void addDecls(Node n) {
95         n.addDecls(context);
96     }
97
98     public NodeVisitor enter(Node parent, Node n) {
99         if (Report.should_report(Report.visit, 5))
100         Report.report(5, "enter(" + n + ")");
101
102         ContextVisitor v = this;
103
104         Context c = this.enterScope(parent, n);
105
106         if (c != this.context) {
107             v = (ContextVisitor) this.copy();
108             v.context = c;
109             v.outer = this;
110             v.error = false;
111         }
112
113         return v.superEnter(parent, n);
114     }
115
116     public NodeVisitor superEnter(Node parent, Node n) {
117         return super.enter(parent, n);
118     }
119
120     public Node leave(Node parent, Node old, Node n, NodeVisitor v) {
121         Node m = super.leave(parent, old, n, v);
122
123         this.addDecls(m);
124
125         return m;
126     }
127 }
128
Popular Tags