Пример #1
0
  /** Typing rules: see XSLT Reference by M. Kay page 345. */
  public Type typeCheck(SymbolTable stable) throws TypeCheckError {
    final Type tleft = _left.typeCheck(stable);
    final Type tright = _right.typeCheck(stable);

    if (tleft.isSimple() && tright.isSimple()) {
      if (tleft != tright) {
        if (tleft instanceof BooleanType) {
          _right = new CastExpr(_right, Type.Boolean);
        } else if (tright instanceof BooleanType) {
          _left = new CastExpr(_left, Type.Boolean);
        } else if (tleft instanceof NumberType || tright instanceof NumberType) {
          _left = new CastExpr(_left, Type.Real);
          _right = new CastExpr(_right, Type.Real);
        } else { // both compared as strings
          _left = new CastExpr(_left, Type.String);
          _right = new CastExpr(_right, Type.String);
        }
      }
    } else if (tleft instanceof ReferenceType) {
      _right = new CastExpr(_right, Type.Reference);
    } else if (tright instanceof ReferenceType) {
      _left = new CastExpr(_left, Type.Reference);
    }
    // the following 2 cases optimize @attr|.|.. = 'string'
    else if (tleft instanceof NodeType && tright == Type.String) {
      _left = new CastExpr(_left, Type.String);
    } else if (tleft == Type.String && tright instanceof NodeType) {
      _right = new CastExpr(_right, Type.String);
    }
    // optimize node/node
    else if (tleft instanceof NodeType && tright instanceof NodeType) {
      _left = new CastExpr(_left, Type.String);
      _right = new CastExpr(_right, Type.String);
    } else if (tleft instanceof NodeType && tright instanceof NodeSetType) {
      // compare(Node, NodeSet) will be invoked
    } else if (tleft instanceof NodeSetType && tright instanceof NodeType) {
      swapArguments(); // for compare(Node, NodeSet)
    } else {
      // At least one argument is of type node, node-set or result-tree

      // Promote an expression of type node to node-set
      if (tleft instanceof NodeType) {
        _left = new CastExpr(_left, Type.NodeSet);
      }
      if (tright instanceof NodeType) {
        _right = new CastExpr(_right, Type.NodeSet);
      }

      // If one arg is a node-set then make it the left one
      if (tleft.isSimple() || tleft instanceof ResultTreeType && tright instanceof NodeSetType) {
        swapArguments();
      }

      // Promote integers to doubles to have fewer compares
      if (_right.getType() instanceof IntType) {
        _right = new CastExpr(_right, Type.Real);
      }
    }
    return _type = Type.Boolean;
  }
Пример #2
0
  /** Type check the two parameters for this function */
  public Type typeCheck(SymbolTable stable) throws TypeCheckError {
    // Check that the function was passed exactly two arguments
    if (argumentCount() != 2) {
      throw new TypeCheckError(new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR, getName(), this));
    }

    // The first argument must be a literal String
    Expression exp = argument(0);
    if (exp instanceof LiteralExpr) {
      _className = ((LiteralExpr) exp).getValue();
      _type = Type.newObjectType(_className);
    } else {
      throw new TypeCheckError(new ErrorMsg(ErrorMsg.NEED_LITERAL_ERR, getName(), this));
    }

    // Second argument must be of type reference or object
    _right = argument(1);
    Type tright = _right.typeCheck(stable);
    if (tright != Type.Reference && tright instanceof ObjectType == false) {
      throw new TypeCheckError(new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, tright, _type, this));
    }

    return _type;
  }
Пример #3
0
  public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
    final ConstantPoolGen cpg = classGen.getConstantPool();
    final InstructionList il = methodGen.getInstructionList();

    // Save current node and current iterator on the stack
    il.append(methodGen.loadCurrentNode());
    il.append(methodGen.loadIterator());

    // Collect sort objects associated with this instruction
    final Vector sortObjects = new Vector();
    Enumeration children = elements();
    while (children.hasMoreElements()) {
      final Object child = children.nextElement();
      if (child instanceof Sort) {
        sortObjects.addElement(child);
      }
    }

    if ((_type != null) && (_type instanceof ResultTreeType)) {
      // Store existing DOM on stack - must be restored when loop is done
      il.append(methodGen.loadDOM());

      // <xsl:sort> cannot be applied to a result tree - issue warning
      if (sortObjects.size() > 0) {
        ErrorMsg msg = new ErrorMsg(ErrorMsg.RESULT_TREE_SORT_ERR, this);
        getParser().reportError(WARNING, msg);
      }

      // Put the result tree on the stack (DOM)
      _select.translate(classGen, methodGen);
      // Get an iterator for the whole DOM - excluding the root node
      _type.translateTo(classGen, methodGen, Type.NodeSet);
      // Store the result tree as the default DOM
      il.append(SWAP);
      il.append(methodGen.storeDOM());
    } else {
      // Compile node iterator
      if (sortObjects.size() > 0) {
        Sort.translateSortIterator(classGen, methodGen, _select, sortObjects);
      } else {
        _select.translate(classGen, methodGen);
      }

      if (_type instanceof ReferenceType == false) {
        il.append(methodGen.loadContextNode());
        il.append(methodGen.setStartNode());
      }
    }

    // Overwrite current iterator
    il.append(methodGen.storeIterator());

    // Give local variables (if any) default values before starting loop
    initializeVariables(classGen, methodGen);

    final BranchHandle nextNode = il.append(new GOTO(null));
    final InstructionHandle loop = il.append(NOP);

    translateContents(classGen, methodGen);

    nextNode.setTarget(il.append(methodGen.loadIterator()));
    il.append(methodGen.nextNode());
    il.append(DUP);
    il.append(methodGen.storeCurrentNode());
    il.append(new IFGT(loop));

    // Restore current DOM (if result tree was used instead for this loop)
    if ((_type != null) && (_type instanceof ResultTreeType)) {
      il.append(methodGen.storeDOM());
    }

    // Restore current node and current iterator from the stack
    il.append(methodGen.storeIterator());
    il.append(methodGen.storeCurrentNode());
  }
