📄 slotget.java
字号:
package gnu.kawa.reflect;import gnu.mapping.*;import gnu.expr.*;import gnu.bytecode.*;import gnu.lists.FString;import gnu.kawa.lispexpr.LangPrimType;public class SlotGet extends Procedure2 implements HasSetter, CanInline, Inlineable{ static Class[] noClasses = { }; /** True if this is a "static-field" operation. */ boolean isStatic; Procedure setter; public static final SlotGet field = new SlotGet("field", false, SlotSet.set$Mnfield$Ex); public static final SlotGet slotRef = new SlotGet("slot-ref", false, SlotSet.set$Mnfield$Ex); public static final SlotGet staticField = new SlotGet("static-field", true, SlotSet.set$Mnstatic$Mnfield$Ex); public SlotGet(String name, boolean isStatic) { super(name); this.isStatic = isStatic; } public SlotGet(String name, boolean isStatic, Procedure setter) { super(name); this.isStatic = isStatic; this.setter = setter; } public static Object field(Object obj, String fname) { return field.apply2(obj, fname); } public static Object staticField(Object obj, String fname) { return staticField.apply2(obj, fname); } public Object apply2 (Object arg1, Object arg2) { String name, fname; String getName = null, isName = null; if (arg2 instanceof gnu.bytecode.Field) { fname = ((gnu.bytecode.Field) arg2).getName(); name = Compilation.demangleName(fname, true); } else if (arg2 instanceof gnu.bytecode.Method) { String mname = ((gnu.bytecode.Method) arg2).getName(); name = Compilation.demangleName(mname, false); if (mname.startsWith("get")) getName = mname; else if (mname.startsWith("is")) isName = mname; fname = null; } else if (! (arg2 instanceof String) && ! (arg2 instanceof FString)) throw new WrongType(this, 2, arg2, "string"); else { name = arg2.toString(); fname = gnu.expr.Compilation.mangleNameIfNeeded(name); } // "intern" fname if it is "class" or "length": if ("class".equals(fname)) fname = "class"; else if ("length".equals(fname)) fname = "length"; return getSlotValue(isStatic, arg1, name, fname, getName, isName, Language.getDefaultLanguage()); } /** The actual gets of finding the field value. * The compiler emits calls to this method if the field name is literals * but the actual field is not known at compile time. * This speeds lookup a bit. */ public static Object getSlotValue (boolean isStatic, Object obj, String name, String fname, String getName, String isName, Language language) { Class clas = isStatic ? coerceToClass(obj) : obj.getClass(); if (fname == "length" && clas.isArray()) { int length = java.lang.reflect.Array.getLength(obj); return language.coerceToObject(length); } if (fname == "class") return clas; boolean illegalAccess = false; if (fname != null) { java.lang.reflect.Field field; try { field = clas.getField(fname); } catch (Exception ex) { field = null; } if (field != null) { if (isStatic && (field.getModifiers() & java.lang.reflect.Modifier.STATIC) == 0) throw new RuntimeException("cannot access non-static field '" + fname + '\''); try { return language.coerceToObject(field.getType(), field.get(obj)); } catch (IllegalAccessException ex) { illegalAccess = true; } catch (Exception ex) { ex.printStackTrace(); // FIXME? } } } // Try looking for a method "getFname" or "isFname" instead: try { String mname = null; java.lang.reflect.Method getmethod = null; try { mname = getName != null ? getName : ClassExp.slotToMethodName("get", name); getmethod = clas.getMethod(mname, noClasses); } catch (Exception getEx) { mname = isName != null ? isName : ClassExp.slotToMethodName("is", name); getmethod = clas.getMethod(mname, noClasses); } if (isStatic && (getmethod.getModifiers() & java.lang.reflect.Modifier.STATIC) == 0) throw new RuntimeException("cannot call non-static getter method '" + mname + '\''); Object result = getmethod.invoke(obj, Values.noArgs); result = language.coerceToObject(getmethod.getReturnType(), result); return result; } catch (java.lang.reflect.InvocationTargetException ex) { throw WrappedException.wrapIfNeeded(ex.getTargetException()); } catch (IllegalAccessException ex) { illegalAccess = true; } catch (java.lang.NoSuchMethodException ex) { } if (illegalAccess) throw new RuntimeException("illegal access for field "+fname); else throw new RuntimeException ("no such field "+fname +" in "+clas.getName()); } static Class coerceToClass(Object obj) { if (obj instanceof Class) return (Class) obj; if (obj instanceof gnu.bytecode.Type) return ((gnu.bytecode.Type) obj).getReflectClass(); throw new RuntimeException("argument is neither Class nor Type"); } public void setN (Object[] args) { int nargs = args.length; if (nargs != 3) throw new WrongArguments(getSetter(), nargs); set2(args[0], args[1], args[2]); } public void set2 (Object obj, Object name, Object value) { SlotSet.apply(isStatic, obj, (String) name, value); } /** Get a named property - field or 'get' accessor method. * @param clas the class type declaring the property. * @param name the source (unmangled) name of the property. */ public static Member lookupMember (ClassType clas, String name, ClassType caller) { gnu.bytecode.Field field = clas.getField(Compilation.mangleNameIfNeeded(name), -1); if (field != null) { if (caller == null) caller = Type.pointer_type; if (caller.isAccessible(field.getDeclaringClass(), field.getModifiers())) return field; } // Try looking for a method "getFname" instead: String getname = ClassExp.slotToMethodName("get", name); gnu.bytecode.Method method = clas.getMethod(getname, Type.typeArray0); if (method == null) return field; else return method; } public Expression inline (ApplyExp exp, ExpWalker walker) { Compilation comp = walker.getCompilation(); Language language = comp.getLanguage(); Type type; Expression[] args = exp.getArgs(); Expression arg0 = args[0]; Expression arg1 = args[1]; String name = null; if (arg1 instanceof QuoteExp) { Object val1 = ((QuoteExp) arg1).getValue(); if (val1 instanceof String
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -