/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtXmlPatterns module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. #ifndef Patternist_SequenceFNs_H #define Patternist_SequenceFNs_H #include #include #include #include /** * @file * @short Contains classes implementing the functions found in * XQuery 1.0 and * XPath 2.0 Functions and Operators, 15.1 General Functions and Operators on Sequences. * * @todo document that some functions have both eval funcs implented. * * @ingroup Patternist_functions */ QT_BEGIN_NAMESPACE namespace QPatternist { /** * @short Implements the function fn:boolean(). * * @see EBVExtractor * @ingroup Patternist_functions * @author Frans Englich */ class BooleanFN : public FunctionCall { public: virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; /** * If @p reqType is CommonSequenceTypes::EBV, the type check of * the operand is returned. Hence, this removes redundant calls * to fn:boolean(). */ virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType); }; /** * @short Implements the function fn:index-of(). * * @ingroup Patternist_functions * @author Frans Englich */ class IndexOfFN : public FunctionCall, public ComparisonPlatform { public: inline IndexOfFN() : ComparisonPlatform() { } virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType); inline AtomicComparator::Operator operatorID() const { return AtomicComparator::OperatorEqual; } }; /** * @short Implements the functions fn:exists() and fn:empty(). * * Existence is a template value class. Appropriate implementations are achieved * by instantiating it with either IDExistsFN or IDEmptyFN. * * @ingroup Patternist_functions * @author Frans Englich */ template class Existence : public FunctionCall { public: virtual bool evaluateEBV(const DynamicContext::Ptr &context) const { if(Id == IDExistsFN) return !m_operands.first()->evaluateSequence(context)->isEmpty(); else return m_operands.first()->evaluateSequence(context)->isEmpty(); } /** * Attempts to rewrite to @c false or @c true by looking at the static * cardinality of its operand. */ virtual Expression::Ptr compress(const StaticContext::Ptr &context) { // RVCT doesn't like using template parameter in trinary operator when the trinary operator result is // passed directly into another constructor. Q_ASSERT(Id == IDExistsFN || Id == IDEmptyFN); const Expression::Ptr me(FunctionCall::compress(context)); if(me != this) return me; // RVCT doesn't like using template parameter in trinary operator when the trinary operator result is // passed directly into another constructor. Expression::ID tempId = Id; const Cardinality myCard((tempId == IDExistsFN) ? Cardinality::oneOrMore() : Cardinality::empty()); const Cardinality card(m_operands.first()->staticType()->cardinality()); if(myCard.isMatch(card)) { /* Since the dynamic type always is narrower than the static type or equal, and that the static type is in scope, it means we will always be true. */ return wrapLiteral(CommonValues::BooleanTrue, context, this); } else { /* Is it even possible to hit? */ if(myCard.canMatch(card)) { return me; } else { /* We can never hit. */ return wrapLiteral(CommonValues::BooleanFalse, context, this); } } } }; /** * @short Implements the function fn:distinct-values(). * * @ingroup Patternist_functions * @author Frans Englich */ class DistinctValuesFN : public FunctionCall, public ComparisonPlatform { public: inline DistinctValuesFN() : ComparisonPlatform() { } virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; /** * Performs necessary type checks, but also implements the optimization * of rewriting to its operand if the operand's cardinality is zero-or-one * or exactly-one. */ virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType); /** * @returns a type whose item type is the type of the first operand, and * a cardinality which is non-empty if the first operand's type is non-empty * and allows exactly-one. The latter is needed for operands which has the * cardinality 2+, since distinct-values possibly removes items from the * source sequence. */ virtual SequenceType::Ptr staticType() const; protected: inline AtomicComparator::Operator operatorID() const { return AtomicComparator::OperatorEqual; } }; /** * @short Implements the function fn:insert-before(). * * @todo docs, explain why evaluateSequence and evaluateSingleton is implemented * * @ingroup Patternist_functions * @author Frans Englich */ class InsertBeforeFN : public FunctionCall { public: virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; /** * Implements the static enferences rules. The function's static item type * is the union type of the first and third argument, and the cardinality is * the cardinalities of the two operands added together. For example, * insert-before((1, "str"), 1, xs:double(0)) has the static type xs:anyAtomicType+. * * @see XQuery 1.0 * and XPath 2.0 Formal Semantics, 7.2.15 The fn:insert-before function */ virtual SequenceType::Ptr staticType() const; }; /** * @short Implements the function fn:remove(). * * @ingroup Patternist_functions * @author Frans Englich */ class RemoveFN : public FunctionCall { public: virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; /** * Implements the static enferences rules, "Since one item may be removed * from the sequence, the resulting type is made optional:" * * statEnv |- (FN-URI,"remove")(Type, Type1) : prime(Type) * quantifier(Type)? * * However, because Patternist's type system is more fine grained than Formal Semantics, * the sequence isn't made optional. Instead its minimum length is reduced with one. * * @see XQuery 1.0 * and XPath 2.0 Formal Semantics, 7.2.11 The fn:remove function */ virtual SequenceType::Ptr staticType() const; }; /** * @short Implements the function fn:reverse(). * * @ingroup Patternist_functions * @author Frans Englich */ class ReverseFN : public FunctionCall { public: virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType); /** * Formally speaking, the type inference is: * @verbatim statEnv |- (FN-URI,"reverse")(Type) : prime(Type) * quantifier(Type) @endverbatim * * @see XQuery 1.0 * and XPath 2.0 Formal Semantics, 7.2.12 The fn:reverse function * @returns the static type of the function's first argument. */ virtual SequenceType::Ptr staticType() const; }; /** * @short Implements the function fn:subsequence(). * * @ingroup Patternist_functions * @author Frans Englich * @todo Type inference can be made stronger for this function */ class SubsequenceFN : public FunctionCall { public: SubsequenceFN(); virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType); /** * This function implements rewrites the SubsequenceFN instance into an * empty sequence if its third argument, the sequence length argument, is * evaluated and is effectively equal or less than zero. */ virtual Expression::Ptr compress(const StaticContext::Ptr &context); /** * Partially implements the static type inference rules. * * @see XQuery 1.0 * and XPath 2.0 Formal Semantics, 7.2.13 The fn:subsequence function */ virtual SequenceType::Ptr staticType() const; private: bool m_hasTypeChecked; }; } QT_END_NAMESPACE #endif