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_OptimizerFramework_H
51#define Patternist_OptimizerFramework_H
52
53#include <QSharedData>
54
55#include <private/qexpression_p.h>
56
57QT_BEGIN_NAMESPACE
58
59namespace QPatternist
60{
61 /**
62 * @short A factory for creating Expression instances.
63 *
64 * ExpressionIdentifier is one of the building block of Patternist's
65 * optimizer framework. An ExpressionIdentifier sub-class has
66 * the responsibility of creating the Expression that should be
67 * the result of the optimization.
68 *
69 * This class and sub-classes are never used on their own,
70 * but in cooperation with OptimizationPass.
71 *
72 * @author Frans englich <frans.englich@nokia.com>
73 * @ingroup Patternist_expressions
74 */
75 class ExpressionCreator : public QSharedData
76 {
77 public:
78 typedef QExplicitlySharedDataPointer<ExpressionCreator> Ptr;
79
80 /**
81 * For some reason this constructor cannot be synthesized.
82 */
83 inline ExpressionCreator()
84 {
85 }
86
87 virtual ~ExpressionCreator();
88 /**
89 * Creates an expression that has @p operands as operands.
90 *
91 * The Expression that is returned is guaranteed, by the caller,
92 * to get a treatment identical to if the expression was created
93 * in an ordinary compilation(via the parser, and so forth). That is,
94 * Expression::typeCheck() and Expression::compress() stages will be
95 * carried out on the returned expression.
96 *
97 * @returns an Expression::Ptr that never is non @c null, valid pointer
98 */
99 virtual Expression::Ptr create(const Expression::List &operands,
100 const StaticContext::Ptr &context,
101 const SourceLocationReflection *const) const = 0;
102
103 private:
104 Q_DISABLE_COPY(ExpressionCreator)
105 };
106
107 /**
108 * @short Abstract base class for all classes that identify Expressions
109 * based on some criteria.
110 *
111 * ExpressionIdentifier is one of the building block of Patternist's
112 * optimizer framework. An ExpressionIdentifier sub-class has
113 * the responsibility of determining whether a particular Expression
114 * is the one an OptimizationPass should apply for.
115 *
116 * This class and sub-classes are never used on their own,
117 * but in cooperation with OptimizationPass.
118 *
119 * @author Frans englich <frans.englich@nokia.com>
120 * @ingroup Patternist_expressions
121 */
122 class ExpressionIdentifier : public QSharedData
123 {
124 public:
125 typedef QExplicitlySharedDataPointer<ExpressionIdentifier> Ptr;
126 typedef QList<ExpressionIdentifier::Ptr> List;
127
128 /**
129 * For some reason this constructor cannot be synthesized.
130 */
131 inline ExpressionIdentifier()
132 {
133 }
134
135 virtual ~ExpressionIdentifier();
136 /**
137 * @param expr the Expression to be tested. This is guranteed
138 * to always be a non @c null, valid pointer.
139 *
140 * @returns @c true if @p expr matches as according to this ExpressionIdentifier,
141 * otherwise @c false.
142 */
143 virtual bool matches(const Expression::Ptr &expr) const = 0;
144
145 private:
146 Q_DISABLE_COPY(ExpressionIdentifier)
147 };
148
149 /**
150 * @short Describes how a particular optimization pass should be carried out.
151 *
152 * OptimizationPass is essentially a declaration, which describes
153 * how an optimization pass in the form of an AST rewrite should be done,
154 * by describing what that should be rewritten into what how.
155 *
156 * Each OptimizationPass is applied to a "start" Expression. The Expression
157 * that qualifies as a start Expression for the OptimizationPass in question is
158 * determined by startIdentifier; if its ExpressionIdentifier::matches() function
159 * returns @c true, the optimizer continues to apply this OptimizationPass.
160 *
161 * After a start Expression has been found, it is verified if the operands matches
162 * as well by applying the ExpressionIdentifiers in operandIdentifiers to the
163 * start Expression's operands. Similarly, if the operands matches what
164 * operandIdentifiers requires, the optimizer continues to apply this OptimizationPass.
165 *
166 * At this stage, it has been concluded that the OptimizationPass validly applies, and
167 * what now remains is to carry out the actual rewrite. The Expression rewritten
168 * to is the one returned by ExpressionCreator::create(), when invoked via the resultCreator
169 * variable.
170 *
171 * How these components, startIdentifier, operandIdentifiers, sourceExpression,
172 * and resultCreator interacts with one another is described in more detail
173 * in the member documentation as well as the classes they are instances of.
174 *
175 * @author Frans englich <frans.englich@nokia.com>
176 * @ingroup Patternist_expressions
177 */
178 class OptimizationPass : public QSharedData
179 {
180 public:
181 typedef QExplicitlySharedDataPointer<OptimizationPass> Ptr;
182 typedef QList<OptimizationPass::Ptr> List;
183
184 enum OperandsMatchMethod
185 {
186 /**
187 * All operands must match in the same order the ExpressionMarkers do.
188 */
189 Sequential = 1,
190
191 /**
192 * Matches if all operands are matched, regardless of their order. This is
193 * useful when an OptimizationPass is matching an Expression that has two operands
194 * and that both of them can appear on the left or right hand as long as it is those
195 * two.
196 *
197 * This comparison method only works when two operands
198 * needs to be matched.
199 */
200 AnyOrder
201 };
202
203 /**
204 * An ExpressionMarker identifies an operand Expression relatively
205 * the start Expression by that each integer identifies a step
206 * in a descending AST walk. For example an ExpressionMarker with
207 * only one entry that is 0(zero), identifies the first operand of the
208 * start Expression. An ExpressionMarker containing 1, 2 in that order
209 * identifies the third operand of the second operand of the start Expression.
210 */
211 typedef QList<qint8> ExpressionMarker;
212
213 /**
214 * Creates an OptimizationPass and sets its public variables
215 * to the corresponding values passed in this constructor.
216 */
217 OptimizationPass(const ExpressionIdentifier::Ptr &startID,
218 const ExpressionIdentifier::List &operandIDs,
219 const ExpressionMarker &sourceExpr,
220 const ExpressionCreator::Ptr &resultCtor = ExpressionCreator::Ptr(),
221 const OperandsMatchMethod matchMethod = Sequential);
222
223 /**
224 * The ExpressionIdentifier that must the Expression this OptimizationPass concerns.
225 *
226 * If this variable is @c null, it means that the start Expression does
227 * not have to match any particular ExpressionIdentifier, but is fine as is.
228 *
229 * One might wonder what the purpose of this startIdentifier is, considering
230 * that what start Expression an OptimizationPass can at all apply to is
231 * naturally determined by what Expression::optimizationPasses() re-implementation that
232 * returns this OptimizationPass. The reason is that in some cases an OptimizationPass
233 * nevertheless doesn't apply. For example, optimizations applying to a ValueComparison
234 * might depend on what operator that is in use.
235 *
236 * May be @c null or point to an ExpressionIdentifier.
237 */
238 const ExpressionIdentifier::Ptr startIdentifier;
239
240 /**
241 * In order for an OptimizationPass to apply, the start Expression's
242 * operands must be matched with this list of ExpressionIdentifier instances.
243 * The first ExpressionIdentifier is applied to the first operand, the second
244 * ExpressionIdentifier to the second operand, and so forth until all operands
245 * have been iterated.
246 *
247 * Entries in this list may be @c null, and those signals that the corresponding
248 * operand is not constrained. For example, if the third ExpressionIdentifier in
249 * the list is @c null, it signals that the third operand may be anykind of expression.
250 *
251 * May be empty or contain an arbitrary amount of objects or @c null pointers.
252 */
253 const ExpressionIdentifier::List operandIdentifiers;
254
255 /**
256 * Identifies the expression that should be part of the new expression
257 * that this OptimizationPass rewrites to. If this list is empty, it
258 * means that the result is not derived from the existing tree, and
259 * that resultCreator will exclusively be used for creating the result
260 * Expression.
261 *
262 * How the ExpressionMarker identifies an Expression is document in
263 * its documentation.
264 *
265 * May be empty.
266 */
267 const ExpressionMarker sourceExpression;
268
269 /**
270 * This is the ExpressionCreator that will be used to create the
271 * Expression which is the result. ExpressionCreator::create()
272 * will be passed as operands the Expression that sourceExpression
273 * specify, if any.
274 *
275 * If this variable is @c null, the result Expression will be the one
276 * sourceExpression identifies.
277 */
278 const ExpressionCreator::Ptr resultCreator;
279
280 const OperandsMatchMethod operandsMatchMethod;
281 private:
282 Q_DISABLE_COPY(OptimizationPass)
283 };
284}
285
286QT_END_NAMESPACE
287
288#endif
289

source code of qtxmlpatterns/src/xmlpatterns/expr/qoptimizerframework_p.h