📄 invoke.java
字号:
Language language = comp.getLanguage(); Expression[] args = exp.getArgs(); if (args.length > carg) { Type type = language.getTypeFor(args[carg]); if (! (type instanceof Type)) return exp; checkKnownClass(type, comp); Expression[] nargs = new Expression[args.length]; System.arraycopy(args, 0, nargs, 0, args.length); nargs[carg] = new QuoteExp(type); ApplyExp nexp = new ApplyExp(exp.getFunction(), nargs); nexp.setLine(exp); return nexp; } return exp; } public Expression inline (ApplyExp exp, ExpWalker walker) { Compilation comp = walker.getCompilation(); Expression[] args = exp.getArgs(); int nargs = args.length; if (! comp.mustCompile // This should never happen, as InlineCalls.walkApplyExp // checks the number of arguments before inline is called. || nargs == 0 || ((kind == 'V' || kind == '*') && nargs == 1)) return exp; ObjectType type; Expression arg0 = args[0]; Type type0 = (kind == 'V' || kind == '*' ? arg0.getType() : language.getTypeFor(arg0)); if (type0 instanceof PairClassType) type = ((PairClassType) type0).instanceType; else if (type0 instanceof ObjectType) type = (ObjectType) type0; else type = null; String name = getMethodName(args); int margsLength, argsStartIndex, objIndex; if (kind == 'V' || kind == '*') // Invoke virtual { margsLength = nargs - 1; argsStartIndex = 2; objIndex = 0; } else if (kind == 'N') // make new { margsLength = nargs; argsStartIndex = 0; objIndex = -1; } else if (kind == 'S' || kind == 's') // Invoke static { margsLength = nargs - 2; argsStartIndex = 2; objIndex = -1; } else if (kind == 'P') // Invoke special { margsLength = nargs - 2; argsStartIndex = 3; objIndex = 1; } else return exp; if (kind == 'N' && type instanceof ArrayType) { ArrayType atype = (ArrayType) type; Type elementType = atype.getComponentType(); Expression sizeArg = null; boolean lengthSpecified = false; if (args.length >= 3 && args[1] instanceof QuoteExp) { Object arg1 = ((QuoteExp) args[1]).getValue(); if (arg1 instanceof Keyword && ("length".equals(name = ((Keyword) arg1).getName()) || "size".equals(name))) { sizeArg = args[2]; lengthSpecified = true; } } if (sizeArg == null) sizeArg = QuoteExp.getInstance(new Integer(args.length-1)); Expression alloc = new ApplyExp(new ArrayNew(elementType), new Expression[] { sizeArg } ); if (lengthSpecified && args.length == 3) return alloc; LetExp let = new LetExp(new Expression[] { alloc }); Declaration adecl = let.addDeclaration((String) null, atype); adecl.noteValue(alloc); BeginExp begin = new BeginExp(); int index = 0; for (int i = lengthSpecified ? 3 : 1; i < args.length; i++) { Expression arg = args[i]; if (lengthSpecified && i+1 < args.length && arg instanceof QuoteExp) { Object key = ((QuoteExp) arg).getValue(); if (key instanceof Keyword) { String kname = ((Keyword) key).getName(); try { index = Integer.parseInt(kname); arg = args[++i]; } catch (Throwable ex) { comp.error('e', "non-integer keyword '"+kname+"' in array constructor"); return exp; } } } begin.add(new ApplyExp(new ArraySet(elementType), new Expression[] { new ReferenceExp(adecl), QuoteExp.getInstance(new Integer(index)), arg})); index++; } begin.add(new ReferenceExp(adecl)); let.body = begin; return let; } else if (type != null && name != null) { if (type instanceof TypeValue && kind == 'N') { Procedure constructor = ((TypeValue) type).getConstructor(); if (constructor != null) { Expression[] xargs = new Expression[nargs-1]; System.arraycopy(args, 1, xargs, 0, nargs-1); return ((InlineCalls) walker) .walkApplyOnly(new ApplyExp(constructor, xargs)); } } PrimProcedure[] methods; int okCount, maybeCount; ClassType caller = comp == null ? null : comp.curClass != null ? comp.curClass : comp.mainClass; ObjectType ctype = (ObjectType) type; try { methods = getMethods(ctype, name, caller); long num = selectApplicable(methods, ctype, args, margsLength, argsStartIndex, objIndex); okCount = (int) (num >> 32); maybeCount = (int) num; } catch (Exception ex) { comp.error('w', "unknown class: " + type.getName()); return exp; } int index = -1; Object[] slots; if (okCount + maybeCount == 0 && kind == 'N' && (ClassMethods.selectApplicable(methods, new Type[] { Compilation.typeClassType }) >> 32) == 1 && (slots = checkKeywords(type, args, 1, caller)) != null) { StringBuffer errbuf = null; for (int i = 0; i < slots.length; i++) { if (slots[i] instanceof String) { if (errbuf == null) { errbuf = new StringBuffer(); errbuf.append("no field or setter "); } else errbuf.append(", "); errbuf.append('`'); errbuf.append(slots[i]); errbuf.append('\''); } } if (errbuf != null) { errbuf.append(" in class "); errbuf.append(type.getName()); comp.error('w', errbuf.toString()); return exp; } else { ApplyExp e = new ApplyExp(methods[0], new Expression[] { arg0 }); for (int i = 0; i < slots.length; i++) { Expression[] sargs = { e, new QuoteExp(slots[i]), args[2 * i + 2] }; e = new ApplyExp(SlotSet.setFieldReturnObject, sargs); } return e.setLine(exp); } } int nmethods = methods.length; if (okCount + maybeCount == 0 && kind == 'N') { methods = invokeStatic.getMethods(ctype, "valueOf", caller); argsStartIndex = 1; margsLength = nargs - 1; long num = selectApplicable(methods, ctype, args, margsLength, argsStartIndex, -1); okCount = (int) (num >> 32); maybeCount = (int) num; } if (okCount + maybeCount == 0) { if (comp.getBooleanOption("warn-invoke-unknown-method", true)) { if (kind=='N') name = name+"/valueOf"; if (nmethods + methods.length == 0) comp.error('w', "no accessible method '"+name+"' in "+type.getName()); else comp.error('w', "no possibly applicable method '" +name+"' in "+type.getName()); } } else if (okCount == 1 || (okCount == 0 && maybeCount == 1)) index = 0; else if (okCount > 0) { index = MethodProc.mostSpecific(methods, okCount); if (index < 0) { if (kind == 'S') { // If we didn't find a most specific method, // check if there is one that is static. If so, // prefer that - after all, we're using invoke-static. for (int i = 0; i < okCount; i++) { if (methods[i].getStaticFlag()) { if (index >= 0) { index = -1; break; } else index = i; } } } } if (index < 0 && comp.getBooleanOption("warn-invoke-unknown-method", true)) { StringBuffer sbuf = new StringBuffer(); sbuf.append("more than one definitely applicable method `"); sbuf.append(name); sbuf.append("' in "); sbuf.append(type.getName()); append(methods, okCount, sbuf); comp.error('w', sbuf.toString()); } } else if (comp.getBooleanOption("warn-invoke-unknown-method", true)) { StringBuffer sbuf = new StringBuffer(); sbuf.append("more than one possibly applicable method '"); sbuf.append(name); sbuf.append("' in "); sbuf.append(type.getName()); append(methods, maybeCount, sbuf); comp.error('w', sbuf.toString()); } if (index >= 0) { Expression[] margs = new Expression[margsLength]; int dst = 0; if (objIndex >= 0) margs[dst++] = args[objIndex]; for (int src = argsStartIndex; src < args.length && dst < margs.length; src++, dst++) margs[dst] = args[src]; return new ApplyExp(methods[index], margs).setLine(exp); } } return exp; } private void append (PrimProcedure[] methods, int mcount, StringBuffer sbuf) { for (int i = 0; i < mcount; i++) { sbuf.append("\n candidate: "); sbuf.append(methods[i]); } } private String getMethodName(Expression[] args) { if (kind == 'N') return "<init>"; int nameIndex = (kind == 'P' ? 2 : 1); if (args.length >= nameIndex + 1) return ClassMethods.checkName(args[nameIndex], false); return null; } /** Return an ApplyExp that will call a method with given arguments. * @param type the class containing the method we want to call. * @param name the name of the method we want to call * @param args the arguments to the call * @return an ApplyExp representing the call */ public static synchronized ApplyExp makeInvokeStatic(ClassType type, String name, Expression[] args) { PrimProcedure method = getStaticMethod(type, name, args); if (method == null) throw new RuntimeException("missing or ambiguous method `" + name + "' in " + type.getName()); return new ApplyExp(method, args); } public static synchronized PrimProcedure getStaticMethod(ClassType type, String name, Expression[] args) { PrimProcedure[] methods = invokeStatic.getMethods(type, name, null); long num = selectApplicable(methods, type, args, args.length, 0, -1); int okCount = (int) (num >> 32); int maybeCount = (int) num; int index; if (methods == null) index = -1; else if (okCount > 0) index = MethodProc.mostSpecific(methods, okCount); else if (maybeCount == 1) index = 0; else index = -1; return index < 0 ? null : methods[index]; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -