source: trunk/src/xmlpatterns/expr/qgenericpredicate.cpp@ 846

Last change on this file since 846 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 8.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtXmlPatterns module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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
56QT_BEGIN_NAMESPACE
57
58using namespace QPatternist;
59
60GenericPredicate::GenericPredicate(const Expression::Ptr &sourceExpression,
61 const Expression::Ptr &predicate) : PairContainer(sourceExpression,
62 predicate)
63{
64}
65
66Expression::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
117Expression::Ptr GenericPredicate::createFirstItem(const Expression::Ptr &sourceExpression)
118
119{
120 return Expression::Ptr(new FirstItemPredicate(sourceExpression));
121}
122
123Item 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
159Item::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
170Item 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
178SequenceType::List GenericPredicate::expectedOperandTypes() const
179{
180 SequenceType::List result;
181 result.append(CommonSequenceTypes::ZeroOrMoreItems);
182 result.append(CommonSequenceTypes::ZeroOrMoreItems);
183 return result;
184}
185
186SequenceType::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
193ExpressionVisitorResult::Ptr GenericPredicate::accept(const ExpressionVisitor::Ptr &visitor) const
194{
195 return visitor->visit(this);
196}
197
198ItemType::Ptr GenericPredicate::newFocusType() const
199{
200 return m_operand1->staticType()->itemType();
201}
202
203Expression::Properties GenericPredicate::properties() const
204{
205 return CreatesFocusForLast;
206}
207
208QString GenericPredicate::description() const
209{
210 return QLatin1String("predicate");
211}
212
213Expression::ID GenericPredicate::id() const
214{
215 return IDGenericPredicate;
216}
217
218QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.