1 package gnu.kawa.reflect; 2 import gnu.bytecode.*; 3 import gnu.mapping.*; 4 import gnu.mapping.Location; import gnu.expr.*; 6 7 public class FieldLocation extends ClassMemberLocation 8 { 9 Declaration decl; 10 13 Object value; 14 static final int SETUP_DONE = 1; 16 18 static final int INDIRECT_LOCATION = 2; 19 22 static final int CONSTANT = 4; 23 28 static final int VALUE_SET = 8; 29 public static final int PROCEDURE = 16; 32 public static final int SYNTAX = 32; 33 35 public static final int KIND_FLAGS_SET = 64; 36 private int flags; 37 38 public boolean isIndirectLocation () 39 { return (flags & INDIRECT_LOCATION) != 0; } 40 41 public void setProcedure () 42 { 43 flags |= PROCEDURE|CONSTANT|KIND_FLAGS_SET; 44 } 45 46 public void setSyntax () 47 { 48 flags |= SYNTAX|CONSTANT|KIND_FLAGS_SET; 49 } 50 51 void setKindFlags () 52 { 53 String fname = getMemberName(); 54 gnu.bytecode.Field fld = getDeclaringClass().getDeclaredField(fname); 55 int fflags = fld.getModifiers(); 56 Type ftype = fld.getType(); 57 if (ftype.isSubtype(Compilation.typeLocation)) 58 flags |= INDIRECT_LOCATION; 59 if ((fflags & Access.FINAL) != 0) 60 { 61 if ((flags & INDIRECT_LOCATION) == 0) 62 { 63 flags |= CONSTANT; 64 if (ftype.isSubtype(Compilation.typeProcedure)) 65 flags |= PROCEDURE; 66 if (ftype.isSubtype(ClassType.make("kawa.lang.Syntax"))) 67 flags |= SYNTAX; 68 } 69 else 70 { 71 Location loc = (Location) getFieldValue(); 72 if (loc instanceof FieldLocation) 73 { 74 FieldLocation floc = (FieldLocation) loc; 75 if ((floc.flags & KIND_FLAGS_SET) == 0) 76 floc.setKindFlags(); 77 flags |= (floc.flags & (SYNTAX|PROCEDURE|CONSTANT)); 78 if ((floc.flags & CONSTANT) != 0) 79 { 80 if ((floc.flags & VALUE_SET) != 0) 81 { 82 value = floc.value; 83 flags |= VALUE_SET; 84 } 85 } 86 else 87 { 88 value = floc; 89 flags |= VALUE_SET; 90 } 91 } 92 else if (loc.isConstant()) 93 { 94 Object val = loc.get(null); 95 if (val instanceof Procedure) 97 flags |= PROCEDURE; 98 if (val instanceof kawa.lang.Syntax) flags |= SYNTAX; 100 flags |= CONSTANT|VALUE_SET; 101 value = val; 102 } 103 } 104 } 105 flags |= KIND_FLAGS_SET; 106 } 107 108 public boolean isProcedureOrSyntax () 109 { 110 if ((flags & KIND_FLAGS_SET) == 0) 111 setKindFlags(); 112 return (flags & (PROCEDURE+SYNTAX)) != 0; 113 } 114 115 public FieldLocation(Object instance, String cname, String fname) 116 { 117 super(instance, ClassType.make(cname), fname); 118 } 119 120 public FieldLocation(Object instance, ClassType type, String mname) 121 { 122 super(instance, type, mname); 123 } 124 125 126 public void setDeclaration (Declaration decl) 127 { 128 this.decl = decl; 129 } 130 131 public Field getField () 132 { 133 return type.getDeclaredField(mname); 134 } 135 136 137 public Type getFType () 138 { 139 return type.getDeclaredField(mname).getType(); 140 } 141 142 public synchronized Declaration getDeclaration () 143 { 144 if ((flags & KIND_FLAGS_SET) == 0) 145 setKindFlags(); 146 Declaration d = decl; 147 if (d == null) 148 { 149 String fname = getMemberName(); 150 ClassType t = getDeclaringClass(); 151 gnu.bytecode.Field procField = t.getDeclaredField(fname); 152 if (procField == null) 153 return null; 154 ModuleInfo info = ModuleInfo.find(t.getName()); 155 ModuleExp mexp = info.getModuleExp(); 156 for (d = mexp.firstDecl(); d != null; d = d.nextDecl()) 157 { 158 if (d.field != null && d.field.getName().equals(fname)) 159 break; 160 } 161 if (d == null) 162 throw new RuntimeException ("no field found for "+this); 163 decl = d; 164 } 165 return d; 166 } 167 168 void setup () 169 { 170 synchronized (this) 171 { 172 if ((flags & SETUP_DONE) != 0) 173 return; 174 super.setup(); 175 if ((flags & KIND_FLAGS_SET) == 0) 176 setKindFlags(); 177 flags |= SETUP_DONE; 178 } 179 } 180 181 public Object get (Object defaultValue) 182 { 183 try 184 { 185 setup(); 186 } 187 catch (Throwable ex) 188 { 189 return defaultValue; 190 } 191 Object v; 192 if ((flags & VALUE_SET) != 0) 193 { 194 v = value; 195 if ((flags & CONSTANT) != 0) 196 return v; 197 } 198 else 199 { 200 v = getFieldValue(); 201 if ((type.getDeclaredField(mname).getModifiers() & Access.FINAL) != 0) 202 { 203 flags |= VALUE_SET; 204 if ((flags & INDIRECT_LOCATION) == 0) 205 flags |= CONSTANT; 206 value = v; 207 } 208 } 209 if ((flags & INDIRECT_LOCATION) != 0) 210 { 211 Object unb = Location.UNBOUND; 212 Location loc = (Location) v; 213 v = loc.get(unb); 214 if (v == unb) 215 return defaultValue; 216 if (loc.isConstant()) 217 { 218 flags |= CONSTANT; 219 value = v; 220 } 221 } 222 return v; 223 } 224 225 private Object getFieldValue () 226 { 227 super.setup(); try 229 { 230 return rfield.get(instance); 231 } 232 catch (Throwable ex) 233 { 234 throw WrappedException.wrapIfNeeded(ex); 235 } 236 } 237 238 public void set (Object newValue) 239 { 240 setup(); 241 if ((flags & INDIRECT_LOCATION) == 0) 242 { 243 try 244 { 245 rfield.set(instance, newValue); 246 } 247 catch (Throwable ex) 248 { 249 throw WrappedException.wrapIfNeeded(ex); 250 } 251 } 252 else 253 { 254 Object v; 255 if ((flags & VALUE_SET) != 0) 256 v = value; 257 else 258 { 259 flags |= VALUE_SET; 260 v = getFieldValue(); 261 value = v; 262 } 263 ((Location) v).set(newValue); 264 } 265 } 266 267 public boolean isConstant () 268 { 269 if ((flags & KIND_FLAGS_SET) == 0) 270 setKindFlags(); 271 if ((flags & CONSTANT) != 0) 272 return true; 273 if (isIndirectLocation()) 274 { 275 Object v; 276 if ((flags & VALUE_SET) != 0) 277 v = value; 278 else 279 { 280 try 281 { 282 setup(); 283 } 284 catch (Throwable ex) 285 { 286 return false; 287 } 288 v = getFieldValue(); 289 flags |= VALUE_SET; 290 value = v; 291 } 292 return ((Location) v).isConstant(); 293 } 294 return false; 295 } 296 297 public boolean isBound () 298 { 299 if ((flags & KIND_FLAGS_SET) == 0) 300 setKindFlags(); 301 if ((flags & CONSTANT) != 0 || (flags & INDIRECT_LOCATION) == 0) 302 return true; 303 Object v; 304 if ((flags & VALUE_SET) != 0) 305 v = value; 306 else 307 { 308 try 309 { 310 setup(); 311 } 312 catch (Throwable ex) 313 { 314 return false; 315 } 316 v = getFieldValue(); 317 flags |= VALUE_SET; 318 value = v; 319 } 320 return ((Location) v).isBound(); 321 } 322 323 public static FieldLocation make (Object instance, Declaration decl) 324 { 325 gnu.bytecode.Field fld = decl.field; 326 ClassType ctype = fld.getDeclaringClass(); 327 FieldLocation loc = new FieldLocation(instance, ctype, fld.getName()); 328 loc.setDeclaration(decl); 329 return loc; 331 } 332 333 public static FieldLocation make ( Object instance, String cname, String fldName) 334 { 335 return new FieldLocation( instance, ClassType.make(cname), fldName); 336 } 337 338 public String toString() 339 { 340 StringBuffer sbuf = new StringBuffer (); 341 sbuf.append("FieldLocation["); 342 if (instance != null) 343 { 344 sbuf.append(instance); 345 sbuf.append(' '); 346 } 347 sbuf.append(type.getName()); 348 sbuf.append('.'); 349 sbuf.append(mname); 350 354 sbuf.append(']'); 355 return sbuf.toString(); 356 } 357 } 358 | Popular Tags |