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