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 }