| /**************************************************************************** |
| ** |
| ** 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 <QSharedData> |
| |
| #include <private/qexpression_p.h> |
| |
| 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 <frans.englich@nokia.com> |
| * @ingroup Patternist_expressions |
| */ |
| class ExpressionCreator : public QSharedData |
| { |
| public: |
| typedef QExplicitlySharedDataPointer<ExpressionCreator> 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 <frans.englich@nokia.com> |
| * @ingroup Patternist_expressions |
| */ |
| class ExpressionIdentifier : public QSharedData |
| { |
| public: |
| typedef QExplicitlySharedDataPointer<ExpressionIdentifier> Ptr; |
| typedef QList<ExpressionIdentifier::Ptr> 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 <frans.englich@nokia.com> |
| * @ingroup Patternist_expressions |
| */ |
| class OptimizationPass : public QSharedData |
| { |
| public: |
| typedef QExplicitlySharedDataPointer<OptimizationPass> Ptr; |
| typedef QList<OptimizationPass::Ptr> 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<qint8> 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 |