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, 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(Identifier id) {
157            // we bind no fields or local variables/formals ourselves:
158            return parent.locateFieldOrLocal(id);
159        }
160    
161        public boolean isDuplicate(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(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    }