123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- package kawa.lang;
- //import java.lang.reflect.Field; // Confuses Gcj. Should FIX gcj.
- import java.lang.reflect.Modifier;
- import java.util.Vector;
- import gnu.bytecode.*;
- import gnu.mapping.*;
- import gnu.lists.*;
- import gnu.expr.Compilation;
- import gnu.expr.Mangling;
- public class Record
- {
- public String getTypeName()
- {
- return getClass().getName();
- }
- public static boolean isRecord (Object obj) { return obj instanceof Record; }
- public int hashCode()
- {
- java.lang.reflect.Field[] fields = getClass().getFields();
- int hash = 12345;
- for (int i = 0; i < fields.length; i++)
- {
- java.lang.reflect.Field field = fields[i];
- Object value;
- try
- {
- value = field.get(this);
- }
- catch (IllegalAccessException ex)
- {
- continue;
- }
- if (value != null)
- hash ^= value.hashCode();
- }
- return hash;
- }
- static java.lang.reflect.Field getField (Class clas, String fname)
- throws NoSuchFieldException
- {
- ClassType ctype = (ClassType) Type.make(clas);
- for (gnu.bytecode.Field fld = ctype.getFields();
- fld != null; fld = fld.getNext())
- {
- if ((fld.getModifiers() & (Modifier.STATIC|Modifier.PUBLIC))
- != Modifier.PUBLIC)
- continue;
- if (! fld.getSourceName().equals(fname))
- continue;
- return fld.getReflectField();
- }
- throw new NoSuchFieldException();
- }
- public Object get (String fname, Object defaultValue)
- {
- Class clas = getClass();
- try
- {
- return getField(clas, fname).get(this);
- }
- catch (NoSuchFieldException ex)
- {
- //return defaultValue;
- throw new GenericError("no such field "+fname+" in "+clas.getName());
- }
- catch (IllegalAccessException ex)
- {
- throw new GenericError("illegal access for field "+fname);
- }
- }
- public Object put (String fname, Object value)
- {
- return set1 (this, fname, value);
- }
- public static Object set1 (Object record, String fname, Object value)
- {
- Class clas = record.getClass();
- try
- {
- java.lang.reflect.Field fld = getField(clas, fname);
- Object old = fld.get(record);
- fld.set(record, value);
- return old;
- }
- catch (NoSuchFieldException ex)
- {
- //throw new UnboundLocation(fname);
- throw new GenericError("no such field "+fname+" in "+clas.getName());
- }
- catch (IllegalAccessException ex)
- {
- throw new GenericError("illegal access for field "+fname);
- }
- }
- public boolean equals (Object obj)
- {
- if (this == obj)
- return true;
- Class thisClass = getClass();
- if (obj == null || obj.getClass() != thisClass)
- return false;
- ClassType ctype = (ClassType) Type.make(thisClass);
- for (gnu.bytecode.Field fld = ctype.getFields();
- fld != null; fld = fld.getNext())
- {
- if ((fld.getModifiers() & (Modifier.STATIC|Modifier.PUBLIC))
- != Modifier.PUBLIC)
- continue;
- Object value1, value2;
- try
- {
- java.lang.reflect.Field field = fld.getReflectField();
- value1 = field.get(this);
- value2 = field.get(obj);
- }
- catch (Exception ex)
- {
- throw new WrappedException(ex);
- }
- if (! (value1.equals(value2)))
- return false;
- }
- return true;
- }
- public String toString()
- {
- StringBuffer buf = new StringBuffer(200);
- buf.append("#<");
- buf.append(getTypeName());
- ClassType ctype = (ClassType) Type.make(getClass());
- for (gnu.bytecode.Field fld = ctype.getFields();
- fld != null; fld = fld.getNext())
- {
- if ((fld.getModifiers() & (Modifier.STATIC|Modifier.PUBLIC))
- != Modifier.PUBLIC)
- continue;
- Object value;
- try
- {
- java.lang.reflect.Field field = fld.getReflectField();
- value = field.get(this);
- }
- catch (Exception ex)
- {
- value = "#<illegal-access>";
- }
- buf.append(' ');
- buf.append(fld.getSourceName());
- buf.append(": ");
- buf.append(value);
- }
- buf.append(">");
- return buf.toString();
- }
- public void print(java.io.PrintWriter ps)
- {
- ps.print(toString());
- }
- public static ClassType makeRecordType (String name, LList fnames)
- {
- ClassType superClass = ClassType.make("kawa.lang.Record");
- String mangledName = Mangling.mangleClassName(name);
- ClassType clas = new ClassType(mangledName);
- clas.setClassfileVersion(Compilation.defaultClassFileVersion);
- clas.setSuper(superClass);
- clas.setModifiers(Access.PUBLIC|Access.SUPER);
- // Generate the (default) constructor.
- Method constructor = clas.addMethod ("<init>", Type.typeArray0,
- Type.voidType, Access.PUBLIC);
- Method superConstructor
- = superClass.addMethod ("<init>", Type.typeArray0,
- Type.voidType, Access.PUBLIC);
- gnu.bytecode.CodeAttr code = constructor.startCode();
- code.emitPushThis();
- code.emitInvokeSpecial(superConstructor);
- code.emitReturn();
- if (! name.equals(mangledName))
- {
- Method meth = clas.addMethod ("getTypeName", Type.typeArray0,
- Compilation.typeString, Access.PUBLIC);
- code = meth.startCode();
- code.emitPushString(name);
- code.emitReturn();
- }
- //StringBuffer fnamesBuf = new StringBuffer(100);
- gnu.bytecode.Field fld;
- while (fnames != LList.Empty)
- {
- Pair pair = (Pair) fnames;
- String fname = pair.getCar().toString();
- //fnamesBuf.append(fname); fnamesBuf.append('\n');
- fld = clas.addField(Mangling.mangleNameIfNeeded(fname),
- Type.pointer_type, Access.PUBLIC);
- fld.setSourceName(fname.intern());
- fnames = (LList) pair.getCdr();
- }
- /*
- fld = clas.addField("$FieldNames$", Compilation.typeString,
- Access.PUBLIC|Access.STATIC|Access.FINAL);
- ConstantValueAttr attr = new ConstantValueAttr(fnamesBuf.toString());
- attr.addToFrontOf(fld);
- */
- byte[][] arrays = new byte[1][];
- String[] names = new String[1];
- names[0] = mangledName;
- arrays[0] = clas.writeToArray();
- ArrayClassLoader loader = new ArrayClassLoader(names, arrays);
- try
- {
- Class reflectClass = loader.loadClass (mangledName);
- Type.registerTypeForClass(reflectClass, clas);
- return clas;
- }
- catch (ClassNotFoundException ex)
- {
- throw new InternalError (ex.toString());
- }
- }
- public static LList typeFieldNames (Class clas)
- {
- LList list = LList.Empty;
- /*
- try
- {
- Field fld = clas.getDeclaredField("$FieldNames$");
- String names = (String) fld.get(null);
- int nfields = 0;
- int limit = names.length() - 1;
-
- int ifield;
- while (limit > 0)
- {
- int start = names.lastIndexOf('\n', limit - 1);
- String fname = names.substring(start + 1, limit);
- list = new Pair(fname.intern(), list);
- limit = start;
- }
- return list;
- }
- catch (Exception ex)
- {
- }
- */
- ClassType ctype = (ClassType) Type.make(clas);
- gnu.bytecode.Field field = ctype.getFields();
- Vector vec = new Vector(100);
- for (; field != null; field = field.getNext())
- {
- if ((field.getModifiers() & (Modifier.STATIC|Modifier.PUBLIC))
- == Modifier.PUBLIC)
- vec.addElement(SimpleSymbol.valueOf(field.getSourceName()));
- }
- for (int i = vec.size(); --i >= 0; )
- {
- list = new Pair(vec.elementAt(i), list);
- }
- return list;
- }
- public static LList typeFieldNames (ClassType ctype)
- {
- return typeFieldNames(ctype.getReflectClass());
- }
- }
|