/**************************************************************************** ** ** 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_OptimizerFramework_H #define Patternist_OptimizerFramework_H #include #include QT_BEGIN_NAMESPACE namespace QPatternist { /** * @short A factory for creating Expression instances. * * ExpressionIdentifier is one of the building block of Patternist's * optimizer framework. An ExpressionIdentifier sub-class has * the responsibility of creating the Expression that should be * the result of the optimization. * * This class and sub-classes are never used on their own, * but in cooperation with OptimizationPass. * * @author Frans englich * @ingroup Patternist_expressions */ class ExpressionCreator : public QSharedData { public: typedef QExplicitlySharedDataPointer Ptr; /** * For some reason this constructor cannot be synthesized. */ inline ExpressionCreator() { } virtual ~ExpressionCreator(); /** * Creates an expression that has @p operands as operands. * * The Expression that is returned is guaranteed, by the caller, * to get a treatment identical to if the expression was created * in an ordinary compilation(via the parser, and so forth). That is, * Expression::typeCheck() and Expression::compress() stages will be * carried out on the returned expression. * * @returns an Expression::Ptr that never is non @c null, valid pointer */ virtual Expression::Ptr create(const Expression::List &operands, const StaticContext::Ptr &context, const SourceLocationReflection *const) const = 0; private: Q_DISABLE_COPY(ExpressionCreator) }; /** * @short Abstract base class for all classes that identify Expressions * based on some criteria. * * ExpressionIdentifier is one of the building block of Patternist's * optimizer framework. An ExpressionIdentifier sub-class has * the responsibility of determining whether a particular Expression * is the one an OptimizationPass should apply for. * * This class and sub-classes are never used on their own, * but in cooperation with OptimizationPass. * * @author Frans englich * @ingroup Patternist_expressions */ class ExpressionIdentifier : public QSharedData { public: typedef QExplicitlySharedDataPointer Ptr; typedef QList List; /** * For some reason this constructor cannot be synthesized. */ inline ExpressionIdentifier() { } virtual ~ExpressionIdentifier(); /** * @param expr the Expression to be tested. This is guranteed * to always be a non @c null, valid pointer. * * @returns @c true if @p expr matches as according to this ExpressionIdentifier, * otherwise @c false. */ virtual bool matches(const Expression::Ptr &expr) const = 0; private: Q_DISABLE_COPY(ExpressionIdentifier) }; /** * @short Describes how a particular optimization pass should be carried out. * * OptimizationPass is essentially a declaration, which describes * how an optimization pass in the form of an AST rewrite should be done, * by describing what that should be rewritten into what how. * * Each OptimizationPass is applied to a "start" Expression. The Expression * that qualifies as a start Expression for the OptimizationPass in question is * determined by startIdentifier; if its ExpressionIdentifier::matches() function * returns @c true, the optimizer continues to apply this OptimizationPass. * * After a start Expression has been found, it is verified if the operands matches * as well by applying the ExpressionIdentifiers in operandIdentifiers to the * start Expression's operands. Similarly, if the operands matches what * operandIdentifiers requires, the optimizer continues to apply this OptimizationPass. * * At this stage, it has been concluded that the OptimizationPass validly applies, and * what now remains is to carry out the actual rewrite. The Expression rewritten * to is the one returned by ExpressionCreator::create(), when invoked via the resultCreator * variable. * * How these components, startIdentifier, operandIdentifiers, sourceExpression, * and resultCreator interacts with one another is described in more detail * in the member documentation as well as the classes they are instances of. * * @author Frans englich * @ingroup Patternist_expressions */ class OptimizationPass : public QSharedData { public: typedef QExplicitlySharedDataPointer Ptr; typedef QList List; enum OperandsMatchMethod { /** * All operands must match in the same order the ExpressionMarkers do. */ Sequential = 1, /** * Matches if all operands are matched, regardless of their order. This is * useful when an OptimizationPass is matching an Expression that has two operands * and that both of them can appear on the left or right hand as long as it is those * two. * * This comparison method only works when two operands * needs to be matched. */ AnyOrder }; /** * An ExpressionMarker identifies an operand Expression relatively * the start Expression by that each integer identifies a step * in a descending AST walk. For example an ExpressionMarker with * only one entry that is 0(zero), identifies the first operand of the * start Expression. An ExpressionMarker containing 1, 2 in that order * identifies the third operand of the second operand of the start Expression. */ typedef QList ExpressionMarker; /** * Creates an OptimizationPass and sets its public variables * to the corresponding values passed in this constructor. */ OptimizationPass(const ExpressionIdentifier::Ptr &startID, const ExpressionIdentifier::List &operandIDs, const ExpressionMarker &sourceExpr, const ExpressionCreator::Ptr &resultCtor = ExpressionCreator::Ptr(), const OperandsMatchMethod matchMethod = Sequential); /** * The ExpressionIdentifier that must the Expression this OptimizationPass concerns. * * If this variable is @c null, it means that the start Expression does * not have to match any particular ExpressionIdentifier, but is fine as is. * * One might wonder what the purpose of this startIdentifier is, considering * that what start Expression an OptimizationPass can at all apply to is * naturally determined by what Expression::optimizationPasses() re-implementation that * returns this OptimizationPass. The reason is that in some cases an OptimizationPass * nevertheless doesn't apply. For example, optimizations applying to a ValueComparison * might depend on what operator that is in use. * * May be @c null or point to an ExpressionIdentifier. */ const ExpressionIdentifier::Ptr startIdentifier; /** * In order for an OptimizationPass to apply, the start Expression's * operands must be matched with this list of ExpressionIdentifier instances. * The first ExpressionIdentifier is applied to the first operand, the second * ExpressionIdentifier to the second operand, and so forth until all operands * have been iterated. * * Entries in this list may be @c null, and those signals that the corresponding * operand is not constrained. For example, if the third ExpressionIdentifier in * the list is @c null, it signals that the third operand may be anykind of expression. * * May be empty or contain an arbitrary amount of objects or @c null pointers. */ const ExpressionIdentifier::List operandIdentifiers; /** * Identifies the expression that should be part of the new expression * that this OptimizationPass rewrites to. If this list is empty, it * means that the result is not derived from the existing tree, and * that resultCreator will exclusively be used for creating the result * Expression. * * How the ExpressionMarker identifies an Expression is document in * its documentation. * * May be empty. */ const ExpressionMarker sourceExpression; /** * This is the ExpressionCreator that will be used to create the * Expression which is the result. ExpressionCreator::create() * will be passed as operands the Expression that sourceExpression * specify, if any. * * If this variable is @c null, the result Expression will be the one * sourceExpression identifies. */ const ExpressionCreator::Ptr resultCreator; const OperandsMatchMethod operandsMatchMethod; private: Q_DISABLE_COPY(OptimizationPass) }; } QT_END_NAMESPACE #endif