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