/** * Set the definitions of the parameters in the compiled function, as an array. * * @param fn the compiled object representing the user-written function */ public void setParameterDefinitions(UserFunction fn) { UserFunctionParameter[] params = new UserFunctionParameter[getNumberOfArguments()]; fn.setParameterDefinitions(params); int count = 0; AxisIterator kids = iterateAxis(Axis.CHILD); while (true) { NodeInfo node = kids.next(); if (node == null) { return; } if (node instanceof XSLParam) { UserFunctionParameter param = new UserFunctionParameter(); params[count++] = param; param.setRequiredType(((XSLParam) node).getRequiredType()); param.setVariableQName(((XSLParam) node).getVariableQName()); param.setSlotNumber(((XSLParam) node).getSlotNumber()); ((XSLParam) node).fixupBinding(param); int refs = ExpressionTool.getReferenceCount(fn.getBody(), param, false); param.setReferenceCount(refs); } } }
public void typeCheckBody() throws XPathException { Expression exp = compiledFunction.getBody(); Expression exp2 = exp; ExpressionVisitor visitor = makeExpressionVisitor(); try { // We've already done the typecheck of each XPath expression, but it's worth doing again at // this // level because we have more information now. exp2 = visitor.typeCheck(exp, null); if (resultType != null) { RoleLocator role = new RoleLocator(RoleLocator.FUNCTION_RESULT, functionName, 0); role.setErrorCode("XTTE0780"); exp2 = TypeChecker.staticTypeCheck(exp2, resultType, false, role, visitor); } } catch (XPathException err) { err.maybeSetLocation(this); compileError(err); } if (exp2 != exp) { compiledFunction.setBody(exp2); } }
/** * Show a direct call from the Java application to a function defined in the Query. This is a very * efficient way of invoking a query, but it does minimal checking of the supplied arguments */ public static void exampleDirectFunction() throws XPathException { final Configuration config = new Configuration(); final StaticQueryContext sqc = config.newStaticQueryContext(); final XQueryExpression exp1 = sqc.compileQuery( "declare namespace f='f.ns';" + "declare function f:t1($v1 as xs:integer, $v2 as xs:untypedAtomic*) { " + " $v1 div $v2" + "};" + "10"); final UserFunction fn1 = exp1.getStaticContext().getUserDefinedFunction("f.ns", "t1", 2); if (fn1 == null) { throw new IllegalStateException("Function f:t1() not found"); } final Controller controller = exp1.newController(); final Value[] arglist = new Value[2]; arglist[0] = new Int64Value(10); for (int i = 3; i < 10; i++) { arglist[1] = new Int64Value(i); final ValueRepresentation result = fn1.call(arglist, controller); System.out.println(arglist[0] + " div " + arglist[1] + " = " + result); } }
/** * Compile the function into a UserFunction object, which treats the function body as a single * XPath expression. This involves recursively translating xsl:variable declarations into let * expressions, withe the action part of the let expression containing the rest of the function * body. The UserFunction that is created will be linked from all calls to this function, so * nothing else needs to be done with the result. If there are no calls to it, the compiled * function will be garbage-collected away. * * @param exec the Executable * @param decl this xsl:function declaration * @throws XPathException if a failure occurs */ private void compileAsExpression(Executable exec, Declaration decl) throws XPathException { Expression exp = compileSequenceConstructor(exec, decl, iterateAxis(Axis.CHILD), false); if (exp == null) { exp = Literal.makeEmptySequence(); } else { ExpressionVisitor visitor = makeExpressionVisitor(); exp = exp.simplify(visitor); } if (exec.getConfiguration().isCompileWithTracing()) { TraceExpression trace = new TraceExpression(exp); trace.setConstructType(StandardNames.XSL_FUNCTION); trace.setNamespaceResolver(getNamespaceResolver()); trace.setObjectName(getObjectName()); exp = trace; } UserFunction fn = exec.getConfiguration().newUserFunction(memoFunction); fn.setHostLanguage(Configuration.XSLT); fn.setBody(exp); fn.setFunctionName(getObjectName()); setParameterDefinitions(fn); fn.setResultType(getResultType()); fn.setLineNumber(getLineNumber()); fn.setSystemId(getSystemId()); fn.setStackFrameMap(stackFrameMap); fn.setExecutable(exec); compiledFunction = fn; fixupInstruction(fn); if (memoFunction && !fn.isMemoFunction()) { compileWarning( "Memo functions are not available in Saxon-HE: saxon:memo-function attribute ignored", SaxonErrorCode.SXWN9011); } }
public void optimize(Declaration declaration) throws XPathException { Expression exp = compiledFunction.getBody(); ExpressionVisitor visitor = makeExpressionVisitor(); Expression exp2 = exp; Optimizer opt = getConfiguration().obtainOptimizer(); try { if (opt.getOptimizationLevel() != Optimizer.NO_OPTIMIZATION) { exp2 = exp.optimize(visitor, null); } } catch (XPathException err) { err.maybeSetLocation(this); compileError(err); } // Try to extract new global variables from the body of the function if (opt.getOptimizationLevel() != Optimizer.NO_OPTIMIZATION) { Expression exp3 = opt.promoteExpressionsToGlobal(exp2, visitor); if (exp3 != null) { exp2 = visitor.optimize(exp3, null); } } // Add trace wrapper code if required exp2 = makeTraceInstruction(this, exp2); allocateSlots(exp2); if (exp2 != exp) { compiledFunction.setBody(exp2); } int tailCalls = ExpressionTool.markTailFunctionCalls(exp2, getObjectName(), getNumberOfArguments()); if (tailCalls != 0) { compiledFunction.setTailRecursive(tailCalls > 0, tailCalls > 1); compiledFunction.setBody(new TailCallLoop(compiledFunction)); } // Generate byte code if appropriate if (getConfiguration().isGenerateByteCode(Configuration.XSLT)) { try { Expression cbody = opt.compileToByteCode( compiledFunction.getBody(), nameAtt, Expression.PROCESS_METHOD | Expression.ITERATE_METHOD); if (cbody != null) { compiledFunction.setBody(cbody); } } catch (Exception e) { System.err.println("Failed while compiling function " + nameAtt); e.printStackTrace(); throw new XPathException(e); } } compiledFunction.computeEvaluationMode(); if (isExplaining()) { exp2.explain(getConfiguration().getStandardErrorOutput()); } }