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 69 QT_BEGIN_NAMESPACE 70 71 namespace 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: IndexOfFN()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 operatorID()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: evaluateEBV(const DynamicContext::Ptr & context)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 */ compress(const StaticContext::Ptr & context)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(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(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: DistinctValuesFN()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: operatorID()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 289 statEnv |- (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 336 QT_END_NAMESPACE 337 338 #endif 339