src/xmlpatterns/expr/qexpression_p.h
changeset 0 1918ee327afb
child 4 3b1da2848fc7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/xmlpatterns/expr/qexpression_p.h	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,909 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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