Qt 4.8
qexpression.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qboolean_p.h"
43 #include "qcommonvalues_p.h"
44 #include "qemptysequence_p.h"
45 #include "qliteral_p.h"
46 #include "qliteralsequence_p.h"
47 #include "qoperandsiterator_p.h"
48 #include "qoptimizerframework_p.h"
49 #include "qstaticfocuscontext_p.h"
50 #include "qtypechecker_p.h"
51 
52 #include "qexpression_p.h"
53 
55 
56 using namespace QPatternist;
57 
59 {
60 }
61 
63 {
64  Q_ASSERT(context);
65  const ItemType::Ptr focusType(newFocusType());
66  Q_ASSERT(focusType);
67  return StaticContext::Ptr(new StaticFocusContext(focusType, context));
68 }
69 
71  const SequenceType::Ptr &reqType)
72 {
73  Q_ASSERT(reqType);
74  typeCheckOperands(context);
75  return TypeChecker::applyFunctionConversion(Expression::Ptr(this), reqType, context);
76 }
77 
79 {
80  const Expression::List ops(operands());
81 
82  /* Check if this expression has any operands at all. */
83  if(ops.isEmpty())
84  return; /* We're done, early exit. */
85 
87  Expression::List result;
88 
89  /* If we create a focus, we handle the last one specially, so avoid it in the loop. */
90  const bool createsFocus = has(CreatesFocusForLast);
91  const SequenceType::List::const_iterator typeEnd(createsFocus ? --opTypes.constEnd()
92  : opTypes.constEnd());
93  const Expression::List::const_iterator end(createsFocus ? --ops.constEnd()
94  : ops.constEnd());
95 
97  SequenceType::Ptr t(*reqType);
98  // TODO we assign twice to t here(also below in loop) when ops.size() > 1
99 
101 
102  for(; it != end; ++it)
103  {
104  /* This ensures that the last expectedOperandType stays, and is
105  * used for all other operands. This is used for expressions that
106  * have an infinite amount of operands, such as the concat() function. */
107  if(reqType != typeEnd)
108  {
109  t = *reqType;
110  ++reqType;
111  }
112 
113  /* Let the child & its children typecheck. */
114  result.append((*it)->typeCheck(context, t));
115  }
116 
117  if(createsFocus)
118  {
119  const StaticContext::Ptr newContext(finalizeStaticContext(context));
120  result.append(ops.last()->typeCheck(newContext, opTypes.last()));
121  }
122 
123  setOperands(result);
124 }
125 
127  const StaticContext::Ptr &context)
128 {
129  Q_ASSERT(expr);
130 
131  const OptimizationPass::List opts(expr->optimizationPasses());
132 
133  if(opts.isEmpty()) /* Early exit. */
134  {
135  return expr;
136  }
137 
138  const OptimizationPass::List::const_iterator passEnd(opts.constEnd());
139  const OptimizationPass::List::const_iterator end(opts.constEnd());
140  OptimizationPass::List::const_iterator passIt(opts.constBegin());
141 
142  for(; passIt != passEnd; ++passIt) /* Invoke each optimization pass. */
143  {
144  const OptimizationPass::Ptr pass(*passIt); /* Alias, for readability. */
145  OptimizationPass::ExpressionMarker sourceMarker(pass->sourceExpression);
146 
147  if(pass->startIdentifier && !pass->startIdentifier->matches(expr))
148  {
149  /* This pass specified a start identifier and it did
150  * not match -- let's try the next OptimizationPass. */
151  continue;
152  }
153 
154  const ExpressionIdentifier::List::const_iterator idEnd(pass->operandIdentifiers.constEnd());
155  ExpressionIdentifier::List::const_iterator idIt(pass->operandIdentifiers.constBegin());
156  const Expression::List ops(expr->operands());
157  const Expression::List::const_iterator opEnd(ops.constEnd());
158  Expression::List::const_iterator opIt(ops.constBegin());
159 
160  switch(pass->operandsMatchMethod)
161  {
163  {
164  for(; opIt != opEnd; ++opIt)
165  {
166  const Expression::Ptr operand(*opIt); /* Alias, for readability. */
167  const ExpressionIdentifier::Ptr opIdentifier(*idIt); /* Alias, for readability. */
168  if(opIdentifier && !opIdentifier->matches(operand))
169  {
170  break;
171  }
172 
173  ++idIt;
174  }
175 
176  if(opIt == opEnd)
177  break; /* All operands matched, so this pass matched. */
178  else
179  {
180  /* The loop above did not finish which means all operands did not match.
181  Therefore, this OptimizationPass did not match -- let's try the next one. */
182  continue;
183  }
184  }
186  {
187  Q_ASSERT_X(ops.count() == 2, Q_FUNC_INFO,
188  "AnyOrder is currently only supported for Expressions with two operands.");
189  if(pass->operandIdentifiers.first()->matches(ops.first()) &&
190  pass->operandIdentifiers.last()->matches(ops.last()))
191  {
192  break;
193  }
194  else if(pass->operandIdentifiers.first()->matches(ops.last()) &&
195  pass->operandIdentifiers.last()->matches(ops.first()))
196  {
197  sourceMarker.first() = 1;
198  sourceMarker[1] = 0;
199  break; /* This pass matched. */
200  }
201  else
202  continue; /* This pass didn't match, let's loop through the next pass. */
203  }
204  }
205 
206  /* Figure out the source Expression, if any. */
208  Expression::Ptr sourceExpr;
209 
210  if(!sourceMarker.isEmpty())
211  {
214  sourceExpr = expr;
215 
216  for(; mIt != mEnd; ++mIt)
217  {
218  Q_ASSERT(*mIt >= 0);
219  sourceExpr = sourceExpr->operands().at(*mIt);
220  }
221 
222  operands.append(sourceExpr);
223  }
224 
225  if(operands.isEmpty())
226  {
227  Q_ASSERT(pass->resultCreator);
228  return pass->resultCreator->create(Expression::List(), context, expr.data())->compress(context);
229  }
230  else if(pass->resultCreator)
231  return pass->resultCreator->create(operands, context, expr.data())->compress(context);
232  else
233  {
234  return sourceExpr;
235  }
236  }
237 
238  return expr;
239 }
240 
242 {
243  if(!compressOperands(context))
244  {
245  /* At least one of the operands cannot be evaluated at compile, so
246  * 'this' Expression cannot const fold. */
247  return invokeOptimizers(Expression::Ptr(this), context);
248  }
249 
250  Expression::Ptr retval;
251 
253  retval = Expression::Ptr(this);
254  else
255  retval = constantPropagate(context);
256 
257  return invokeOptimizers(retval, context);
258 }
259 
261 {
262  Q_ASSERT(context);
263 
264  /* Optimization: We rewrite literals to literals here, which is pointless.
265  * Maybe we should have a property which says "doesn't disable elimination
266  * but don't eliminate me." */
267  if(staticType()->cardinality().allowsMany())
268  {
270  Item::List result;
271  Item item(it->next());
272 
273  while(item)
274  {
275  result.append(item);
276  item = it->next();
277  }
278 
279  switch(result.count())
280  {
281  case 0:
282  return EmptySequence::create(this, context);
283  case 1:
284  return rewrite(Expression::Ptr(new Literal(result.first())), context);
285  default:
286  return rewrite(Expression::Ptr(new LiteralSequence(result)), context);
287  }
288  }
289  else
290  {
291  const Item item(evaluateSingleton(context->dynamicContext()));
292 
293  if(item)
294  return rewrite(Expression::Ptr(new Literal(item)), context);
295  else
296  return EmptySequence::create(this, context);
297  }
298 }
299 
301 {
302  const Item item(evaluateSingleton(context));
303 
304  if(item)
305  return makeSingletonIterator(item);
306  else
308 }
309 
311 {
312  return Boolean::fromValue(evaluateEBV(context));
313 }
314 
316 {
317  return Boolean::evaluateEBV(evaluateSequence(context), context);
318 }
319 
321 {
322  QAbstractXmlReceiver *const receiver = context->outputReceiver();
323  const Item::Iterator::Ptr it(evaluateSequence(context));
324  Item next(it->next());
325 
326  while(next)
327  {
328  receiver->item(next);
329  next = it->next();
330  }
331 }
332 
334 {
335  Q_ASSERT_X(false, Q_FUNC_INFO,
336  "expectedContextItemType() must be overridden when RequiresContextItem is set.");
337  return ItemType::Ptr();
338 }
339 
341 {
342  return Properties();
343 }
344 
346 {
347  OperandsIterator it(Ptr(const_cast<Expression *>(this)), OperandsIterator::ExcludeParent);
348  Expression::Ptr next(it.next());
349 
351 
352  while(next)
353  {
354  dependencies |= next->dependencies();
355  next = it.next();
356  }
357 
359 }
360 
362 {
363  const Expression::List ops(operands());
364  const int len = ops.count();
365 
366  for(int i = 0; i < len; ++i)
367  ops.at(i)->announceFocusType(itemType);
368 }
369 
371 {
372  Properties props(properties());
373  const Expression::List ops(operands());
374  const int len = ops.count();
375 
376  for(int i = 0; i < len; ++i)
377  props |= ops.at(i)->deepProperties();
378 
379  return props;
380 }
381 
383 {
384  return IDIgnorableExpression;
385 }
386 
388 {
389  return OptimizationPass::List();
390 }
391 
393 {
394  Q_ASSERT_X(false, Q_FUNC_INFO,
395  "This function must be overridden when CreatesFocusForLast is set.");
396  return ItemType::Ptr();
397 }
398 
400 {
401  return this;
402 }
403 
405 {
406  return QString::fromLatin1("Expression, id: %1").arg(QString::number(id()));
407 }
408 
410 {
411  return 0.5;
412 }
413 
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
virtual SequenceType::List expectedOperandTypes() const =0
virtual void setOperands(const Expression::List &operands)=0
A push interface for the XPath Data Model. Similar to SAX&#39;s ContentHandler.
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
A StaticContext that carries a specified static type for the context item, but otherwise delegates to...
#define it(className, varName)
virtual PatternPriority patternPriority() const
virtual bool evaluateEBV(const DynamicContext::Ptr &context) const
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qlist.h:269
The QList::const_iterator class provides an STL-style const iterator for QList and QQueue...
Definition: qlist.h:228
static Expression::Ptr invokeOptimizers(const Expression::Ptr &expr, const StaticContext::Ptr &context)
virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType)
Definition: qexpression.cpp:70
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
static bool evaluateEBV(const Item::Iterator::Ptr &e, const QExplicitlySharedDataPointer< DynamicContext > &)
Definition: qboolean.cpp:55
The QString class provides a Unicode character string.
Definition: qstring.h:83
virtual ItemType::Ptr expectedContextItemType() const
static Expression::Ptr create(const Expression *const replacementFor, const StaticContext::Ptr &context)
Creates an EmptySequence that is a replacement for replacementFor.
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
bool hasDependency(const Property prop) const
static const EmptyIterator< Item >::Ptr emptyIterator
bool has(const Property prop) const
virtual Expression::Ptr compress(const StaticContext::Ptr &context)
virtual QList< QExplicitlySharedDataPointer< OptimizationPass > > optimizationPasses() const
Expression::Ptr next()
Returns the current Expression and advances the iterator.
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
virtual const SourceLocationReflection * actualReflection() const
Returns this.
QList< OptimizationPass::Ptr > List
friend class const_iterator
Definition: qlist.h:264
virtual ID id() const
T * data() const
Returns a pointer to the shared data object.
Definition: qshareddata.h:145
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
void typeCheckOperands(const StaticContext::Ptr &context)
Definition: qexpression.cpp:78
StaticContext::Ptr finalizeStaticContext(const StaticContext::Ptr &context) const
Definition: qexpression.cpp:62
static void rewrite(Expression::Ptr &old, const Expression::Ptr &New, const StaticContext::Ptr &context)
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The namespace for the internal API of QtXmlPatterns.
virtual void item(const Item &item)=0
Sends an Item to this QAbstractXmlReceiver that may be a QXmlNodeModelIndex or an AtomicValue...
static Boolean::Ptr fromValue(const bool value)
Definition: qboolean.cpp:115
virtual Expression::List operands() const =0
Houses an AtomicValue, making it available as an Expression.
Definition: qliteral_p.h:74
T & first()
Returns a reference to the first item in the list.
Definition: qlist.h:282
QExplicitlySharedDataPointer< Expression > Ptr
A smart pointer wrapping mutable Expression instances.
QExplicitlySharedDataPointer< ItemType > Ptr
Definition: qitemtype_p.h:88
virtual SequenceType::Ptr staticType() const =0
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
QFlags< Property > Properties
Represents an item in the XPath 2.0 Data Model.
Definition: qitem_p.h:182
virtual bool compressOperands(const StaticContext::Ptr &)=0
static Expression::Ptr applyFunctionConversion(const Expression::Ptr &operand, const SequenceType::Ptr &reqType, const StaticContext::Ptr &context, const ReportContext::ErrorCode code=ReportContext::XPTY0004, const Options=Options(AutomaticallyConvert|CheckFocus))
Builds a pipeline of artificial AST nodes that ensures operand conforms to the type reqType by applyi...
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
virtual QExplicitlySharedDataPointer< DynamicContext > dynamicContext() const =0
Properties deepProperties() const
Computes the union of properties for this Expression and all its descending children.
T & last()
Returns a reference to the last item in the list.
Definition: qlist.h:284
virtual Properties properties() const
virtual QString description() const
Expression::Ptr constantPropagate(const StaticContext::Ptr &context) const
Performs constant propagation, also called constant folding, on this expression.
Houses a sequence of atomic values, making it available as an Expression.
The QFlags class provides a type-safe way of storing OR-combinations of enum values.
Definition: qglobal.h:2313
virtual QAbstractXmlReceiver * outputReceiver() const =0
QExplicitlySharedDataPointer< StaticContext > Ptr
static const KeyPair *const end
xsDouble PatternPriority
virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const
virtual void announceFocusType(const ItemType::Ptr &itemType)
virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const
virtual ItemType::Ptr newFocusType() const
Base class for all instances that represents something at a certain location.
virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const
virtual Properties dependencies() const
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:272
A helper class that iterates a tree of Expression instances. It is not a sub-class of QAbstractXmlFor...
#define Q_FUNC_INFO
Definition: qglobal.h:1871