1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include "qcardinalityverifier_p.h"
43 #include "qcommonsequencetypes_p.h"
44 #include "qemptysequence_p.h"
45 #include "qsequencemappingiterator_p.h"
47 #include "qexpressionsequence_p.h"
51 using namespace QPatternist;
53 ExpressionSequence::ExpressionSequence(const Expression::List &ops) : UnlimitedContainer(ops)
55 Q_ASSERT_X(1 < ops.count(), Q_FUNC_INFO,
56 "It makes no sense to have an ExpressionSequence containing less than two expressions.");
59 Item::Iterator::Ptr ExpressionSequence::mapToSequence(const Expression::Ptr &expr,
60 const DynamicContext::Ptr &context) const
62 return expr->evaluateSequence(context);
65 Item::Iterator::Ptr ExpressionSequence::evaluateSequence(const DynamicContext::Ptr &context) const
67 return makeSequenceMappingIterator<Item>(ConstPtr(this),
68 makeListIterator(m_operands),
72 void ExpressionSequence::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const
74 Expression::List::const_iterator it(m_operands.constBegin());
75 const Expression::List::const_iterator end(m_operands.constEnd());
76 Expression::List result;
78 for(; it != end; ++it)
79 (*it)->evaluateToSequenceReceiver(context);
82 Expression::Ptr ExpressionSequence::compress(const StaticContext::Ptr &context)
84 const Expression::Ptr me(UnlimitedContainer::compress(context));
89 Expression::List::const_iterator it(m_operands.constBegin());
90 const Expression::List::const_iterator end(m_operands.constEnd());
91 Expression::List result;
93 for(; it != end; ++it)
95 const ID Id = (*it)->id();
97 /* Remove empty sequences. This is rather important because we have some steps in the parser that
98 * intentionally, unconditionally and for temporary reasons create expressions like (expr, ()). Of course,
99 * empty sequences also occur as part of optimizations.
101 * User function call sites that are of type empty-sequence() must be avoided since
102 * they may contain calls to fn:error(), which we would rewrite away otherwise. */
103 if(Id != IDUserFunctionCallsite && (*it)->staticType()->cardinality().isEmpty())
105 /* Rewrite "(1, (), 2)" into "(1, 2)" by not
106 * adding (*it) to result. */
109 else if(Id == IDExpressionSequence)
111 /* Rewrite "(1, (2, 3), 4)" into "(1, 2, 3, 4)" */
112 Expression::List::const_iterator seqIt((*it)->operands().constBegin());
113 const Expression::List::const_iterator seqEnd((*it)->operands().constEnd());
115 for(; seqIt != seqEnd; ++seqIt)
116 result.append(*seqIt);
123 return EmptySequence::create(this, context);
124 else if(result.count() == 1)
125 return result.first();
133 Expression::Ptr ExpressionSequence::typeCheck(const StaticContext::Ptr &context,
134 const SequenceType::Ptr &reqType)
137 Expression::List::iterator it(m_operands.begin());
138 const Expression::List::iterator end(m_operands.end());
140 /* We treat the cardinality differently here by allowing the empty sequence
141 * for each individual Expression, since the Cardinality can be conformed to by
142 * the ExpressionSequence as a whole(which we check for at the end). */
143 const SequenceType::Ptr testOnlyIT(makeGenericSequenceType(reqType->itemType(),
144 Cardinality::empty() |
145 reqType->cardinality()));
147 for(; it != end; ++it)
148 *it = (*it)->typeCheck(context, testOnlyIT);
150 /* The above loop is only guaranteed to find item type errors, but the cardinality
151 * can still be wrong since the operands were treated individually. */
152 return CardinalityVerifier::verifyCardinality(Expression::Ptr(this), reqType->cardinality(), context);
155 Expression::Properties ExpressionSequence::properties() const
157 const Expression::List::const_iterator end(m_operands.constEnd());
158 Expression::List::const_iterator it;
159 bool allEvaled = true;
160 Expression::Properties props(DisableElimination); /* Why do we have this flag? */
162 for(it = m_operands.constBegin(); it != end; ++it)
164 const Expression::Properties newp((*it)->properties());
167 if((newp & IsEvaluated) != IsEvaluated)
175 props &= ~IsEvaluated; /* Remove IsEvaluated. */
177 /* One of our children might need the focus, but we don't, so
179 return props & ~RequiresFocus;
182 SequenceType::Ptr ExpressionSequence::staticType() const
184 return operandsUnionType<ProductOfCardinality>();
187 SequenceType::List ExpressionSequence::expectedOperandTypes() const
189 SequenceType::List result;
190 /* ExpressionSequence is a bit strange type wise since it has an
191 * infinite amount of operands. */
192 result.append(CommonSequenceTypes::ZeroOrMoreItems);
196 ExpressionVisitorResult::Ptr ExpressionSequence::accept(const ExpressionVisitor::Ptr &visitor) const
198 return visitor->visit(this);
201 Expression::ID ExpressionSequence::id() const
203 return IDExpressionSequence;