1 package kawa.lang; 2 import java.lang.reflect.Modifier ; 4 import java.util.Vector ; 5 import gnu.bytecode.*; 6 import gnu.mapping.*; 7 import gnu.lists.*; 8 import gnu.expr.Compilation; 9 10 public class Record 11 { 12 public String getTypeName() 13 { 14 return getClass().getName(); 15 } 16 17 public static boolean isRecord (Object obj) { return obj instanceof Record; } 18 19 public int hashCode() 20 { 21 java.lang.reflect.Field [] fields = getClass().getFields(); 22 int hash = 12345; 23 for (int i = 0; i < fields.length; i++) 24 { 25 java.lang.reflect.Field field = fields[i]; 26 Object value; 27 try 28 { 29 value = field.get(this); 30 } 31 catch (IllegalAccessException ex) 32 { 33 continue; 34 } 35 if (value != null) 36 hash ^= value.hashCode(); 37 } 38 return hash; 39 } 40 41 static java.lang.reflect.Field getField (Class clas, String fname) 42 throws NoSuchFieldException 43 { 44 ClassType ctype = (ClassType) Type.make(clas); 45 for (gnu.bytecode.Field fld = ctype.getFields(); 46 fld != null; fld = fld.getNext()) 47 { 48 if ((fld.getModifiers() & (Modifier.STATIC|Modifier.PUBLIC)) 49 != Modifier.PUBLIC) 50 continue; 51 if (! fld.getSourceName().equals(fname)) 52 continue; 53 return fld.getReflectField(); 54 } 55 throw new NoSuchFieldException (); 56 } 57 58 public Object get (String fname, Object defaultValue) 59 { 60 Class clas = getClass(); 61 try 62 { 63 return getField(clas, fname).get(this); 64 } 65 catch (NoSuchFieldException ex) 66 { 67 throw new GenericError("no such field "+fname+" in "+clas.getName()); 69 } 70 catch (IllegalAccessException ex) 71 { 72 throw new GenericError("illegal access for field "+fname); 73 } 74 } 75 76 public Object put (String fname, Object value) 77 { 78 return set1 (this, fname, value); 79 } 80 81 public static Object set1 (Object record, String fname, Object value) 82 { 83 Class clas = record.getClass(); 84 try 85 { 86 java.lang.reflect.Field fld = getField(clas, fname); 87 Object old = fld.get(record); 88 fld.set(record, value); 89 return old; 90 } 91 catch (NoSuchFieldException ex) 92 { 93 throw new GenericError("no such field "+fname+" in "+clas.getName()); 95 } 96 catch (IllegalAccessException ex) 97 { 98 throw new GenericError("illegal access for field "+fname); 99 } 100 } 101 102 public boolean equals (Object obj) 103 { 104 if (this == obj) 105 return true; 106 Class thisClass = getClass(); 107 if (obj == null || obj.getClass() != thisClass) 108 return false; 109 ClassType ctype = (ClassType) Type.make(thisClass); 110 for (gnu.bytecode.Field fld = ctype.getFields(); 111 fld != null; fld = fld.getNext()) 112 { 113 if ((fld.getModifiers() & (Modifier.STATIC|Modifier.PUBLIC)) 114 != Modifier.PUBLIC) 115 continue; 116 Object value1, value2; 117 try 118 { 119 java.lang.reflect.Field field = fld.getReflectField(); 120 value1 = field.get(this); 121 value2 = field.get(obj); 122 } 123 catch (Exception ex) 124 { 125 throw new WrappedException(ex); 126 } 127 if (! (value1.equals(value2))) 128 return false; 129 } 130 return true; 131 } 132 133 public String toString() 134 { 135 StringBuffer buf = new StringBuffer (200); 136 buf.append("#<"); 137 buf.append(getTypeName()); 138 ClassType ctype = (ClassType) Type.make(getClass()); 139 for (gnu.bytecode.Field fld = ctype.getFields(); 140 fld != null; fld = fld.getNext()) 141 { 142 if ((fld.getModifiers() & (Modifier.STATIC|Modifier.PUBLIC)) 143 != Modifier.PUBLIC) 144 continue; 145 Object value; 146 try 147 { 148 java.lang.reflect.Field field = fld.getReflectField(); 149 value = field.get(this); 150 } 151 catch (Exception ex) 152 { 153 value = "#<illegal-access>"; 154 } 155 buf.append(' '); 156 buf.append(fld.getSourceName()); 157 buf.append(": "); 158 buf.append(value); 159 } 160 buf.append(">"); 161 return buf.toString(); 162 } 163 164 public void print(java.io.PrintWriter ps) 165 { 166 ps.print(toString()); 167 } 168 169 public static ClassType makeRecordType (String name, LList fnames) 170 { 171 ClassType superClass = ClassType.make("kawa.lang.Record"); 172 String mangledName = Compilation.mangleNameIfNeeded(name); 173 ClassType clas = new ClassType(mangledName); 174 clas.setSuper(superClass); 175 clas.access_flags = Access.PUBLIC; 176 177 Method constructor = clas.addMethod ("<init>", Type.typeArray0, 179 Type.void_type, Access.PUBLIC); 180 Method superConstructor 181 = superClass.addMethod ("<init>", Type.typeArray0, 182 Type.void_type, Access.PUBLIC); 183 gnu.bytecode.CodeAttr code = constructor.startCode(); 184 code.emitPushThis(); 185 code.emitInvokeSpecial(superConstructor); 186 code.emitReturn(); 187 if (! name.equals(mangledName)) 188 { 189 Method meth = clas.addMethod ("getTypeName", Type.typeArray0, 190 Compilation.typeString, Access.PUBLIC); 191 code = meth.startCode(); 192 code.emitPushString(name); 193 code.emitReturn(); 194 } 195 196 gnu.bytecode.Field fld; 198 while (fnames != LList.Empty) 199 { 200 Pair pair = (Pair) fnames; 201 String fname = pair.car.toString(); 202 fld = clas.addField(Compilation.mangleNameIfNeeded(fname), 204 Type.pointer_type, Access.PUBLIC); 205 fld.setSourceName(fname.intern()); 206 fnames = (LList) pair.cdr; 207 } 208 214 215 byte[][] arrays = new byte[1][]; 216 String [] names = new String [1]; 217 names[0] = mangledName; 218 arrays[0] = clas.writeToArray(); 219 ArrayClassLoader loader = new ArrayClassLoader(names, arrays); 220 try 221 { 222 Class reflectClass = loader.loadClass (mangledName, true); 223 Type.registerTypeForClass(reflectClass, clas); 224 return clas; 225 } 226 catch (ClassNotFoundException ex) 227 { 228 throw new InternalError (ex.toString()); 229 } 230 } 231 232 public static LList typeFieldNames (Class clas) 233 { 234 LList list = LList.Empty; 235 257 ClassType ctype = (ClassType) Type.make(clas); 258 gnu.bytecode.Field field = ctype.getFields(); 259 Vector vec = new Vector (100); 260 for (; field != null; field = field.getNext()) 261 { 262 if ((field.getModifiers() & (Modifier.STATIC|Modifier.PUBLIC)) 263 == Modifier.PUBLIC) 264 vec.addElement(field.getSourceName()); 265 } 266 for (int i = vec.size(); --i >= 0; ) 267 { 268 list = new Pair(vec.elementAt(i), list); 269 } 270 return list; 271 } 272 273 public static LList typeFieldNames (ClassType ctype) 274 { 275 return typeFieldNames(ctype.getReflectClass()); 276 } 277 } 278 | Popular Tags |