Beispiel #1
0
 /**
  * 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);
     }
   }
 }
Beispiel #2
0
  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);
    }
  }
Beispiel #3
0
  /**
   * 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);
    }
  }
Beispiel #4
0
  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());
    }
  }