applytoargs.java
来自「A framework written in Java for implemen」· Java 代码 · 共 230 行
JAVA
230 行
package gnu.kawa.functions;import gnu.bytecode.*;import gnu.expr.*;import gnu.mapping.*;import gnu.kawa.reflect.Invoke;import gnu.kawa.reflect.ArrayGet;/** Implement the standard Scheme function "apply". * This has been generalized so that the last (list argument) * can be any sequence, or any primitive array coercible to Object[]. */public class ApplyToArgs extends ProcedureN implements CanInline{ public int match1 (Object arg1, CallContext ctx) { if (arg1 instanceof Procedure) return ((Procedure) arg1).match0(ctx); else return super.match1(arg1, ctx); } public int match2 (Object arg1, Object arg2, CallContext ctx) { if (arg1 instanceof Procedure) return ((Procedure) arg1).match1(arg2, ctx); else return super.match2(arg1, arg2, ctx); } public int match3 (Object arg1, Object arg2, Object arg3, CallContext ctx) { if (arg1 instanceof Procedure) return ((Procedure) arg1).match2(arg2, arg3, ctx); else return super.match3(arg1, arg2, arg3, ctx); } public int match4 (Object arg1, Object arg2, Object arg3, Object arg4, CallContext ctx) { if (arg1 instanceof Procedure) return ((Procedure) arg1).match3(arg2, arg3, arg4, ctx); else return super.match4(arg1, arg2, arg3, arg4, ctx); } public int matchN (Object[] args, CallContext ctx) { int n = args.length; if (n > 0 && args[0] instanceof Procedure) { Procedure proc = (Procedure) args[0]; switch (n) { case 1: return proc.match0(ctx); case 2: return proc.match1(args[1], ctx); case 3: return proc.match2(args[1], args[2], ctx); case 4: return proc.match3(args[1], args[2], args[3], ctx); case 5: return proc.match4(args[1], args[2], args[3], args[4], ctx); default: Object[] xargs = new Object[n-1]; System.arraycopy(args, 1, xargs, 0, n-1); return proc.matchN(xargs, ctx); } } return super.matchN(args, ctx); } public void check1 (Object arg1, CallContext ctx) { if (arg1 instanceof Procedure) ((Procedure) arg1).check0(ctx); else super.check1(arg1, ctx); } public void check2 (Object arg1, Object arg2, CallContext ctx) { if (arg1 instanceof Procedure) ((Procedure) arg1).check1(arg2, ctx); else super.check2(arg1, arg2, ctx); } public void check3 (Object arg1, Object arg2, Object arg3, CallContext ctx) { if (arg1 instanceof Procedure) ((Procedure) arg1).check2(arg2, arg3, ctx); else super.check3(arg1, arg2, arg3, ctx); } public void check4 (Object arg1, Object arg2, Object arg3, Object arg4, CallContext ctx) { if (arg1 instanceof Procedure) ((Procedure) arg1).check3(arg2, arg3, arg4, ctx); else super.check4(arg1, arg2, arg3, arg4, ctx); } public void checkN (Object[] args, CallContext ctx) { int code = matchN(args, ctx); if (code != 0) { Procedure proc = this; if (args.length > 0 && args[0] instanceof Procedure) { proc = (Procedure) args[0]; Object[] xargs = new Object[args.length-1]; System.arraycopy(args, 1, xargs, 0, xargs.length); args = xargs; } throw MethodProc.matchFailAsException(code, proc, args); } } public ApplyToArgs (String name, Language language) { super(name); this.language = language; } Language language; public Expression inline (ApplyExp exp, ExpWalker walker) { Expression[] args = exp.getArgs(); int nargs = args.length - 1; if (nargs >= 0) { Expression proc = args[0]; args[0] = proc; Type ptype = proc.getType(); ApplyExp result; Compilation comp = walker.getCompilation(); Language language = comp.getLanguage(); // This might be more cleanly handled at the type specifier. FIXME if (Invoke.checkKnownClass(ptype, comp) < 0) return exp; ClassType ctype; if (ptype.isSubtype(Compilation.typeProcedure)) { Expression[] rargs = new Expression[nargs]; System.arraycopy(args, 1, rargs, 0, nargs); result = new ApplyExp(proc, rargs); } else if (ptype.isSubtype(Compilation.typeType) || language.getTypeFor(proc,false) != null) { result = new ApplyExp(Invoke.make, args); } else if (ptype instanceof ArrayType) { Type elementType = ((ArrayType) ptype).getComponentType(); result = new ApplyExp(new ArrayGet(elementType), args); } else if (ptype instanceof ClassType && (ctype = (ClassType) ptype).isSubclass(typeList) && nargs == 1) { // We search for a "get(int)" method, rather than just using // typeList.getDeclaredMethod("get", 1) to see if we make a // a virtual call rather than an interface call. Method get = ctype.getMethod("get", new Type[] { Type.int_type }); result = new ApplyExp(get, args); } else return exp; result.setLine(exp); return ((InlineCalls) walker).walkApplyOnly(result); } return exp; } static final ClassType typeList /* #ifdef JAVA2 */ = ClassType.make("java.util.List"); /* #else */ // = ClassType.make("gnu.lists.Sequence"); /* #endif */ public Object applyN (Object[] args) throws Throwable { Object proc = args[0]; Object[] rargs = new Object[args.length-1]; System.arraycopy(args, 1, rargs, 0, rargs.length); if (proc instanceof Procedure) { return ((Procedure) proc).applyN(rargs); } if (proc instanceof gnu.bytecode.Type) { return gnu.kawa.reflect.Invoke.make.applyN(args); } if (proc instanceof /* #ifdef JAVA2 */ java.util.List /* #else */ // gnu.lists.Sequence /* #endif */ ) { if (args.length != 2) throw new WrongArguments(this, args.length); // FIXME int index = ((Number) rargs[0]).intValue(); /* #ifdef JAVA2 */ return ((java.util.List) proc).get(index); /* #else */ // return ((gnu.lists.Sequence) proc).get(index); /* #endif */ } Class pclass = proc.getClass(); if (pclass.isArray()) { if (args.length != 2) throw new WrongArguments(this, args.length); // FIXME return java.lang.reflect.Array.get(proc, ((Number) rargs[0]).intValue()); } throw new WrongType(this, 0, proc, "procedure"); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?