예제 #1
0
  /**
   * Compile: this registers the template with the rule manager, and ensures space is available for
   * local variables
   */
  public Expression compile(Executable exec) throws XPathException {

    Expression block = compileSequenceConstructor(exec, iterateAxis(Axis.CHILD), true);
    if (block == null) {
      block = Literal.makeEmptySequence();
    }
    compiledTemplate.setMatchPattern(match);
    compiledTemplate.setBody(block);
    compiledTemplate.setStackFrameMap(stackFrameMap);
    compiledTemplate.setExecutable(getExecutable());
    compiledTemplate.setSystemId(getSystemId());
    compiledTemplate.setLineNumber(getLineNumber());
    compiledTemplate.setHasRequiredParams(hasRequiredParams);
    compiledTemplate.setRequiredType(requiredType);

    Expression exp = null;
    try {
      exp = makeExpressionVisitor().simplify(block);
    } catch (XPathException e) {
      compileError(e);
    }

    try {
      if (requiredType != null) {
        RoleLocator role = new RoleLocator(RoleLocator.TEMPLATE_RESULT, diagnosticId, 0);
        // role.setSourceLocator(new ExpressionLocation(this));
        role.setErrorCode("XTTE0505");
        exp = TypeChecker.staticTypeCheck(exp, requiredType, false, role, makeExpressionVisitor());
      }
    } catch (XPathException err) {
      compileError(err);
    }

    compiledTemplate.setBody(exp);
    compiledTemplate.init(getObjectName(), getPrecedence(), getMinImportPrecedence());

    if (getConfiguration().isCompileWithTracing()) {
      TraceWrapper trace = new TraceInstruction(exp, this);
      trace.setLocationId(allocateLocationId(getSystemId(), getLineNumber()));
      trace.setContainer(compiledTemplate);
      exp = trace;
      compiledTemplate.setBody(exp);
    }

    ItemType contextItemType = Type.ITEM_TYPE;
    if (getObjectName() == null) {
      // the template can't be called by name, so the context item must match the match pattern
      contextItemType = match.getNodeTest();
    }

    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.
      Expression exp2 = visitor.typeCheck(exp, contextItemType);
      exp2 = visitor.optimize(exp2, contextItemType);
      if (exp != exp2) {
        compiledTemplate.setBody(exp2);
        exp = exp2;
      }
    } catch (XPathException e) {
      compileError(e);
    }

    // Try to extract new global variables from the body of the function
    //        ExpressionPresenter presenter = ExpressionPresenter.make(getConfiguration());
    //        exp.explain(presenter);
    //        presenter.close();
    if (!getConfiguration().isCompileWithTracing()) {
      Expression exp2 = getConfiguration().getOptimizer().promoteExpressionsToGlobal(exp, visitor);
      if (exp != exp2) {
        compiledTemplate.setBody(exp2);
        exp = exp2;
      }
    }

    allocateSlots(exp);
    if (match != null) {
      RuleManager mgr = getPrincipalStylesheet().getRuleManager();
      for (int i = 0; i < modeNames.length; i++) {
        StructuredQName nc = modeNames[i];
        Mode mode = mgr.getMode(nc, true);
        if (prioritySpecified) {
          mgr.setHandler(match, compiledTemplate, mode, getPrecedence(), priority);
        } else {
          mgr.setHandler(match, compiledTemplate, mode, getPrecedence());
        }
      }

      allocatePatternSlots(match, getSlotManager());
    }

    if (isExplaining()) {
      System.err.println(
          "Optimized expression tree for template at line "
              + getLineNumber()
              + " in "
              + getSystemId()
              + ':');
      exp.explain(System.err);
    }

    return null;
  }