summaryrefslogtreecommitdiff
path: root/src/xmlpatterns/expr/qexpression_p.h
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commite1b2c9deb5943faae2b29be6a5c006f75bb73f06 (patch)
treefc79e45367c0a8fc71185e9afc33f7503a58653c /src/xmlpatterns/expr/qexpression_p.h
downloadqtxmlpatterns-e1b2c9deb5943faae2b29be6a5c006f75bb73f06.tar.gz
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/xmlpatterns/expr/qexpression_p.h')
-rw-r--r--src/xmlpatterns/expr/qexpression_p.h909
1 files changed, 909 insertions, 0 deletions
diff --git a/src/xmlpatterns/expr/qexpression_p.h b/src/xmlpatterns/expr/qexpression_p.h
new file mode 100644
index 0000000..8bf37df
--- /dev/null
+++ b/src/xmlpatterns/expr/qexpression_p.h
@@ -0,0 +1,909 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 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