Beispiel #1
0
  /**
   * Type check a predicate expression. If the type of the expression is number convert it to
   * boolean by adding a comparison with position(). Note that if the expression is a parameter, we
   * cannot distinguish at compile time if its type is number or not. Hence, expressions of
   * reference type are always converted to booleans.
   *
   * <p>This method may be called twice, before and after calling <code>dontOptimize()</code>. If
   * so, the second time it should honor the new value of <code>_canOptimize</code>.
   */
  public Type typeCheck(SymbolTable stable) throws TypeCheckError {
    Type texp = _exp.typeCheck(stable);

    // We need explicit type information for reference types - no good!
    if (texp instanceof ReferenceType) {
      _exp = new CastExpr(_exp, texp = Type.Real);
    }

    // A result tree fragment should not be cast directly to a number type,
    // but rather to a boolean value, and then to a numer (0 or 1).
    // Ref. section 11.2 of the XSLT 1.0 spec
    if (texp instanceof ResultTreeType) {
      _exp = new CastExpr(_exp, Type.Boolean);
      _exp = new CastExpr(_exp, Type.Real);
      texp = _exp.typeCheck(stable);
    }

    // Numerical types will be converted to a position filter
    if (texp instanceof NumberType) {
      // Cast any numerical types to an integer
      if (texp instanceof IntType == false) {
        _exp = new CastExpr(_exp, Type.Int);
      }

      if (_canOptimize) {
        // Nth position optimization. Expression must not depend on context
        _nthPositionFilter = !_exp.hasLastCall() && !_exp.hasPositionCall();

        // _nthDescendant optimization - only if _nthPositionFilter is on
        if (_nthPositionFilter) {
          SyntaxTreeNode parent = getParent();
          _nthDescendant =
              (parent instanceof Step) && (parent.getParent() instanceof AbsoluteLocationPath);
          return _type = Type.NodeSet;
        }
      }

      // Reset optimization flags
      _nthPositionFilter = _nthDescendant = false;

      // Otherwise, expand [e] to [position() = e]
      final QName position = getParser().getQNameIgnoreDefaultNs("position");
      final PositionCall positionCall = new PositionCall(position);
      positionCall.setParser(getParser());
      positionCall.setParent(this);

      _exp = new EqualityExpr(Operators.EQ, positionCall, _exp);
      if (_exp.typeCheck(stable) != Type.Boolean) {
        _exp = new CastExpr(_exp, Type.Boolean);
      }
      return _type = Type.Boolean;
    } else {
      // All other types will be handled as boolean values
      if (texp instanceof BooleanType == false) {
        _exp = new CastExpr(_exp, Type.Boolean);
      }
      return _type = Type.Boolean;
    }
  }
Beispiel #2
0
 /** Returns true if the expression in this predicate contains a call to last(). */
 public boolean hasLastCall() {
   return _exp.hasLastCall();
 }
 public boolean hasLastCall() {
   if (_left.hasLastCall()) return true;
   if (_right.hasLastCall()) return true;
   return false;
 }