1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
|
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtXmlPatterns module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
** $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_Expression_H
#define Patternist_Expression_H
#include <QFlags>
#include <QSharedData>
#include "qcppcastinghelper_p.h"
#include "qdebug_p.h"
#include "qdynamiccontext_p.h"
#include "qexpressiondispatch_p.h"
#include "qitem_p.h"
#include "qsequencetype_p.h"
#include "qsourcelocationreflection_p.h"
#include "qstaticcontext_p.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
template<typename T> class QList;
template<typename T> class QVector;
namespace QPatternist
{
template<typename T, typename ListType> class ListIterator;
class OptimizationPass;
/**
* @short Base class for all AST nodes in an XPath/XQuery/XSL-T expression.
*
* @section ExpressionCreation Expression Compilation
*
* @subsection ExpressionCreationParser The process of creating an Expression
*
* The initial step of creating an internal representation(in some circles
* called an IR tree) of the XPath string follows classic compiler design: a scanner
* is invoked, resulting in tokens, which sub-sequently are consumed by a parser
* which groups the tokens into rules, resulting in the creation of
* Abstract Syntax Tree(AST) nodes that are arranged in a hierarchical structure
* similar to the EBNF.
*
* More specifically, ExpressionFactory::createExpression() is called with a
* pointer to a static context, and the string for the expression. This is subsequently
* tokenized by a Flex scanner. Mistakes detected at this stage is syntax
* errors, as well as a few semantical errors. Syntax errors can be divided
* in two types:
*
* - The scanner detects it. An example is the expression "23Eb3" which
* is not a valid number literal, or "1prefix:my-element" which is not a
* valid QName.
* - The parser detects it. This means a syntax error at a
* higher level, that a group of tokens couldn't be reduced to a
* rule(expression). An example is the expression "if(a = b) 'match' else
* 'no match'"; the tokenizer would handle it fine, but the parser would
* fail because the tokens could not be reduced to a rule due to the token
* for the "then" word was missing.
*
* Apart from the syntax errors, the actions in the parser also detects
* errors when creating the corresponding expressions. This is for example
* that no namespace binding for a prefix could be found, or that a function
* call was used which no function implementation could be found for.
*
* When the parser has finished, the result is an AST. That is, a
* hierarchical structure consisting of Expression sub-classes. The
* individual expressions haven't at this point done anything beyond
* receiving their child-expressions(if any), and hence reminds of a
* "construction scaffold". In other words, a tree for the expression
* <tt>'string' + 1 and xs:date('2001-03-13')</tt> could have been created, even if
* that expression contains errors(one can't add a xs:integer to a xs:string,
* and the Effective %Boolean Value cannot be extracted for date types).
*
* @subsection ExpressionCreationTypeChecking Type Checking
*
* After the AST creation, ExpressionFactory::createExpression continues with
* calling the AST node(which is an Expression instance)'s typeCheck()
* function. This step ensures that the static types of the operands matches
* the operators, and in the cases where it doesn't, modifies the AST such
* that the necessary conversions are done -- if possible, otherwise the
* result is a type error.
*
*
* This step corresponds roughly to what <a
* href="http://www.w3.org/TR/xpath20/#id-static-analysis">2.2.3.1 Static Analysis Phase</a>
* labels operation tree normalization; step SQ5.
*
* @subsection ExpressionCreationCompression Compressing -- Optimization and Fixup
*
* The last step is calling compress(). This function is not called
* 'optimize', 'simplify' or the like, because although it performs all
* optimization, it also involves mandatory stages.
*
* One such is const folding, which while being an efficient optimization,
* also is a necessity for many XSL-T constructs. Another important step is
* that functions which had an evaluation dependency on the static context(as
* opposed to the dynamic) performs their "fixup".
*
* In other words, this stage potentially performs AST re-writes. For example,
* the expression <tt>3 + 3, concat('foo', '-', 'bar'), true() and false()</tt> would
* result in an AST corresponding to <tt>6, 'foo-bar', false()</tt>. This process
* is done backwards; each expression asks its operands to compress before it
* performs its own compression(and so forth, until the root expression's call
* returns to the caller).
*
* @see <a href="http://www.w3.org/TR/xpath20/#id-errors-and-opt">XML Path Language
* (XPath) 2.0, 2.3.4 Errors and Optimization</a>
* @see <a href="http://www.w3.org/TR/xpath20/#id-expression-processing">XML Path
* Language (XPath) 2.0, 2.2.3 Expression Processing</a>
* @see <a href="http://www.w3.org/TR/xquery-xpath-parsing/">Building a Tokenizer
* for XPath or XQuery</a>
* @see ExpressionFactory
* @author Frans Englich <frans.englich@nokia.com>
* @ingroup Patternist_expressions
*/
class Q_AUTOTEST_EXPORT Expression : public QSharedData
, public CppCastingHelper<Expression>
, public SourceLocationReflection
{
public:
/**
* @short A smart pointer wrapping mutable Expression instances.
*/
typedef QExplicitlySharedDataPointer<Expression> Ptr;
/**
* @short A smart pointer wrapping @c const Expression instances.
*/
typedef QExplicitlySharedDataPointer<const Expression> ConstPtr;
/**
* A list of Expression instances, each wrapped in a smart pointer.
*/
typedef QList<Expression::Ptr> List;
/**
* A vector of Expression instances, each wrapped in a smart pointer.
*/
typedef QVector<Expression::Ptr> Vector;
typedef QT_PREPEND_NAMESPACE(QAbstractXmlForwardIterator<Expression::Ptr>)
QAbstractXmlForwardIterator;
/**
* Enum flags describing the characteristics of the expression.
*
* @see Expression::properties()
*/
enum Property
{
/**
* This flag applies for functions, and results in the expression <tt>.</tt>
* being appended to its operands if its operand count is lower than the
* maximum amount of arguments.
*
* In effect, it result in a modification of the function's arguments to have
* appended the context item.
*
* One function which has this property is <tt>fn:number()</tt>.
*
* @see ContextItem
* @see <a href="http://www.w3.org/TR/xpath-functions/#func-signatures">XQuery 1.0 and
* XPath 2.0 Functions and Operators, 1.3 Function Signatures and Descriptions</a>
*/
UseContextItem = 1,
/**
* Disables compression(evaluation at compile time), such that the
* Expression isn't const-folded, but ensured to be run at runtime. The
* operands are still attempted to be compressed, unless
* they override compression as well.
*
* @see compress()
*/
DisableElimination = 1 << 1,
/**
* Signals that the expression is already evaluated and can be considered
* a constant value.
* For example, atomic values return this flag in their
* implementations of the properties() functions.
*
* @see isEvaluated()
*/
IsEvaluated = 1 << 2,
/**
* Signals that the expression cannot be optimized away by judging
* its static type.
*
* This is currently used for properly handling the @c none type, in
* the <tt>fn:error()</tt> function. In type operations, the none type doesn't show
* up and that can make expressions, such as InstanceOf, believe
* it is safe to const fold, while it in fact is not.
*/
DisableTypingDeduction = 1 << 3,
/**
* This property affects the static type -- staticType() -- of an expression. It
* is implemented in FunctionCall::staticType() and therefore only work for FunctionCall
* sub-classes and when that function is not re-implemented in an inhibiting way.
*
* When set, the cardinality of the static type is zero if the Expression's first
* operand allows an empty sequence, otherwise it is the cardinality of the Expression's
* static type modulo Cardinality::empty(). This is used for specifying proper static
* type inference for functions that have "If $arg is the empty sequence,
* the empty sequence is returned." However, before setting this property one
* must be aware that no other conditions can lead to the empty sequence, since
* otherwise the static type would be wrong.
*/
EmptynessFollowsChild = 1 << 4,
/**
* This is similar to EmptynessFollowsChild, and also implemented in FunctionCall.
* When set, it makes FunctionCall::typeCheck() rewrite itself into an empty sequence
* if the first operand is the empty sequence.
*
* This property is often used together with EmptynessFollowsChild.
*/
RewriteToEmptyOnEmpty = 1 << 5,
/**
* When set, it signals that the focus cannot be undefined. For example,
* the <tt>fn:position()</tt> function extracts information from the focus. Setting
* this flag ensures type checking is carried out appropriately.
*
* However, setting RequiresFocus does not imply this Expression requires the context
* item to be defined. It only means the focus, of somekind, needs to be defined.
*
* @see RequiresContextItem
*/
RequiresFocus = 1 << 6,
/**
* An Expression with this Property set, signals that it only affects
* the order of its return value.
*/
AffectsOrderOnly = 1 << 7,
/**
* When set, signals that the context item, must be defined for this Expression. When
* setting this property, expectedContextItemType() must be re-implemented.
*
* Setting this property also sets RequiresFocus.
*
* @see DynamicContext::contextItem()
*/
RequiresContextItem = (1 << 8) | RequiresFocus,
/**
* When set, signals that this expression creates a focus for its last operand.
* When set, newFocusType() must be overridden to return the static type
* of the context item.
*
* @see announceFocusType()
* @see newFocusType()
*/
CreatesFocusForLast = 1 << 9,
/**
* Signals that the last operand is a collation argument. This ensures
* that the necessary code is generated for checking that the collation
* is supported.
*
* This only applies to sub-classes of FunctionCall.
*/
LastOperandIsCollation = 1 << 10,
/**
* When set, the Expression depends on local variables such as
* those found in @c for expressions. However, this does not
* include let bindings.
*/
DependsOnLocalVariable = (1 << 11) | DisableElimination,
/**
* When set, it signals that the Expression does not need
* an evaluation cache, despite what other flags might imply.
*/
EvaluationCacheRedundant = (1 << 12),
/**
* Signals that the Expression constructs nodes, either directly
* or computationally. For example, AttributeConstructor has this property
* set.
*
* Since node constructors constructs nodes which have node
* identities, node constructors are considered creative on
* evaluation.
*/
IsNodeConstructor = 1 << 13,
/**
* Whether this expression requires the current item, as returned
* from @c fn:current().
*
* CurrentFN uses this flag.
*/
RequiresCurrentItem = 1 << 14
};
/**
* A QFlags template for type-safe handling of ExpressionProperty values. If
* Expression::Property flags needs to be stored in a class, declared the variable
* to be of type Expression::Properties.
*
* @see QFlags
*/
typedef QFlags<Property> Properties;
/**
* Enumerators that identifies Expression sub-classes.
*
* @see id()
*/
enum ID
{
/**
* Identifies Boolean.
*/
IDBooleanValue = 1,
/**
* Identifies CountFN.
*/
IDCountFN,
/**
* Identifies EmptyFN.
*/
IDEmptyFN,
/**
* Identifies ExistsFN.
*/
IDExistsFN,
/**
* Identifies ExpressionSequence and LiteralSequence.
*/
IDExpressionSequence,
/**
* Identifies GeneralComparison.
*/
IDGeneralComparison,
/**
* Identifies IfThenClause.
*/
IDIfThenClause,
/**
* Identifies nothing in particular. The default implementation
* of id() returns this, which is suitable for Expression instances
* which never needs to be identified in this aspect.
*/
IDIgnorableExpression,
/**
* Identifies Integer.
*/
IDIntegerValue,
/**
* Identifies PositionFN.
*/
IDPositionFN,
/**
* Identifies AtomicString, AnyURI, and UntypedAtomic.
*/
IDStringValue,
/**
* Identifies ValueComparison.
*/
IDValueComparison,
/**
* Identifies VariableReference.
*/
IDRangeVariableReference,
/**
* Identifies ContextItem.
*/
IDContextItem,
/**
* Identifies UserFunctionCallsite.
*/
IDUserFunctionCallsite,
/**
* Identifies ExpressionVariableReference.
*/
IDExpressionVariableReference,
/**
* Identifies ExpressionVariableReference.
*/
IDAttributeConstructor,
/**
* Identifies UpperCaseFN.
*/
IDUpperCaseFN,
/**
* Identifies LowerCaseFN.
*/
IDLowerCaseFN,
/**
* Identifies FirstItemPredicate.
*/
IDFirstItemPredicate,
IDEmptySequence,
IDReturnOrderBy,
IDLetClause,
IDForClause,
IDPath,
IDNamespaceConstructor,
IDArgumentReference,
IDGenericPredicate,
IDAxisStep,
/**
* A literal which is either @c xs:float or
* @c xs:double.
*/
IDFloat,
IDCombineNodes,
IDUnresolvedVariableReference,
IDCardinalityVerifier
};
inline Expression()
{
}
virtual ~Expression();
/**
* Evaluate this Expression by iterating over it. This is a central function
* for evaluating expressions.
*
* Expressions must always always return a valid QAbstractXmlForwardIterator and may
* never return 0. If an empty result is of interest to be returned, the
* EmptyIterator should be returned.
*
* The default implementation returns a SingletonIterator over the
* item returned from evaluateSingleton().
*
* @note This function may raise an exception when calling, not only
* when QAbstractXmlForwardIterator::next() is called on the return value. This is because
* in some cases evaluateSingleton() is called directly.
*/
virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const;
/**
* @todo Docs
*/
virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const;
/**
* Determines the Effective %Boolean Value of the expression.
*
* The Effective %Boolean Value of a value is not necessarily the same
* as converting the value to a new value of type xs:boolean.
*
* Note that this function cannot return the empty sequence,
* evaluateSingleton() must be overridden in order to be able to do
* that.
*
* The default implementation results in a type error. Hence, this function
* must be overridden if such behavior is not of interest.
*
* @see <a href="http://www.w3.org/TR/xpath20/#id-ebv">XML Path Language (XPath) 2.0,
* 2.4.3 Effective Boolean Value</a>
*/
virtual bool evaluateEBV(const DynamicContext::Ptr &context) const;
/**
* Evaluates this Expression by sending its output to DynamicContext::outputReceiver().
*/
virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const;
/**
* @returns the expression's child expressions. For example, a function's
* arguments is returned here.
*
* If this Expression has no operands, an empty list should be returned.
*/
virtual Expression::List operands() const = 0;
virtual void setOperands(const Expression::List &operands) = 0;
/**
* @returns the static type of this Expression. For example, an 'and' expression
* have as static type xs:boolean
*/
virtual SequenceType::Ptr staticType() const = 0;
/**
* Returns a list of Sequence Types, describing the type of each of the
* expression's operands. Hence, this function has a relationship to
* the operands() function:
*
* - The lengths of the lists returned by expectedOperandTypes()
* and operands() should always be equal in length, since one
* cannot describe the type of a non-existent operand(and all
* operands must have type information).
* - A significant difference between the two functions is that while
* the type of objects in the list returned by operands() may vary
* between compilations/static context, simply because the particular
* Expression is part of different XPath expressions, the
* types in the list returned by expectedOperandTypes is always the same
* since the function/operator signature never changes.
*
* This function should not be confused with staticType(),
* which returns the static type of the expression itself, not its operands. The
* function call is an expression where this is clear: the type of the return
* value is not the same as the arguments' types. The static type of the
* operands supplied to the expression can be determined via the staticType()
* function of the instances returned by operands().
*
* If the expression has no operands, an empty list should be returned.
*/
virtual SequenceType::List expectedOperandTypes() const = 0;
/**
* This implementation guarantees to never rewrite away this Expression, but
* at most rewrite it as a child of another expression(that presumably have a
* type checking role). It is therefore always safe to override this
* function and call this implementation and not worry about that this Expression
* becomes deleted.
*
* Many Expressions override typeCheck() and performs optimizations, as opposed
* to doing it in the compress() stage. This is due to that the design
* of those Expressions often are tied to that certain simplifications
* are done at the typeCheck() stage of the compilation process or that
* it in some other way is related to what the typeCheck() do. Also, the earlier
* the AST can be simplified, the better the chances are for subsequent
* optimizations.
*
* It is important that the super class's typeCheck() is called before doing
* any custom type checking, since the call can change the children(notably,
* the childrens' static types). For example, if the Expression, MyExpression
* in the example, does not match the required type, typeCheck returns the Expression
* wrapped in for example ItemVerifier, CardinalityVerifier, or both.
*
* typeCheck() may be called many times. typeCheck() must either raise an error
* if this Expression is an invalid expression. Thus, it is guaranteed that an Expression
* is valid after typeCheck() is called.
*
* @param context supplies information, such as namespace bindings and
* available function signatures, that can be needed at compilation time. @p context is
* guaranteed by the caller to never null.
* @param reqType the static type that this Expression must match when evaluated. @p reqType is
* guaranteed by the caller to never null.
* @returns an Expression that can be this Expression, or another expression,
* which somehow is necessary for making this Expression conforming to
* @p reqType
*/
virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context,
const SequenceType::Ptr &reqType);
/**
* compress() is the last stage performs in compiling an expression, done after
* the initial AST build and calling typeCheck(). compress() performs crucial
* simplifications, either by having drastic performance implications or that
* some expressions depend on it for proper behavior.
*
* The default implementation performs a sparse conditional constant
* propagation. In short, a recursive process is performed in the AST
* which examines if the Expression's operands are constant values, and if so,
* performs a const fold(AST rewrite) into the result of evaluating the expression
* in question. This default behavior can be disabled by letting properties() return
* DisableElimination.
*
* This compress() stage can be relative effective due to the design of XPath, in
* part because intrinsic functions are heavily used. Many Expressions override compress()
* and do optimizations specific to what they do. Also, many Expressions performs
* optimizations in their typeCheck().
*
* @param context the static context. Supplies compile time information, and is
* the channel for communicating error messages.
* @see <a href="http://en.wikipedia.org/wiki/Sparse_conditional_constant_propagation">Wikipedia,
* the free encyclopedia, Sparse conditional constant propagation</a>
* @see <a href="http://en.wikipedia.org/wiki/Intrinsic_function">Wikipedia,
* the free encyclopedia, Intrinsic function</a>
* @see <a href="http://en.wikipedia.org/wiki/Compiler_optimization">Wikipedia, the
* free encyclopedia, Compiler optimization</a>
*/
virtual Expression::Ptr compress(const StaticContext::Ptr &context);
/**
* @returns a bitwise OR'd value of properties, describing the
* characteristics of the expression. These properties affects how
* this Expression is treated in for example type checking stages.
*
* The default implementation returns 0. Override and let the function return
* a different value, if that's of interest.
*
* An important decision when re-implementing properties() is whether
* to OR in the properties() of ones operands. For instance, if an
* operand has RequiresFocus set, that flag nost likely applies to the
* apparent as well, since it depends on its operand.
*
* @see deepProperties()
* @returns Expression::None, meaning no special properties
*/
virtual Properties properties() const;
/**
* Recursively computes through all descendants until a Property
* is encount
*/
virtual Properties dependencies() const;
/**
* @short Computes the union of properties for this Expression and all
* its descending children.
*
* @see properties()
*/
Properties deepProperties() const;
/**
* This function is a utility function, which performs bitwise logic
* on properties() in order to find out whether the Expression::IsEvaluated
* flag is set.
*
* @note Do not attempt to re-implement this function. Instead, return the
* IsEvaluated flag by re-implementing the properties() function.
*/
inline bool isEvaluated() const;
/**
* This function is a utility function, syntactic sugar for determining
* whether this Expression is @p id. For example, calling <tt>is(IDIfThenClause)</tt>
* is equivalent to <tt>id() == IDIfThenClause</tt>
*
* @note Do not attempt to re-implement this function. Instead, return the
* appropriate flag in the virtual id() function.
*/
inline bool is(const ID id) const;
/**
* Determines whether this Expression has Property @p prop set.
*
* Calling <tt>expr->has(MyProperty)</tt> is semantically equivalent
* to <tt>expr->properties().testFlag(MyProperty)</tt>. In
* other words, has(), as well as is(), provides syntacti sugar
* and makes code more readable.
*
* @note Do not attempt to re-implement this function. Instead, return
* the appropriate flag by re-implementing the properties() function.
*/
inline bool has(const Property prop) const;
inline bool hasDependency(const Property prop) const;
virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const = 0;
/**
* This property, which has no setter, returns an enum value that uniquely identifies
* this Expression. Patternist makes no use of C++'s dynamic_cast feature, but uses this
* polymorphic function instead.
*
* @returns always IgnorableExpression.
*/
virtual ID id() const;
/**
* Returns the OptimizationPasses that applies for this Expression. The
* default implementation returns an empty list. Sub-classes can re-implement
* this function and return actual OptimizationPasses.
*
* @returns always an empty list.
*/
virtual QList<QExplicitlySharedDataPointer<OptimizationPass> > optimizationPasses() const;
/**
* Returns the required type the context item must be an instance of.
*
* If this Expression requires a focus, meaning its properties()
* function returns RequiresContextItem,
* it must return a type from this function. If any type is ok, BuiltinTypes::item should be
* returned.
*
* In other words, this function must only be re-implemented if the focus is used. The default
* implementation performs an assert crash.
*/
virtual ItemType::Ptr expectedContextItemType() const;
/**
* If an Expression creates a focus because it has set the property CreatesFocusForLast,
* it should override this function and make it return the ItemType that
* the context item in the focus has.
*
* @returns never @c null.
* @see announceFocusType()
*/
virtual ItemType::Ptr newFocusType() const;
/**
* @short Returns @c this.
*/
virtual const SourceLocationReflection *actualReflection() const;
/**
* Reimplementation of SourceLocationReflection::description().
*/
virtual QString description() const;
/**
* When this function is called, it signals that the parent will create
* a focus of type @p itemType.
*
* This type can also be retrieved through StaticContext::contextItemType()
* when inside typeCheck(), but in some cases this is too late. For
* instance, a parent needs to have the static type of its child
* properly reported before it calls its typeCheck()(and the child's
* type is inferred from the focus).
*
* The default implementation delegates the call on to the children.
*
* This function may be called at arbitrary times, in arbitrary
* amounts.
*
* If the AST node overriding this call has children, it should be
* considered whether the default implementation should be called, such
* that they type is announced to them too.
*
* The caller guarantees that @p itemType is not @c null.
*/
virtual void announceFocusType(const ItemType::Ptr &itemType);
/**
* This function take the two Expression pointers @p old and @p New, and
* in a safe way, by handling reference counting and being aware of whether
* the two pointers actually are different, switches the two. When compiling
* in debug mode, informative debug messages are printed.
*
* This function is conceptually similar to Qt's qSwap(), but has
* debugging functionality and also handles source locations.
*/
static inline void rewrite(Expression::Ptr &old,
const Expression::Ptr &New,
const StaticContext::Ptr &context);
/**
* @short Rewrites this Expression to @p to, and return @p to.
*
* Source location annotations are adjusted appropriately.
*/
inline const Expression::Ptr &rewrite(const Expression::Ptr &to,
const StaticContext::Ptr &context) const;
/**
* By default 0.5 is returned.
*/
virtual PatternPriority patternPriority() const;
protected:
/**
* @returns @c true if all operands are constant values of somekind, and are already
* evaluated. A string literal, is a typical example.
*/
virtual bool compressOperands(const StaticContext::Ptr &) = 0;
void typeCheckOperands(const StaticContext::Ptr &context);
private:
static Expression::Ptr invokeOptimizers(const Expression::Ptr &expr,
const StaticContext::Ptr &context);
/**
* @return a StaticContext that has adopted the context item type properly
* for this Expression.
*/
inline StaticContext::Ptr finalizeStaticContext(const StaticContext::Ptr &context) const;
/**
* @short Performs constant propagation, also called constant folding, on this expression.
*
* This means that it attempts to evaluate this expression at compile and returns the result value
* appropriately as an Expression. For example, for the XPath expression
* <tt>1 + 3</tt> would an Integer of value 4 would be returned.
*
* It is not checked whether constant propagation is possible, the
* caller is responsible for this.
*
* @see <a href="http://en.wikipedia.org/wiki/Constant_propagation">Constant folding,
* From Wikipedia, the free encyclopedia</a>
*/
Expression::Ptr constantPropagate(const StaticContext::Ptr &context) const;
Q_DISABLE_COPY(Expression)
};
Q_DECLARE_OPERATORS_FOR_FLAGS(Expression::Properties)
inline bool Expression::is(const Expression::ID i) const
{
return id() == i;
}
inline bool Expression::isEvaluated() const
{
return has(IsEvaluated);
}
inline bool Expression::has(const Expression::Property prop) const
{
return properties().testFlag(prop);
}
inline bool Expression::hasDependency(const Expression::Property prop) const
{
return dependencies().testFlag(prop);
}
inline void Expression::rewrite(Expression::Ptr &old,
const Expression::Ptr &New,
const StaticContext::Ptr &context)
{
Q_ASSERT(old);
Q_ASSERT(New);
if(old != New)
{
pDebug() << "AST REWRITE:" << old.data() << "to" << New.data()
<< '(' << old->actualReflection() << "to" << New->actualReflection() << ", "
<< old->description() << "to" << New->description() << ")";
/* The order of these two lines is significant.. */
context->addLocation(New.data(), context->locationFor(old->actualReflection()));
old = New;
}
}
inline const Expression::Ptr &Expression::rewrite(const Expression::Ptr &to,
const StaticContext::Ptr &context) const
{
context->addLocation(to.data(), context->locationFor(this));
return to;
}
}
Q_DECLARE_TYPEINFO(QPatternist::Expression::Ptr, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
QT_END_HEADER
#endif
|