1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7**
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 The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
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 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40//
41// W A R N I N G
42// -------------
43//
44// This file is not part of the Qt API. It exists purely as an
45// implementation detail. This header file may change from version to
46// version without notice, or even be removed.
47//
48// We mean it.
49
50#ifndef Patternist_SequenceFNs_H
51#define Patternist_SequenceFNs_H
52
53#include <private/qatomiccomparator_p.h>
54#include <private/qcomparisonplatform_p.h>
55#include <private/qliteral_p.h>
56#include <private/qfunctioncall_p.h>
57
58/**
59 * @file
60 * @short Contains classes implementing the functions found in
61 * <a href="http://www.w3.org/TR/xpath-functions/#general-seq-funcs">XQuery 1.0 and
62 * XPath 2.0 Functions and Operators, 15.1 General Functions and Operators on Sequences</a>.
63 *
64 * @todo document that some functions have both eval funcs implented.
65 *
66 * @ingroup Patternist_functions
67 */
68
69QT_BEGIN_NAMESPACE
70
71namespace QPatternist
72{
73 /**
74 * @short Implements the function <tt>fn:boolean()</tt>.
75 *
76 * @see EBVExtractor
77 * @ingroup Patternist_functions
78 * @author Frans Englich <frans.englich@nokia.com>
79 */
80 class BooleanFN : public FunctionCall
81 {
82 public:
83 virtual bool evaluateEBV(const DynamicContext::Ptr &context) const;
84
85 /**
86 * If @p reqType is CommonSequenceTypes::EBV, the type check of
87 * the operand is returned. Hence, this removes redundant calls
88 * to <tt>fn:boolean()</tt>.
89 */
90 virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context,
91 const SequenceType::Ptr &reqType);
92 };
93
94 /**
95 * @short Implements the function <tt>fn:index-of()</tt>.
96 *
97 * @ingroup Patternist_functions
98 * @author Frans Englich <frans.englich@nokia.com>
99 */
100 class IndexOfFN : public FunctionCall,
101 public ComparisonPlatform<IndexOfFN, false>
102 {
103 public:
104 inline IndexOfFN() : ComparisonPlatform<IndexOfFN, false>()
105 {
106 }
107
108 virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const;
109 virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context,
110 const SequenceType::Ptr &reqType);
111
112 inline AtomicComparator::Operator operatorID() const
113 {
114 return AtomicComparator::OperatorEqual;
115 }
116 };
117
118 /**
119 * @short Implements the functions <tt>fn:exists()</tt> and <tt>fn:empty()</tt>.
120 *
121 * Existence is a template value class. Appropriate implementations are achieved
122 * by instantiating it with either IDExistsFN or IDEmptyFN.
123 *
124 * @ingroup Patternist_functions
125 * @author Frans Englich <frans.englich@nokia.com>
126 */
127 template<const Expression::ID Id>
128 class Existence : public FunctionCall
129 {
130 public:
131 virtual bool evaluateEBV(const DynamicContext::Ptr &context) const
132 {
133 if(Id == IDExistsFN)
134 return !m_operands.first()->evaluateSequence(context)->isEmpty();
135 else
136 return m_operands.first()->evaluateSequence(context)->isEmpty();
137 }
138
139 /**
140 * Attempts to rewrite to @c false or @c true by looking at the static
141 * cardinality of its operand.
142 */
143 virtual Expression::Ptr compress(const StaticContext::Ptr &context)
144 {
145 // RVCT doesn't like using template parameter in trinary operator when the trinary operator result is
146 // passed directly into another constructor.
147 Q_ASSERT(Id == IDExistsFN || Id == IDEmptyFN);
148
149 const Expression::Ptr me(FunctionCall::compress(context));
150
151 if(me != this)
152 return me;
153
154 // RVCT doesn't like using template parameter in trinary operator when the trinary operator result is
155 // passed directly into another constructor.
156 Expression::ID tempId = Id;
157 const Cardinality myCard((tempId == IDExistsFN) ? Cardinality::oneOrMore() : Cardinality::empty());
158
159 const Cardinality card(m_operands.first()->staticType()->cardinality());
160 if(myCard.isMatch(other: card))
161 { /* Since the dynamic type always is narrower than the static type or equal, and that the
162 static type is in scope, it means we will always be true. */
163 return wrapLiteral(CommonValues::BooleanTrue, context, this);
164 }
165 else
166 {
167 /* Is it even possible to hit? */
168 if(myCard.canMatch(other: card))
169 {
170 return me;
171 }
172 else
173 { /* We can never hit. */
174 return wrapLiteral(CommonValues::BooleanFalse, context, this);
175 }
176 }
177 }
178 };
179
180 /**
181 * @short Implements the function <tt>fn:distinct-values()</tt>.
182 *
183 * @ingroup Patternist_functions
184 * @author Frans Englich <frans.englich@nokia.com>
185 */
186 class DistinctValuesFN : public FunctionCall,
187 public ComparisonPlatform<IndexOfFN, false>
188 {
189 public:
190 inline DistinctValuesFN() : ComparisonPlatform<IndexOfFN, false>()
191 {
192 }
193
194 virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const;
195 /**
196 * Performs necessary type checks, but also implements the optimization
197 * of rewriting to its operand if the operand's cardinality is zero-or-one
198 * or exactly-one.
199 */
200 virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context,
201 const SequenceType::Ptr &reqType);
202 /**
203 * @returns a type whose item type is the type of the first operand, and
204 * a cardinality which is non-empty if the first operand's type is non-empty
205 * and allows exactly-one. The latter is needed for operands which has the
206 * cardinality 2+, since distinct-values possibly removes items from the
207 * source sequence.
208 */
209 virtual SequenceType::Ptr staticType() const;
210
211 protected:
212 inline AtomicComparator::Operator operatorID() const
213 {
214 return AtomicComparator::OperatorEqual;
215 }
216 };
217
218 /**
219 * @short Implements the function <tt>fn:insert-before()</tt>.
220 *
221 * @todo docs, explain why evaluateSequence and evaluateSingleton is implemented
222 *
223 * @ingroup Patternist_functions
224 * @author Frans Englich <frans.englich@nokia.com>
225 */
226 class InsertBeforeFN : public FunctionCall
227 {
228 public:
229 virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const;
230 virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const;
231
232 /**
233 * Implements the static enferences rules. The function's static item type
234 * is the union type of the first and third argument, and the cardinality is
235 * the cardinalities of the two operands added together. For example,
236 * insert-before((1, "str"), 1, xs:double(0)) has the static type xs:anyAtomicType+.
237 *
238 * @see <a href="http://www.w3.org/TR/xquery-semantics/#sec_fn_insert_before">XQuery 1.0
239 * and XPath 2.0 Formal Semantics, 7.2.15 The fn:insert-before function</a>
240 */
241 virtual SequenceType::Ptr staticType() const;
242 };
243
244 /**
245 * @short Implements the function <tt>fn:remove()</tt>.
246 *
247 * @ingroup Patternist_functions
248 * @author Frans Englich <frans.englich@nokia.com>
249 */
250 class RemoveFN : public FunctionCall
251 {
252 public:
253 virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const;
254 virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const;
255
256 /**
257 * Implements the static enferences rules, "Since one item may be removed
258 * from the sequence, the resulting type is made optional:"
259 *
260 * <tt>statEnv |- (FN-URI,"remove")(Type, Type1) : prime(Type) * quantifier(Type)?</tt>
261 *
262 * However, because Patternist's type system is more fine grained than Formal Semantics,
263 * the sequence isn't made optional. Instead its minimum length is reduced with one.
264 *
265 * @see <a href="http://www.w3.org/TR/xquery-semantics/#sec_fn_remove">XQuery 1.0
266 * and XPath 2.0 Formal Semantics, 7.2.11 The fn:remove function</a>
267 */
268 virtual SequenceType::Ptr staticType() const;
269 };
270
271 /**
272 * @short Implements the function <tt>fn:reverse()</tt>.
273 *
274 * @ingroup Patternist_functions
275 * @author Frans Englich <frans.englich@nokia.com>
276 */
277 class ReverseFN : public FunctionCall
278 {
279 public:
280
281 virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const;
282 virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context,
283 const SequenceType::Ptr &reqType);
284
285 /**
286 * Formally speaking, the type inference is:
287 *
288@verbatim
289statEnv |- (FN-URI,"reverse")(Type) : prime(Type) * quantifier(Type)
290@endverbatim
291 *
292 * @see <a href="http://www.w3.org/TR/xquery-semantics/#sec_fn_reverse">XQuery 1.0
293 * and XPath 2.0 Formal Semantics, 7.2.12 The fn:reverse function</a>
294 * @returns the static type of the function's first argument.
295 */
296 virtual SequenceType::Ptr staticType() const;
297 };
298
299 /**
300 * @short Implements the function <tt>fn:subsequence()</tt>.
301 *
302 * @ingroup Patternist_functions
303 * @author Frans Englich <frans.englich@nokia.com>
304 * @todo Type inference can be made stronger for this function
305 */
306 class SubsequenceFN : public FunctionCall
307 {
308 public:
309 SubsequenceFN();
310 virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const;
311 virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const;
312
313 virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context,
314 const SequenceType::Ptr &reqType);
315
316 /**
317 * This function implements rewrites the SubsequenceFN instance into an
318 * empty sequence if its third argument, the sequence length argument, is
319 * evaluated and is effectively equal or less than zero.
320 */
321 virtual Expression::Ptr compress(const StaticContext::Ptr &context);
322
323 /**
324 * Partially implements the static type inference rules.
325 *
326 * @see <a href="http://www.w3.org/TR/xquery-semantics/#sec_fn_subsequence">XQuery 1.0
327 * and XPath 2.0 Formal Semantics, 7.2.13 The fn:subsequence function</a>
328 */
329 virtual SequenceType::Ptr staticType() const;
330
331 private:
332 bool m_hasTypeChecked;
333 };
334}
335
336QT_END_NAMESPACE
337
338#endif
339

source code of qtxmlpatterns/src/xmlpatterns/functions/qsequencefns_p.h