Пример #4
0
  public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
    final ConstantPoolGen cpg = classGen.getConstantPool();
    final InstructionList il = methodGen.getInstructionList();

    final Type tleft = _left.getType();
    Type tright = _right.getType();

    if (tleft instanceof BooleanType || tleft instanceof NumberType) {
      translateDesynthesized(classGen, methodGen);
      synthesize(classGen, methodGen);
      return;
    }

    if (tleft instanceof StringType) {
      final int equals = cpg.addMethodref(STRING_CLASS, "equals", "(" + OBJECT_SIG + ")Z");
      _left.translate(classGen, methodGen);
      _right.translate(classGen, methodGen);
      il.append(new INVOKEVIRTUAL(equals));

      if (_op == Operators.NE) {
        il.append(ICONST_1);
        il.append(IXOR); // not x <-> x xor 1
      }
      return;
    }

    BranchHandle truec, falsec;

    if (tleft instanceof ResultTreeType) {
      if (tright instanceof BooleanType) {
        _right.translate(classGen, methodGen);
        if (_op == Operators.NE) {
          il.append(ICONST_1);
          il.append(IXOR); // not x <-> x xor 1
        }
        return;
      }

      if (tright instanceof RealType) {
        _left.translate(classGen, methodGen);
        tleft.translateTo(classGen, methodGen, Type.Real);
        _right.translate(classGen, methodGen);

        il.append(DCMPG);
        falsec =
            il.append(
                _op == Operators.EQ
                    ? (BranchInstruction) new IFNE(null)
                    : (BranchInstruction) new IFEQ(null));
        il.append(ICONST_1);
        truec = il.append(new GOTO(null));
        falsec.setTarget(il.append(ICONST_0));
        truec.setTarget(il.append(NOP));
        return;
      }

      // Next, result-tree/string and result-tree/result-tree comparisons

      _left.translate(classGen, methodGen);
      tleft.translateTo(classGen, methodGen, Type.String);
      _right.translate(classGen, methodGen);

      if (tright instanceof ResultTreeType) {
        tright.translateTo(classGen, methodGen, Type.String);
      }

      final int equals = cpg.addMethodref(STRING_CLASS, "equals", "(" + OBJECT_SIG + ")Z");
      il.append(new INVOKEVIRTUAL(equals));

      if (_op == Operators.NE) {
        il.append(ICONST_1);
        il.append(IXOR); // not x <-> x xor 1
      }
      return;
    }

    if (tleft instanceof NodeSetType && tright instanceof BooleanType) {
      _left.translate(classGen, methodGen);
      _left.startIterator(classGen, methodGen);
      Type.NodeSet.translateTo(classGen, methodGen, Type.Boolean);
      _right.translate(classGen, methodGen);

      il.append(IXOR); // x != y <-> x xor y
      if (_op == Operators.EQ) {
        il.append(ICONST_1);
        il.append(IXOR); // not x <-> x xor 1
      }
      return;
    }

    if (tleft instanceof NodeSetType && tright instanceof StringType) {
      _left.translate(classGen, methodGen);
      _left.startIterator(classGen, methodGen); // needed ?
      _right.translate(classGen, methodGen);
      il.append(new PUSH(cpg, _op));
      il.append(methodGen.loadDOM());
      final int cmp =
          cpg.addMethodref(
              BASIS_LIBRARY_CLASS,
              "compare",
              "(" + tleft.toSignature() + tright.toSignature() + "I" + DOM_INTF_SIG + ")Z");
      il.append(new INVOKESTATIC(cmp));
      return;
    }

    // Next, node-set/t for t in {real, string, node-set, result-tree}
    _left.translate(classGen, methodGen);
    _left.startIterator(classGen, methodGen);
    _right.translate(classGen, methodGen);
    _right.startIterator(classGen, methodGen);

    // Cast a result tree to a string to use an existing compare
    if (tright instanceof ResultTreeType) {
      tright.translateTo(classGen, methodGen, Type.String);
      tright = Type.String;
    }

    // Call the appropriate compare() from the BasisLibrary
    il.append(new PUSH(cpg, _op));
    il.append(methodGen.loadDOM());

    final int compare =
        cpg.addMethodref(
            BASIS_LIBRARY_CLASS,
            "compare",
            "(" + tleft.toSignature() + tright.toSignature() + "I" + DOM_INTF_SIG + ")Z");
    il.append(new INVOKESTATIC(compare));
  }