📄 getnamedpart.java
字号:
Environment env = ctx.getEnvironment(); Symbol sym = env.getSymbol(combinedName); Object unb = gnu.mapping.Location.UNBOUND; Object property = null; // FIXME? Object value = env.get(sym, property, unb); if (value != unb) { ctx.writeValue(value); return; } } super.apply(ctx); } public GetNamedExp(Expression[] args) { super(GetNamedPart.getNamedPart, args); } protected GetNamedExp setProcedureKind (char kind) { // Called from GetNamedPart.inline when the expression evaluates to a // procedure that takes (at least) a 'this' parameter. If the // expression is in turn used in function call position it is normally // the first argment to ApplyToArgs, so setting the type to typeProcedure // allows ApplyToArgs.inline to be optimized away, and then later // the inline method in the GetNamedExp class can get called. this.type = Compilation.typeProcedure; this.kind = kind; return this; } public Expression inline (ApplyExp exp, InlineCalls walker, Declaration decl) { Expression[] pargs = getArgs(); Expression context = pargs[0]; Expression[] args = exp.getArgs(); Expression[] xargs; switch (kind) { case 'M': decl = invokeDecl; xargs = new Expression[args.length+2]; xargs[0] = pargs[0]; xargs[1] = pargs[1]; System.arraycopy(args, 0, xargs, 2, args.length); break; case 'N': // new decl = makeDecl; xargs = new Expression[args.length+1]; System.arraycopy(args, 0, xargs, 1, args.length); xargs[0] = context; break; case 'I': // instance-of decl = instanceOfDecl; xargs = new Expression[args.length+1]; System.arraycopy(args, 1, xargs, 2, args.length-1); xargs[0] = args[0]; xargs[1] = context; break; case 'C': // cast decl = castDecl; xargs = new Expression[args.length+1]; System.arraycopy(args, 1, xargs, 2, args.length-1); xargs[0] = context; xargs[1] = args[0]; break; case 'S': // invoke-static decl = invokeStaticDecl; xargs = new Expression[args.length+2]; xargs[0] = context; xargs[1] = pargs[1]; System.arraycopy(args, 0, xargs, 2, args.length); break; default: return exp; } ApplyExp result = new ApplyExp(new ReferenceExp(decl), xargs); result.setLine(exp); return walker.walkApplyOnly(result); } public boolean side_effects () { // The actual GetNamedExp that returns a method reference doesn't // have side-effects - though applying tha result does. if (kind == 'S' || kind == 'N' || kind == 'C' || kind == 'I') return false; if (kind == 'M') return getArgs()[0].side_effects(); return true; } static final Declaration fieldDecl = Declaration.getDeclarationFromStatic("gnu.kawa.reflect.SlotGet", "field"); static final Declaration staticFieldDecl = Declaration.getDeclarationFromStatic("gnu.kawa.reflect.SlotGet", "staticField"); static final Declaration makeDecl = Declaration.getDeclarationFromStatic("gnu.kawa.reflect.Invoke", "make"); static final Declaration invokeDecl = Declaration.getDeclarationFromStatic("gnu.kawa.reflect.Invoke", "invoke"); static final Declaration invokeStaticDecl = Declaration.getDeclarationFromStatic("gnu.kawa.reflect.Invoke", "invokeStatic"); static final Declaration instanceOfDecl = Declaration.getDeclarationFromStatic("kawa.standard.Scheme", "instanceOf"); static final Declaration castDecl = Declaration.getDeclarationFromStatic("gnu.kawa.functions.Convert", "as");}class NamedPart extends ProcedureN implements HasSetter, Externalizable, CanInline{ Object container; Object member; char kind; MethodProc methods; public NamedPart(Object container, Object member, char kind) { this.container = container; this.member = member; this.kind = kind; } public NamedPart (Object container, String mname, char kind, MethodProc methods) { this.container = container; this.methods = methods; this.member = mname; this.kind = kind; } public int numArgs() { if (kind == 'I' || kind == 'C') return 0x1001; if (kind == 'D') return 0x1000; return 0xfffff000; } public Expression inline (ApplyExp exp, ExpWalker walker) { Expression[] args = exp.getArgs(); switch (kind) { case 'D': String fname = member.toString().substring(1); Expression[] xargs = new Expression[2]; xargs[1] = QuoteExp.getInstance(fname); SlotGet proc; if (args.length > 0) { xargs[0] = Convert.makeCoercion(args[0], new QuoteExp(container)); proc = SlotGet.field; } else { xargs[0] = QuoteExp.getInstance(container); proc = SlotGet.staticField; } ApplyExp aexp = new ApplyExp(proc, xargs); aexp.setLine(exp); return ((InlineCalls) walker).walkApplyOnly(aexp); } return exp; } public void apply (CallContext ctx) throws Throwable { apply(ctx.getArgs(), ctx); } public void apply (Object[] args, CallContext ctx) throws Throwable { // Optimization, so that output from the // method is sent directly to ctx.consumer, rather than reified. if (kind == 'S') methods.checkN(args, ctx); else if (kind=='M') { int nargs = args.length; Object[] xargs = new Object[nargs+1]; xargs[0] = container; System.arraycopy(args, 0, xargs, 1, nargs); methods.checkN(xargs, ctx); } else ctx.writeValue(this.applyN(args)); } public Object applyN (Object[] args) throws Throwable { Object[] xargs; switch (kind) { case 'I': return kawa.standard.Scheme.instanceOf.apply2(args[0], container); case 'C': return gnu.kawa.functions.Convert.as.apply2(container, args[0]); case 'N': xargs = new Object[args.length+1]; xargs[0] = container; System.arraycopy(args, 0, xargs, 1, args.length); return Invoke.make.applyN(xargs); case 'S': return methods.applyN(args); case 'M': xargs = new Object[args.length+1]; xargs[0] = container; System.arraycopy(args, 0, xargs, 1, args.length); return methods.applyN(xargs); case 'D': String fname = member.toString().substring(1); if (args.length == 0) return SlotGet.staticField((ClassType) container, fname); else return SlotGet.field(((Type) container).coerceFromObject(args[0]), fname); } throw new Error("unknown part "+member+" in "+container); } public Procedure getSetter() { if (kind == 'D') return new NamedPartSetter(this); else throw new RuntimeException("procedure '"+getName()+ "' has no setter"); } public void set0 (Object value) throws Throwable { switch (kind) { case 'D': String fname = member.toString().substring(1); SlotSet.setStaticField((ClassType) container, fname, value); return; default: throw new Error("invalid setter for "+this); } } public void set1 (Object object, Object value) throws Throwable { switch (kind) { case 'D': String fname = member.toString().substring(1); object = ((Type) container).coerceFromObject(object); SlotSet.setField(object, fname, value); return; default: throw new Error("invalid setter for "+this); } } public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(container); out.writeObject(member); out.writeChar(kind); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { kind = in.readChar(); container = (Procedure) in.readObject(); member = (Procedure) in.readObject(); }}class NamedPartSetter extends gnu.mapping.Setter implements Externalizable, CanInline{ public NamedPartSetter (NamedPart getter) { super(getter); } public int numArgs() { if (((NamedPart) getter).kind == 'D') return 0x2001; return 0xfffff000; } public Expression inline (ApplyExp exp, ExpWalker walker) { NamedPart get = (NamedPart) this.getter; if (get.kind == 'D') { Expression[] xargs = new Expression[3]; xargs[1] = QuoteExp.getInstance(get.member.toString().substring(1)); xargs[2] = exp.getArgs()[0]; SlotSet proc; if (exp.getArgCount() == 1) { xargs[0] = QuoteExp.getInstance(get.container); proc = SlotSet.set$Mnstatic$Mnfield$Ex; } else if (exp.getArgCount() == 2) { xargs[0] = Convert.makeCoercion(exp.getArgs()[0], new QuoteExp(get.container)); proc = SlotSet.set$Mnfield$Ex; } else return exp; ApplyExp aexp = new ApplyExp(proc, xargs); aexp.setLine(exp); return ((InlineCalls) walker).walkApplyOnly(aexp); } return exp; } public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(getter); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { getter = (Procedure) in.readObject(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -