001 /* Copyright 2000, 2001, Compaq Computer Corporation */
002
003 package javafe.tc;
004
005 import javafe.ast.*;
006 import javafe.util.*;
007
008
009 /**
010 * EnvForLocals are used to extend an existing Env with one new local
011 * type binding.
012 */
013
014 public class EnvForEnclosedScope extends Env implements/*privately*/ Cloneable {
015
016 /***************************************************
017 * *
018 * Creation: *
019 * *
020 **************************************************/
021
022 /**
023 * Our parent environment
024 */
025 //@ invariant !(parent instanceof EnvForCU);
026 protected /*@ non_null @*/ Env parent;
027
028 /**
029 * Create a environment from an existing one by adding a new
030 * local type binding. <p>
031 *
032 * We report an error to ErrorSet if the new local type binding
033 * is a redefinition of a local type binding not hidden by a type
034 * member.<p>
035 */
036 //@ requires !(parent instanceof EnvForCU);
037 public EnvForEnclosedScope(/*@ non_null @*/ Env parent) {
038 this.parent = parent;
039 }
040
041
042
043 /***************************************************
044 * *
045 * Current/enclosing instances I: *
046 * *
047 **************************************************/
048
049 /**
050 * Is there a current instance in scope? <p>
051 *
052 * E.g., is "this" (or "<enclosing class>.this") legal here? <p>
053 *
054 * This is also refered to as "are we in a static context?". The
055 * legality of super also depends on this result. <p>
056 *
057 * The legality of C.this, C != <enclosing class> is different; see
058 * canAccessInstance(-).
059 */
060 public boolean isStaticContext() { return parent.isStaticContext(); }
061
062
063 /**
064 * Return the intermost class enclosing the code that is checked
065 * in this environment. <p>
066 *
067 * May return null if there is no enclosing class (aka, for
068 * environments for CompilationUnits). <p>
069 *
070 * If isStaticContext() returns true, then this is the type of "this".
071 */
072 public TypeSig getEnclosingClass() {
073 return parent.getEnclosingClass();
074 }
075
076
077 /**
078 * If there is an enclosing instance in scope, then return the
079 * (exact) type of the innermost such instance. <p>
080 *
081 * Note: this is considered a current instance, not an enclosing
082 * instance, even inside its methods.
083 */
084 public TypeSig getEnclosingInstance() {
085 return parent.getEnclosingInstance();
086 }
087
088
089 /**
090 * Returns a new Env that acts the same as us, except that its
091 * current instance (if any) is not accessible. <p>
092 *
093 * Note: this routine is somewhat inefficient and should be
094 * avoided unless an unknown environment needs to be coerced in
095 * this way. <p>
096 */
097 public Env asStaticContext() {
098 EnvForEnclosedScope n;
099 try {
100 n = (EnvForEnclosedScope)this.clone();
101 } catch (CloneNotSupportedException e) {
102 Assert.fail("clone did not obey its spec!");
103 return null; // keep compiler happy
104 }
105 n.parent = parent.asStaticContext();
106 return n;
107 }
108
109
110 /***************************************************
111 * *
112 * Simple names: *
113 * *
114 **************************************************/
115
116 /**
117 * Attempt to lookup a simple TypeName in this environment to get
118 * the TypeSig it denotes. Returns null if no such type
119 * exists.<p>
120 *
121 * This routine does not check that the resulting type (if any)
122 * is actually accessable. <p>
123 *
124 * If id is ambiguous, then if loc != Location.NULL then a fatal
125 * error is reported at that location via ErrorSet else one of
126 * its possible meanings is returned.<p>
127 */
128 public TypeSig lookupSimpleTypeName(TypeSig caller, /*@non_null*/Identifier id, int loc) {
129 return parent.lookupSimpleTypeName(caller, id, loc);
130 }
131
132
133 /**
134 * Locate the lexically innermost field or local variable
135 * declaration. <p>
136 *
137 * Let d be the lexically innermost field or local variable
138 * declaration (including formals) of id (if any such declaration
139 * exists). Then this routine returns: <p>
140 *
141 * d (a LocalVarDecl or FormalParaDecl) if d is a local
142 * variable declaration
143 *
144 * the class C that lexically encloses us and contains the
145 * (inherited) field d if d is a field declaration
146 *
147 * null if d does not exist
148 *
149 * Note: inherited fields are considered to lexically enclose the
150 * code of their subclasses. We give the class containing the
151 * field instead of the field itself to postpone dealing with
152 * multiple fields named id visible in the same class.<p>
153 *
154 * In the field case, id disambiguates to C[.this].id.<p>
155 */
156 public ASTNode locateFieldOrLocal(/*@non_null*/Identifier id) {
157 // we bind no fields or local variables/formals ourselves:
158 return parent.locateFieldOrLocal(id);
159 }
160
161 public boolean isDuplicate(/*@non_null*/Identifier id) {
162 return false;
163 }
164
165 /**
166 * Locate the lexically innermost method named id. <p>
167 *
168 * Returns the TypeSig for the innermost lexically enclosing type
169 * that has a method named id or null if no such type exists.<p>
170 *
171 * Note: inherited methods are considered to lexically enclose
172 * the code of their subclasses.<p>
173 *
174 * id disambiguates to C[.this].id.<p>
175 */
176 public TypeSig locateMethod(/*@non_null*/Identifier id) {
177 // we bind no methods ourselves:
178 return parent.locateMethod(id);
179 }
180
181
182 /***************************************************
183 * *
184 * Debugging functions: *
185 * *
186 **************************************************/
187
188 /**
189 * Display information about us to System.out. This function is
190 * intended only for debugging use.
191 */
192 public void display() {
193 parent.display();
194 System.out.println("[[ extended with enclosed scope marker ]] ");
195 }
196 }