src/xmlpatterns/expr/qgenericpredicate.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qabstractfloat_p.h"
       
    43 #include "qboolean_p.h"
       
    44 #include "qbuiltintypes_p.h"
       
    45 #include "qcommonsequencetypes_p.h"
       
    46 #include "qemptysequence_p.h"
       
    47 #include "qfirstitempredicate_p.h"
       
    48 #include "qgenericsequencetype_p.h"
       
    49 #include "qitemmappingiterator_p.h"
       
    50 #include "qliteral_p.h"
       
    51 #include "qpatternistlocale_p.h"
       
    52 #include "qtruthpredicate_p.h"
       
    53 
       
    54 #include "qgenericpredicate_p.h"
       
    55 
       
    56 QT_BEGIN_NAMESPACE
       
    57 
       
    58 using namespace QPatternist;
       
    59 
       
    60 GenericPredicate::GenericPredicate(const Expression::Ptr &sourceExpression,
       
    61                                    const Expression::Ptr &predicate) : PairContainer(sourceExpression,
       
    62                                                                                      predicate)
       
    63 {
       
    64 }
       
    65 
       
    66 Expression::Ptr GenericPredicate::create(const Expression::Ptr &sourceExpression,
       
    67                                          const Expression::Ptr &predicateExpression,
       
    68                                          const StaticContext::Ptr &context,
       
    69                                          const QSourceLocation &location)
       
    70 {
       
    71     Q_ASSERT(sourceExpression);
       
    72     Q_ASSERT(predicateExpression);
       
    73     Q_ASSERT(context);
       
    74     const ItemType::Ptr type(predicateExpression->staticType()->itemType());
       
    75 
       
    76     if(predicateExpression->is(IDIntegerValue) &&
       
    77        predicateExpression->as<Literal>()->item().as<Numeric>()->toInteger() == 1)
       
    78     { /* Handle [1] */
       
    79         return createFirstItem(sourceExpression);
       
    80     }
       
    81     else if(BuiltinTypes::numeric->xdtTypeMatches(type))
       
    82     { /* A numeric predicate, other than [1]. */
       
    83         /* TODO at somepoint we'll return a specialized expr here, NumericPredicate or so.
       
    84          * Dependency analysis is a bit tricky, since the contained expression can depend on
       
    85          * some loop component. */
       
    86         return Expression::Ptr(new GenericPredicate(sourceExpression, predicateExpression));
       
    87     }
       
    88     else if(*CommonSequenceTypes::Empty == *type)
       
    89     {
       
    90         return EmptySequence::create(predicateExpression.data(), context);
       
    91     }
       
    92     else if(*BuiltinTypes::item == *type ||
       
    93             *BuiltinTypes::xsAnyAtomicType == *type)
       
    94     {
       
    95         /* The type couldn't be narrowed at compile time, so we use
       
    96          * a generic predicate. This check is before the CommonSequenceTypes::EBV check,
       
    97          * because the latter matches these types as well. */
       
    98         return Expression::Ptr(new GenericPredicate(sourceExpression, predicateExpression));
       
    99     }
       
   100     else if(CommonSequenceTypes::EBV->itemType()->xdtTypeMatches(type))
       
   101     {
       
   102         return Expression::Ptr(new TruthPredicate(sourceExpression, predicateExpression));
       
   103     }
       
   104     else
       
   105     {
       
   106         context->error(QtXmlPatterns::tr("A value of type %1 cannot be a "
       
   107                                          "predicate. A predicate must have "
       
   108                                          "either a numeric type or an "
       
   109                                          "Effective Boolean Value type.")
       
   110                        .arg(formatType(context->namePool(),
       
   111                                        sourceExpression->staticType())),
       
   112                        ReportContext::FORG0006, location);
       
   113         return Expression::Ptr(); /* Silence compiler warning. */
       
   114     }
       
   115 }
       
   116 
       
   117 Expression::Ptr GenericPredicate::createFirstItem(const Expression::Ptr &sourceExpression)
       
   118 
       
   119 {
       
   120     return Expression::Ptr(new FirstItemPredicate(sourceExpression));
       
   121 }
       
   122 
       
   123 Item GenericPredicate::mapToItem(const Item &item,
       
   124                                  const DynamicContext::Ptr &context) const
       
   125 {
       
   126     const Item::Iterator::Ptr it(m_operand2->evaluateSequence(context));
       
   127     const Item pcateItem(it->next());
       
   128 
       
   129     if(!pcateItem)
       
   130         return Item(); /* The predicate evaluated to the empty sequence */
       
   131     else if(pcateItem.isNode())
       
   132         return item;
       
   133     /* Ok, now it must be an AtomicValue */
       
   134     else if(BuiltinTypes::numeric->xdtTypeMatches(pcateItem.type()))
       
   135     { /* It's a positional predicate. */
       
   136         if(it->next())
       
   137         {
       
   138             context->error(QtXmlPatterns::tr("A positional predicate must "
       
   139                                              "evaluate to a single numeric "
       
   140                                              "value."),
       
   141                               ReportContext::FORG0006, this);
       
   142             return Item();
       
   143         }
       
   144 
       
   145         if(Double::isEqual(static_cast<xsDouble>(context->contextPosition()),
       
   146                            pcateItem.as<Numeric>()->toDouble()))
       
   147         {
       
   148             return item;
       
   149         }
       
   150         else
       
   151             return Item();
       
   152     }
       
   153     else if(Boolean::evaluateEBV(pcateItem, it, context)) /* It's a truth predicate. */
       
   154         return item;
       
   155     else
       
   156         return Item();
       
   157 }
       
   158 
       
   159 Item::Iterator::Ptr GenericPredicate::evaluateSequence(const DynamicContext::Ptr &context) const
       
   160 {
       
   161     const Item::Iterator::Ptr focus(m_operand1->evaluateSequence(context));
       
   162     const DynamicContext::Ptr newContext(context->createFocus());
       
   163     newContext->setFocusIterator(focus);
       
   164 
       
   165     return makeItemMappingIterator<Item>(ConstPtr(this),
       
   166                                          focus,
       
   167                                          newContext);
       
   168 }
       
   169 
       
   170 Item GenericPredicate::evaluateSingleton(const DynamicContext::Ptr &context) const
       
   171 {
       
   172     const Item::Iterator::Ptr focus(m_operand1->evaluateSequence(context));
       
   173     const DynamicContext::Ptr newContext(context->createFocus());
       
   174     newContext->setFocusIterator(focus);
       
   175     return mapToItem(focus->next(), newContext);
       
   176 }
       
   177 
       
   178 SequenceType::List GenericPredicate::expectedOperandTypes() const
       
   179 {
       
   180     SequenceType::List result;
       
   181     result.append(CommonSequenceTypes::ZeroOrMoreItems);
       
   182     result.append(CommonSequenceTypes::ZeroOrMoreItems);
       
   183     return result;
       
   184 }
       
   185 
       
   186 SequenceType::Ptr GenericPredicate::staticType() const
       
   187 {
       
   188     const SequenceType::Ptr type(m_operand1->staticType());
       
   189     return makeGenericSequenceType(type->itemType(),
       
   190                                    type->cardinality() | Cardinality::zeroOrOne());
       
   191 }
       
   192 
       
   193 ExpressionVisitorResult::Ptr GenericPredicate::accept(const ExpressionVisitor::Ptr &visitor) const
       
   194 {
       
   195     return visitor->visit(this);
       
   196 }
       
   197 
       
   198 ItemType::Ptr GenericPredicate::newFocusType() const
       
   199 {
       
   200     return m_operand1->staticType()->itemType();
       
   201 }
       
   202 
       
   203 Expression::Properties GenericPredicate::properties() const
       
   204 {
       
   205     return CreatesFocusForLast;
       
   206 }
       
   207 
       
   208 QString GenericPredicate::description() const
       
   209 {
       
   210     return QLatin1String("predicate");
       
   211 }
       
   212 
       
   213 Expression::ID GenericPredicate::id() const
       
   214 {
       
   215     return IDGenericPredicate;
       
   216 }
       
   217 
       
   218 QT_END_NAMESPACE