15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright 2005 Frerich Raabe <raabe@kde.org>
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006 Apple Computer, Inc.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch *
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
1502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch *
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/xml/XPathPredicate.h"
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/xml/XPathFunctions.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/xml/XPathUtil.h"
33e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "wtf/MathExtras.h"
345d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include <math.h>
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace XPath {
3902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Number::Number(double value)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_value(value)
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
45d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void Number::trace(Visitor* visitor)
46d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
47d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    visitor->trace(m_value);
48d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    Expression::trace(visitor);
49d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
50d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Value Number::evaluate() const
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_value;
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)StringExpression::StringExpression(const String& value)
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_value(value)
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
61d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void StringExpression::trace(Visitor* visitor)
62d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
63d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    visitor->trace(m_value);
64d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    Expression::trace(visitor);
65d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
66d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Value StringExpression::evaluate() const
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_value;
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Value Negative::evaluate() const
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Value p(subExpr(0)->evaluate());
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return -p.toNumber();
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
78d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)NumericOp::NumericOp(Opcode opcode, PassOwnPtrWillBeRawPtr<Expression> lhs, PassOwnPtrWillBeRawPtr<Expression> rhs)
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_opcode(opcode)
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    addSubExpression(lhs);
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    addSubExpression(rhs);
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Value NumericOp::evaluate() const
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Value lhs(subExpr(0)->evaluate());
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Value rhs(subExpr(1)->evaluate());
8902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double leftVal = lhs.toNumber();
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double rightVal = rhs.toNumber();
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (m_opcode) {
945d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    case OP_Add:
955d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return leftVal + rightVal;
965d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    case OP_Sub:
975d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return leftVal - rightVal;
985d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    case OP_Mul:
995d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return leftVal * rightVal;
1005d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    case OP_Div:
1015d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return leftVal / rightVal;
1025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    case OP_Mod:
1035d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return fmod(leftVal, rightVal);
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0.0;
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
109d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)EqTestOp::EqTestOp(Opcode opcode, PassOwnPtrWillBeRawPtr<Expression> lhs, PassOwnPtrWillBeRawPtr<Expression> rhs)
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_opcode(opcode)
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    addSubExpression(lhs);
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    addSubExpression(rhs);
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool EqTestOp::compare(const Value& lhs, const Value& rhs) const
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (lhs.isNodeSet()) {
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const NodeSet& lhsSet = lhs.toNodeSet();
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (rhs.isNodeSet()) {
1215d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // If both objects to be compared are node-sets, then the comparison
1225d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // will be true if and only if there is a node in the first node-set
1235d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // and a node in the second node-set such that the result of
1245d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // performing the comparison on the string-values of the two nodes
1255d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // is true.
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            const NodeSet& rhsSet = rhs.toNodeSet();
1275d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            for (unsigned lindex = 0; lindex < lhsSet.size(); ++lindex) {
1285d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                for (unsigned rindex = 0; rindex < rhsSet.size(); ++rindex) {
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (compare(stringValue(lhsSet[lindex]), stringValue(rhsSet[rindex])))
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return true;
1315d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                }
1325d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            }
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (rhs.isNumber()) {
1365d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // If one object to be compared is a node-set and the other is a
1375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // number, then the comparison will be true if and only if there is
1385d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // a node in the node-set such that the result of performing the
1395d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // comparison on the number to be compared and on the result of
1405d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // converting the string-value of that node to a number using the
1415d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // number function is true.
1425d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            for (unsigned lindex = 0; lindex < lhsSet.size(); ++lindex) {
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (compare(Value(stringValue(lhsSet[lindex])).toNumber(), rhs))
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return true;
1455d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            }
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (rhs.isString()) {
1495d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // If one object to be compared is a node-set and the other is a
1505d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // string, then the comparison will be true if and only if there is
1515d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // a node in the node-set such that the result of performing the
1525d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // comparison on the string-value of the node and the other string
1535d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // is true.
1545d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            for (unsigned lindex = 0; lindex < lhsSet.size(); ++lindex) {
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (compare(stringValue(lhsSet[lindex]), rhs))
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return true;
1575d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            }
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (rhs.isBoolean()) {
1615d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // If one object to be compared is a node-set and the other is a
1625d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // boolean, then the comparison will be true if and only if the
1635d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // result of performing the comparison on the boolean and on the
1645d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // result of converting the node-set to a boolean using the boolean
1655d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // function is true.
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return compare(lhs.toBoolean(), rhs);
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(0);
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (rhs.isNodeSet()) {
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const NodeSet& rhsSet = rhs.toNodeSet();
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (lhs.isNumber()) {
1735d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            for (unsigned rindex = 0; rindex < rhsSet.size(); ++rindex) {
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (compare(lhs, Value(stringValue(rhsSet[rindex])).toNumber()))
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return true;
1765d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            }
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (lhs.isString()) {
1805d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            for (unsigned rindex = 0; rindex < rhsSet.size(); ++rindex) {
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (compare(lhs, stringValue(rhsSet[rindex])))
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return true;
1835d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            }
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (lhs.isBoolean())
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return compare(lhs, rhs.toBoolean());
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(0);
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
19002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Neither side is a NodeSet.
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (m_opcode) {
1935d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    case OpcodeEqual:
1945d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    case OpcodeNotEqual:
1955d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        bool equal;
1965d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (lhs.isBoolean() || rhs.isBoolean())
1975d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            equal = lhs.toBoolean() == rhs.toBoolean();
1985d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        else if (lhs.isNumber() || rhs.isNumber())
1995d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            equal = lhs.toNumber() == rhs.toNumber();
2005d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        else
2015d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            equal = lhs.toString() == rhs.toString();
2025d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
2035d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        if (m_opcode == OpcodeEqual)
2045d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            return equal;
2055d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return !equal;
2065d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    case OpcodeGreaterThan:
2075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return lhs.toNumber() > rhs.toNumber();
2085d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    case OpcodeGreaterOrEqual:
2095d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return lhs.toNumber() >= rhs.toNumber();
2105d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    case OpcodeLessThan:
2115d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return lhs.toNumber() < rhs.toNumber();
2125d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    case OpcodeLessOrEqual:
2135d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return lhs.toNumber() <= rhs.toNumber();
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(0);
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Value EqTestOp::evaluate() const
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Value lhs(subExpr(0)->evaluate());
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Value rhs(subExpr(1)->evaluate());
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return compare(lhs, rhs);
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
227d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)LogicalOp::LogicalOp(Opcode opcode, PassOwnPtrWillBeRawPtr<Expression> lhs, PassOwnPtrWillBeRawPtr<Expression> rhs)
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_opcode(opcode)
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    addSubExpression(lhs);
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    addSubExpression(rhs);
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool LogicalOp::shortCircuitOn() const
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2365d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return m_opcode != OP_And;
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Value LogicalOp::evaluate() const
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Value lhs(subExpr(0)->evaluate());
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This is not only an optimization, http://www.w3.org/TR/xpath
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // dictates that we must do short-circuit evaluation
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool lhsBool = lhs.toBoolean();
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (lhsBool == shortCircuitOn())
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return lhsBool;
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return subExpr(1)->evaluate().toBoolean();
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Value Union::evaluate() const
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Value lhsResult = subExpr(0)->evaluate();
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Value rhs = subExpr(1)->evaluate();
25602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NodeSet& resultSet = lhsResult.modifiableNodeSet();
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const NodeSet& rhsNodes = rhs.toNodeSet();
25902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    HashSet<Node*> nodes;
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < resultSet.size(); ++i)
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        nodes.add(resultSet[i]);
26302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (size_t i = 0; i < rhsNodes.size(); ++i) {
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Node* node = rhsNodes[i];
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (nodes.add(node).isNewEntry)
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            resultSet.append(node);
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2705d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // It is also possible to use merge sort to avoid making the result
2715d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // unsorted; but this would waste the time in cases when order is not
2725d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // important.
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resultSet.markSorted(false);
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return lhsResult;
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
277d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)Predicate::Predicate(PassOwnPtrWillBeRawPtr<Expression> expr)
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_expr(expr)
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
282d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(Predicate);
283d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
284d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void Predicate::trace(Visitor* visitor)
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
286d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    visitor->trace(m_expr);
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool Predicate::evaluate() const
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
291bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    ASSERT(m_expr);
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Value result(m_expr->evaluate());
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // foo[3] means foo[position()=3]
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (result.isNumber())
2975d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return EqTestOp(EqTestOp::OpcodeEqual, adoptPtrWillBeNoop(createFunction("position")), adoptPtrWillBeNoop(new Number(result.toNumber()))).evaluate().toBoolean();
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return result.toBoolean();
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
304