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