📄 functioncall.java
字号:
if (local.indexOf('-') > 0) { local = replaceDash(local); } String extFunction = (String)_extensionFunctionTable.get(namespace + ":" + local); if (extFunction != null) { _fname = new QName(null, null, extFunction); return typeCheckStandard(stable); } else _fname = new QName(namespace, null, local); } return typeCheckExternal(stable); } catch (TypeCheckError e) { ErrorMsg errorMsg = e.getErrorMsg(); if (errorMsg == null) { final String name = _fname.getLocalPart(); errorMsg = new ErrorMsg(ErrorMsg.METHOD_NOT_FOUND_ERR, name); } getParser().reportError(ERROR, errorMsg); return _type = Type.Void; } } } /** * Type check a call to a standard function. Insert CastExprs when needed. * If as a result of the insertion of a CastExpr a type check error is * thrown, then catch it and re-throw it with a new "this". */ public Type typeCheckStandard(SymbolTable stable) throws TypeCheckError { _fname.clearNamespace(); // HACK!!! final int n = _arguments.size(); final Vector argsType = typeCheckArgs(stable); final MethodType args = new MethodType(Type.Void, argsType); final MethodType ptype = lookupPrimop(stable, _fname.getLocalPart(), args); if (ptype != null) { for (int i = 0; i < n; i++) { final Type argType = (Type) ptype.argsType().elementAt(i); final Expression exp = (Expression)_arguments.elementAt(i); if (!argType.identicalTo(exp.getType())) { try { _arguments.setElementAt(new CastExpr(exp, argType), i); } catch (TypeCheckError e) { throw new TypeCheckError(this); // invalid conversion } } } _chosenMethodType = ptype; return _type = ptype.resultType(); } throw new TypeCheckError(this); } public Type typeCheckConstructor(SymbolTable stable) throws TypeCheckError{ final Vector constructors = findConstructors(); if (constructors == null) { // Constructor not found in this class throw new TypeCheckError(ErrorMsg.CONSTRUCTOR_NOT_FOUND, _className); } final int nConstructors = constructors.size(); final int nArgs = _arguments.size(); final Vector argsType = typeCheckArgs(stable); // Try all constructors int bestConstrDistance = Integer.MAX_VALUE; _type = null; // reset for (int j, i = 0; i < nConstructors; i++) { // Check if all parameters to this constructor can be converted final Constructor constructor = (Constructor)constructors.elementAt(i); final Class[] paramTypes = constructor.getParameterTypes(); Class extType = null; int currConstrDistance = 0; for (j = 0; j < nArgs; j++) { // Convert from internal (translet) type to external (Java) type extType = paramTypes[j]; final Type intType = (Type)argsType.elementAt(j); Object match = _internal2Java.maps(intType, extType); if (match != null) { currConstrDistance += ((JavaType)match).distance; } else if (intType instanceof ObjectType) { ObjectType objectType = (ObjectType)intType; if (objectType.getJavaClass() == extType) continue; else if (extType.isAssignableFrom(objectType.getJavaClass())) currConstrDistance += 1; else { currConstrDistance = Integer.MAX_VALUE; break; } } else { // no mapping available currConstrDistance = Integer.MAX_VALUE; break; } } if (j == nArgs && currConstrDistance < bestConstrDistance ) { _chosenConstructor = constructor; _isExtConstructor = true; bestConstrDistance = currConstrDistance; _type = (_clazz != null) ? Type.newObjectType(_clazz) : Type.newObjectType(_className); } } if (_type != null) { return _type; } throw new TypeCheckError(ErrorMsg.ARGUMENT_CONVERSION_ERR, getMethodSignature(argsType)); } /** * Type check a call to an external (Java) method. * The method must be static an public, and a legal type conversion * must exist for all its arguments and its return type. * Every method of name <code>_fname</code> is inspected * as a possible candidate. */ public Type typeCheckExternal(SymbolTable stable) throws TypeCheckError { int nArgs = _arguments.size(); final String name = _fname.getLocalPart(); // check if function is a contructor 'new' if (_fname.getLocalPart().equals("new")) { return typeCheckConstructor(stable); } // check if we are calling an instance method else { boolean hasThisArgument = false; if (nArgs == 0) _isStatic = true; if (!_isStatic) { if (_namespace_format == NAMESPACE_FORMAT_JAVA || _namespace_format == NAMESPACE_FORMAT_PACKAGE) hasThisArgument = true; Expression firstArg = (Expression)_arguments.elementAt(0); Type firstArgType = (Type)firstArg.typeCheck(stable); if (_namespace_format == NAMESPACE_FORMAT_CLASS && firstArgType instanceof ObjectType && _clazz != null && _clazz.isAssignableFrom(((ObjectType)firstArgType).getJavaClass())) hasThisArgument = true; if (hasThisArgument) { _thisArgument = (Expression) _arguments.elementAt(0); _arguments.remove(0); nArgs--; if (firstArgType instanceof ObjectType) { _className = ((ObjectType) firstArgType).getJavaClassName(); } else throw new TypeCheckError(ErrorMsg.NO_JAVA_FUNCT_THIS_REF, name); } } else if (_className.length() == 0) { /* * Warn user if external function could not be resolved. * Warning will _NOT_ be issued is the call is properly * wrapped in an <xsl:if> or <xsl:when> element. For details * see If.parserContents() and When.parserContents() */ final Parser parser = getParser(); if (parser != null) { reportWarning(this, parser, ErrorMsg.FUNCTION_RESOLVE_ERR, _fname.toString()); } unresolvedExternal = true; return _type = Type.Int; // use "Int" as "unknown" } } final Vector methods = findMethods(); if (methods == null) { // Method not found in this class throw new TypeCheckError(ErrorMsg.METHOD_NOT_FOUND_ERR, _className + "." + name); } Class extType = null; final int nMethods = methods.size(); final Vector argsType = typeCheckArgs(stable); // Try all methods to identify the best fit int bestMethodDistance = Integer.MAX_VALUE; _type = null; // reset internal type for (int j, i = 0; i < nMethods; i++) { // Check if all paramteters to this method can be converted final Method method = (Method)methods.elementAt(i); final Class[] paramTypes = method.getParameterTypes(); int currMethodDistance = 0; for (j = 0; j < nArgs; j++) { // Convert from internal (translet) type to external (Java) type extType = paramTypes[j]; final Type intType = (Type)argsType.elementAt(j); Object match = _internal2Java.maps(intType, extType); if (match != null) { currMethodDistance += ((JavaType)match).distance; } else { // no mapping available // // Allow a Reference type to match any external (Java) type at // the moment. The real type checking is performed at runtime. if (intType instanceof ReferenceType) { currMethodDistance += 1; } else if (intType instanceof ObjectType) { ObjectType object = (ObjectType)intType; if (extType.getName().equals(object.getJavaClassName())) currMethodDistance += 0; else if (extType.isAssignableFrom(object.getJavaClass())) currMethodDistance += 1; else { currMethodDistance = Integer.MAX_VALUE; break; } } else { currMethodDistance = Integer.MAX_VALUE; break; } } } if (j == nArgs) { // Check if the return type can be converted extType = method.getReturnType(); _type = (Type) _java2Internal.get(extType); if (_type == null) { _type = Type.newObjectType(extType); } // Use this method if all parameters & return type match if (_type != null && currMethodDistance < bestMethodDistance) { _chosenMethod = method; bestMethodDistance = currMethodDistance; } } } // It is an error if the chosen method is an instance menthod but we don't // have a this argument. if (_chosenMethod != null && _thisArgument == null && !Modifier.isStatic(_chosenMethod.getModifiers())) { throw new TypeCheckError(ErrorMsg.NO_JAVA_FUNCT_THIS_REF, getMethodSignature(argsType)); } if (_type != null) { if (_type == Type.NodeSet) { getXSLTC().setMultiDocument(true); } return _type; } throw new TypeCheckError(ErrorMsg.ARGUMENT_CONVERSION_ERR, getMethodSignature(argsType)); } /** * Type check the actual arguments of this function call. */ public Vector typeCheckArgs(SymbolTable stable) throws TypeCheckError { final Vector result = new Vector(); final Enumeration e = _arguments.elements(); while (e.hasMoreElements()) { final Expression exp = (Expression)e.nextElement(); result.addElement(exp.typeCheck(stable)); } return result; } protected final Expression argument(int i) { return (Expression)_arguments.elementAt(i); } protected final Expression argument() { return argument(0); } protected final int argumentCount() { return _arguments.size(); } protected final void setArgument(int i, Expression exp) { _arguments.setElementAt(exp, i); } /** * Compile the function call and treat as an expression * Update true/false-lists. */ public void translateDesynthesized(ClassGenerator classGen, MethodGenerator methodGen) { Type type = Type.Boolean; if (_chosenMethodType != null) type = _chosenMethodType.resultType(); final InstructionList il = methodGen.getInstructionList(); translate(classGen, methodGen); if ((type instanceof BooleanType) || (type instanceof IntType)) { _falseList.add(il.append(new IFEQ(null))); } } /** * Translate a function call. The compiled code will leave the function's * return value on the JVM's stack. */ public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final int n = argumentCount(); final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); final boolean isSecureProcessing = classGen.getParser().getXSLTC().isSecureProcessing(); int index; // Translate calls to methods in the BasisLibrary if (isStandard() || isExtension()) { for (int i = 0; i < n; i++) { final Expression exp = argument(i); exp.translate(classGen, methodGen); exp.startIterator(classGen, methodGen); } // append "F" to the function's name final String name = _fname.toString().replace('-', '_') + "F"; String args = Constants.EMPTYSTRING; // Special precautions for some method calls if (name.equals("sumF")) { args = DOM_INTF_SIG; il.append(methodGen.loadDOM()); } else if (name.equals("normalize_spaceF")) { if (_chosenMethodType.toSignature(args). equals("()Ljava/lang/String;")) { args = "I"+DOM_INTF_SIG; il.append(methodGen.loadContextNode()); il.append(methodGen.loadDOM());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -