📄 slotget.java
字号:
|| val1 instanceof FString || val1 instanceof Symbol) name = val1.toString(); } if (isStatic) { type = language.getTypeFor(arg0); int known = Invoke.checkKnownClass(type, comp); if (known < 0) return exp; if ("class".equals(name)) { if (known > 0) return QuoteExp.getInstance(type.getReflectClass()); Method method = Compilation.typeType.getDeclaredMethod("getReflectClass", 0); return new ApplyExp(method, new Expression[] { arg0 }); } if (type != null) { Expression[] nargs = new Expression[] { new QuoteExp(type), arg1 }; ApplyExp nexp = new ApplyExp(exp.getFunction(), nargs); nexp.setLine(exp); exp = nexp; } } else type = arg0.getType(); if (type instanceof ClassType && name != null) { ClassType ctype = (ClassType) type; ClassType caller = comp.curClass != null ? comp.curClass : comp.mainClass; Member part = lookupMember(ctype, name, caller); if (part instanceof gnu.bytecode.Field) { gnu.bytecode.Field field = (gnu.bytecode.Field) part; ctype = field.getDeclaringClass(); int modifiers = field.getModifiers(); boolean isStaticField = (modifiers & Access.STATIC) != 0; if (isStatic && ! isStaticField) return new ErrorExp("cannot access non-static field `" + name + "' using `" + getName() + '\'', comp); if (caller != null && ! caller.isAccessible(ctype, modifiers)) return new ErrorExp("field "+ctype.getName()+'.'+name +" is not accessible here", comp); } else if (part instanceof gnu.bytecode.Method) { gnu.bytecode.Method method = (gnu.bytecode.Method) part; ctype = method.getDeclaringClass(); int modifiers = method.getModifiers(); boolean isStaticMethod = method.getStaticFlag(); if (isStatic && ! isStaticMethod) return new ErrorExp("cannot call non-static getter method `" + name + "' using `" + getName() + '\'', comp); if (caller != null && ! caller.isAccessible(ctype, modifiers)) return new ErrorExp( "method "+method +" is not accessible here", comp); } if (part != null) { Expression[] nargs = new Expression[] { arg0, new QuoteExp(part) }; ApplyExp nexp = new ApplyExp(exp.getFunction(), nargs); nexp.setLine(exp); return nexp; } if (type != Type.pointer_type) comp.error('e', "no slot `"+name+"' in "+ctype.getName()); } if (name != null && ! (type instanceof ArrayType)) { String fname = gnu.expr.Compilation.mangleNameIfNeeded(name); // So we can quickly check for "class" or "length". // The name gets interned anyway when compiled. fname = fname.intern(); String getName = ClassExp.slotToMethodName("get", name); String isName = ClassExp.slotToMethodName("is", name); ApplyExp nexp = new ApplyExp(Invoke.invokeStatic, new Expression[] { QuoteExp.getInstance("gnu.kawa.reflect.SlotGet"), QuoteExp.getInstance("getSlotValue"), isStatic ? QuoteExp.trueExp : QuoteExp.falseExp, args[0], QuoteExp.getInstance(name), QuoteExp.getInstance(fname), QuoteExp.getInstance(getName), QuoteExp.getInstance(isName), QuoteExp.getInstance(language)}); nexp.setLine(exp); return ((InlineCalls) walker).walkApplyOnly(nexp); } return exp; } public void compile (ApplyExp exp, Compilation comp, Target target) { Expression[] args = exp.getArgs(); Expression arg0 = args[0]; Expression arg1 = args[1]; Language language = comp.getLanguage(); Type type = isStatic ? language.getTypeFor(arg0) : arg0.getType(); CodeAttr code = comp.getCode(); if (type instanceof ClassType && arg1 instanceof QuoteExp) { ClassType ctype = (ClassType) type; Object part = ((QuoteExp) arg1).getValue(); if (part instanceof gnu.bytecode.Field) { gnu.bytecode.Field field = (gnu.bytecode.Field) part; int modifiers = field.getModifiers(); boolean isStaticField = (modifiers & Access.STATIC) != 0; args[0].compile(comp, isStaticField ? Target.Ignore : Target.pushValue(ctype)); if (isStaticField) { boolean inlined = false; /* FIXME This isn't quite safe. We should only "inline" the value if the field whose initializer is a constant expression (JLS 2nd ed 15.28). We cannot determine this using reflection instead we have to parse the .class file. Type ftype = field.getType(); if ((modifiers & Access.FINAL) != 0 && ftype instanceof PrimType) { // We inline int final fields. // Other kinds of final fields are less obviously a win. char sig = ftype.getSignature().charAt(0); if (sig != 'F' && sig != 'D' && sig != 'J') { try { java.lang.reflect.Field rfield = field.getReflectField(); int val = rfield.getInt(null); code.emitPushInt(val); inlined = true; } catch (Exception ex) { } } } */ if (! inlined) code.emitGetStatic(field); } else code.emitGetField(field); Type ftype = field.getType(); Class fclass = ftype.getReflectClass(); if (fclass != null) ftype = language.getTypeFor(fclass); target.compileFromStack(comp, ftype); return; } if (part instanceof Method) { gnu.bytecode.Method method = (gnu.bytecode.Method) part; int modifiers = method.getModifiers(); boolean isStaticMethod = method.getStaticFlag(); args[0].compile(comp, isStaticMethod ? Target.Ignore : Target.pushValue(ctype)); if (isStaticMethod) code.emitInvokeStatic(method); else if (ctype.isInterface()) code.emitInvokeInterface(method); else code.emitInvokeVirtual(method); target.compileFromStack(comp, method.getReturnType()); return; } } String name = ClassMethods.checkName(arg1); if (type instanceof ArrayType && "length".equals(name) && ! isStatic) { args[0].compile(comp, Target.pushValue(type)); code.emitArrayLength(); target.compileFromStack(comp, LangPrimType.intType); // FIXME return; } ApplyExp.compile(exp, comp, target); } public Type getReturnType (Expression[] args) { int nargs = args.length; if (nargs == 2) { Expression arg0 = args[0]; Expression arg1 = args[1]; if (arg1 instanceof QuoteExp) { Object part = ((QuoteExp) arg1).getValue(); if (part instanceof gnu.bytecode.Field) return ((gnu.bytecode.Field) part).getType(); if (part instanceof gnu.bytecode.Method) return ((gnu.bytecode.Method) part).getReturnType(); if (! isStatic && arg0.getType() instanceof ArrayType && "length".equals(ClassMethods.checkName(arg1, true))) return gnu.kawa.lispexpr.LangPrimType.intType; // FIXME } } return Type.pointer_type; } public Procedure getSetter() { return setter == null ? super.getSetter() : setter; } /** * Convenience method to make an Expression that gets the value of a field. * @param value evaluates to object that has the named field * @param fieldName name of field in value * @return expression that get the name field from value */ public static ApplyExp makeGetField(Expression value, String fieldName) { Expression[] args = new Expression[2]; args[0] = value; args[1] = new QuoteExp(fieldName); return new ApplyExp(gnu.kawa.reflect.SlotGet.field, args); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -