From: <as...@ma...> - 2003-10-25 21:31:50
|
> Since there seems to be interest in this area, I should mention that > ABL's implementation in this area is trying to be more or less like > Allegro's: > > http://www.franz.com/support/documentation/6.2/doc/jlinker.htm > > Or more specifically in the current case: > > http://www.franz.com/support/documentation/6.2/doc/pages/operators/ja= > vatools.jlinker/jfield.htm > I agree, following ACL is a good thing. Although in this particular case, I have some reservations about it, because jfield's argument conventions look rather baroque to me. I'd gladly give up ACL's (jfield class-name field-name nil value) for (setf (jfield class-name field-name) value). Nevertheless, here's a first attempt to emulate ACL's jfield as it stands. Besides jfield, I also extended makeLispObject (and I'm not sure I got it right) just so that even when jfield is used to set a field, the return value is close to what ACL produces. The comments '//case n', where n is between 1 and 7, refer to the corresponding argument list. They sure look ugly, but make this spaghetti easier to follow, at least for me. Andras --- Java.java.orig Sat Oct 25 13:58:00 2003 +++ Java.java Sat Oct 25 21:27:46 2003 @@ -46,27 +46,82 @@ } }; - // ### jfield - // jfield class-name field-name &optional instance - private static final Primitive JFIELD = new Primitive("jfield", PACKAGE_JAVA) - { + // ### jfield + /* + + * class-name field-name: to retrieve the value of a static field. + * class-name field-name instance-ref: to retrieve the value of a class field of the instance. + * class-name field-name primitive-value: to store primitive-value in a static field. + * class-name field-name instance-ref value: to store value in a class field of the instance. + * class-name field-name nil value: to store value in a static field (when value may be confused with an instance-ref). + * field-name instance: to retrieve the value of a field of the instance. The class is derived from the instance. + * field-name instance value: to store value in a field of the instance. The class is derived from the instance. + + */ + private static final Primitive JFIELD = new Primitive("jfield", PACKAGE_JAVA) + { public LispObject execute(LispObject[] args) throws ConditionThrowable { - if (args.length < 2 || args.length > 3) + if (args.length < 2 || args.length > 4) throw new ConditionThrowable(new WrongNumberOfArgumentsException(this)); - String className = LispString.getValue(args[0]); - String fieldName = LispString.getValue(args[1]); + String fieldName, className = null; + Class c; + Field f; Object instance = null; + try { - final Class c = Class.forName(className); - final Field f = c.getField(fieldName); - if (args.length == 3) { - if (args[2] instanceof LispString) - instance = LispString.getValue(args[2]); - else - instance = JavaObject.getObject(args[2]); - } - return makeLispObject(f.get(instance)); + if (args[1] instanceof LispString) { //case 1-5 + fieldName = LispString.getValue(args[1]); + className = LispString.getValue(args[0]); + c = Class.forName(className); + } + else { //case 6-7 + fieldName = LispString.getValue(args[0]); + instance = JavaObject.getObject(args[1]); + c = instance.getClass(); + className = c.getName(); //needed only for the error message + } + + f = c.getField(fieldName); + Class requiredType = f.getType(); + + switch (args.length) { + case 2 : //case 1,6 + break; // this is here only so I can hang the comment above somewhere :-) + case 3 : //case 2,3,7 + if (instance == null) { //case 2,3 + if (args[2] instanceof JavaObject) { //case 2 + instance = JavaObject.getObject(args[2]); + break; + } + else { //case 3 + if (args[2] instanceof Fixnum) { + f.set(instance,new Integer (((Fixnum)args[2]).getValue())); + } + else + if (args[2] instanceof LispFloat) + f.set(instance,new Double (((LispFloat)args[2]).getValue())); + else + if (args[2] instanceof LispCharacter) + f.set(instance,new Character (((LispCharacter)args[2]).getValue())); + else + throw new ConditionThrowable(new TypeError( + "unsupported type in jfield")); + // not sure about this ^ + return args[2]; + } + } + else { // case 7 + f.set(instance,JavaObject.getObject(args[2])); + return args[2]; + } + case 4 : //case 4,5 + if (args[2] != NIL) //case 4 + instance = JavaObject.getObject(args[2]); + f.set(instance,JavaObject.getObject(args[3])); + return args[3]; + } + return makeLispObject(f.get(instance)); } catch (ClassNotFoundException e) { throw new ConditionThrowable(new LispError("class not found: " + className)); @@ -334,6 +389,8 @@ return new LispFloat(((Number)obj).doubleValue()); if (obj instanceof String) return new LispString((String)obj); + if (obj instanceof Character) + return LispCharacter.getInstance(((Character)obj).charValue()); if (obj instanceof Object[]) { Object[] array = (Object[]) obj; Vector v = new Vector(array.length); |