1 package gnu.kawa.reflect; 2 import gnu.mapping.*; 3 import gnu.bytecode.*; 4 import gnu.lists.FString; 5 import gnu.expr.*; 6 7 public class SlotSet extends Procedure3 implements CanInline, Inlineable 8 { 9 10 boolean isStatic; 11 12 14 boolean returnSelf; 15 16 public static final SlotSet set$Mnfield$Ex = new SlotSet("set-field!", false); 17 public static final SlotSet set$Mnstatic$Mnfield$Ex 18 = new SlotSet("set-static-field!", true); 19 public static final SlotSet setFieldReturnObject 20 = new SlotSet("set-field-return-object!", false); 21 static { setFieldReturnObject.returnSelf = true; } 22 23 public SlotSet(String name, boolean isStatic) 24 { 25 super(name); 26 this.isStatic = isStatic; 27 } 28 29 public static void setField (Object obj, String name, Object value) 30 { 31 apply(false, obj, name, value); 32 } 33 34 public static void setStaticField (Object obj, String name, Object value) 35 { 36 apply(true, obj, name, value); 37 } 38 39 public static void apply (boolean isStatic, Object obj, String name, Object value) 40 { 41 Language language = Language.getDefaultLanguage(); 42 boolean illegalAccess = false; 43 String fname = gnu.expr.Compilation.mangleNameIfNeeded(name); 44 Class clas = isStatic ? SlotGet.coerceToClass(obj) : obj.getClass(); 45 try 46 { 47 java.lang.reflect.Field field = clas.getField(fname); 48 Class ftype = field.getType(); 49 field.set(obj, language.coerceFromObject(ftype, value)); 50 return; 51 } 52 catch (java.lang.NoSuchFieldException ex) 53 { 54 } 55 catch (IllegalAccessException ex) 56 { 57 illegalAccess = true; 58 } 59 60 try 63 { 64 java.lang.reflect.Method getmethod = null; 65 66 try { 67 String getName = ClassExp.slotToMethodName("get", name); 68 getmethod = clas.getMethod(getName, SlotGet.noClasses); 69 } catch (Exception getEx) { 70 String getName = ClassExp.slotToMethodName("is", name); 71 getmethod = clas.getMethod(getName, SlotGet.noClasses); 72 } 73 74 String setName = ClassExp.slotToMethodName("set", name); 75 Class [] setArgTypes = new Class [1]; 76 setArgTypes[0] = getmethod.getReturnType(); 77 java.lang.reflect.Method setmethod 78 = clas.getMethod(setName, setArgTypes); 79 Object [] args = new Object [1]; 80 args[0] = language.coerceFromObject(setArgTypes[0], value); 81 setmethod.invoke(obj, args); 82 return; 83 } 84 catch (java.lang.reflect.InvocationTargetException ex) 85 { 86 throw WrappedException.wrapIfNeeded(ex.getTargetException()); 87 } 88 catch (IllegalAccessException ex) 89 { 90 illegalAccess = true; 91 } 92 catch (java.lang.NoSuchMethodException ex) 93 { 94 } 95 96 if (illegalAccess) 97 throw new RuntimeException ("illegal access for field "+name); 98 else 99 throw new RuntimeException ("no such field "+name 100 +" in "+clas.getName()); 101 } 102 103 public Object apply3 (Object obj, Object fname, Object value) 104 { 105 apply(isStatic, obj, (String ) fname, value); 106 return returnSelf ? obj : Values.empty; 107 } 108 109 public static Member 110 lookupMember (ClassType clas, String name, ClassType caller) 111 { 112 gnu.bytecode.Field field 113 = clas.getField(Compilation.mangleNameIfNeeded(name), -1); 114 if (field != null) 115 { 116 if (caller == null) 117 caller = Type.pointer_type; 118 if (caller.isAccessible(field.getDeclaringClass(), 119 field.getModifiers())) 120 return field; 121 } 122 123 String setName = ClassExp.slotToMethodName("set", name); 124 gnu.bytecode.Method method = clas.getMethod(setName, new Type[1]); 125 if (method == null) 126 return field; 127 else 128 return method; 129 } 130 131 static void compileSet(Procedure thisProc, ClassType ctype, 132 Expression valArg, Object part, Compilation comp) 133 { 134 CodeAttr code = comp.getCode(); 135 Language language = comp.getLanguage(); 136 boolean isStatic 137 = thisProc instanceof SlotSet && ((SlotSet) thisProc).isStatic; 138 if (part instanceof gnu.bytecode.Field) 139 { 140 gnu.bytecode.Field field = (gnu.bytecode.Field) part; 141 boolean isStaticField = field.getStaticFlag(); 142 Type ftype = language.getLangTypeFor(field.getType()); 143 if (isStatic && ! isStaticField) 144 comp.error('e', ("cannot access non-static field `" + field.getName() 145 + "' using `" + thisProc.getName() + '\'')); 146 valArg.compile(comp, CheckedTarget.getInstance(ftype)); 147 if (isStaticField) 148 code.emitPutStatic(field); 149 else 150 code.emitPutField(field); 151 return; 152 } 153 if (part instanceof gnu.bytecode.Method) 154 { 155 gnu.bytecode.Method method = (gnu.bytecode.Method) part; 156 boolean isStaticMethod = method.getStaticFlag(); 157 if (isStatic && ! isStaticMethod) 158 comp.error('e', "cannot call non-static getter method `" 159 + method.getName() + "' using `" 160 + thisProc.getName() + '\''); 161 Type[] setArgTypes = method.getParameterTypes(); 162 valArg.compile(comp, CheckedTarget.getInstance(language.getLangTypeFor(setArgTypes[0]))); 163 if (isStaticMethod) 164 code.emitInvokeStatic(method); 165 else if (ctype.isInterface()) 166 code.emitInvokeInterface(method); 167 else 168 code.emitInvokeVirtual(method); 169 return; 170 } 171 } 172 173 public Expression inline (ApplyExp exp, ExpWalker walker) 174 { 175 if (isStatic && walker.getCompilation().mustCompile) 180 return Invoke.inlineClassName (exp, 0, (InlineCalls) walker); 181 else 182 return exp; 183 } 184 185 public void compile (ApplyExp exp, Compilation comp, Target target) 186 { 187 Expression[] args = exp.getArgs(); 188 int nargs = args.length; 189 if (nargs != 3) 190 { 191 String msg = nargs < 3 ? "too few" : "too many"; 192 comp.error('e', msg + " arguments to `"+getName()+'\''); 193 comp.compileConstant(null, target); 194 return; 195 } 196 Expression arg0 = args[0]; 197 Expression arg1 = args[1]; 198 Expression value = args[2]; 199 Type type = isStatic ? kawa.standard.Scheme.exp2Type(arg0) 200 : arg0.getType(); 201 Member part = null; 202 if (type instanceof ClassType && arg1 instanceof QuoteExp) 203 { 204 Object val1 = ((QuoteExp) arg1).getValue(); 205 ClassType ctype = (ClassType) type; 206 String name; 207 ClassType caller = comp.curClass != null ? comp.curClass 208 : comp.mainClass; 209 if (val1 instanceof String 210 || val1 instanceof FString 211 || val1 instanceof Symbol) 212 { 213 name = val1.toString(); 214 part = lookupMember(ctype, name, caller); 215 if (part == null && type != Type.pointer_type) 216 comp.error('e', "no slot `"+name+"' in "+ctype.getName()); 217 } 218 else if (val1 instanceof Member) 219 { 220 part = (Member) val1; 223 name = part.getName(); 224 } 225 else 226 name = null; 227 228 if (part != null) 229 { 230 int modifiers = part.getModifiers(); 231 ClassType ptype = part.getDeclaringClass(); 232 boolean isStaticField = (modifiers & Access.STATIC) != 0; 233 if (caller != null && ! caller.isAccessible(ptype, modifiers)) 234 comp.error('e', "slot '"+name +"' in "+ptype.getName() 235 +" not accessible here"); 236 args[0].compile(comp, 237 isStaticField ? Target.Ignore 238 : Target.pushValue(ctype)); 239 if (returnSelf) 240 comp.getCode().emitDup(ctype); 241 compileSet(this, ctype, args[2], part, comp); 242 if (returnSelf) 243 target.compileFromStack(comp, ctype); 244 else 245 comp.compileConstant(Values.empty, target); 246 return; 247 } 248 } 249 ApplyExp.compile(exp, comp, target); 250 } 251 252 public Type getReturnType (Expression[] args) 253 { 254 if (returnSelf && args.length == 3) 255 return args[0].getType(); 256 return Type.void_type; 257 } 258 } 259 | Popular Tags |