Qt 4.8
quserfunctioncallsite.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 "qcommonsequencetypes_p.h"
43 #include "qdynamiccontextstore_p.h"
44 #include "qevaluationcache_p.h"
45 
47 
49 
50 using namespace QPatternist;
51 
53  const FunctionSignature::Arity ar) : CallSite(nameP)
54  , m_arity(ar)
55  , m_expressionSlotOffset(-2)
56 
57 {
58 }
59 
61 {
62  return m_body->evaluateSequence(bindVariables(context));
63 }
64 
66 {
67  return m_body->evaluateSingleton(bindVariables(context));
68 }
69 
71 {
72  return m_body->evaluateEBV(bindVariables(context));
73 }
74 
76 {
78 }
79 
81 {
82  const DynamicContext::Ptr stackContext(context->createStack());
83  Q_ASSERT(stackContext);
84 
87 
89 
90  for(; it != end; ++it)
91  {
92  stackContext->setExpressionVariable(slot,
93  Expression::Ptr(new DynamicContextStore(*it, context)));
94  ++slot;
95  }
96 
97  return stackContext;
98 }
99 
101 {
102  SequenceType::List result;
103 
105  {
107  const FunctionArgument::List::const_iterator end(args.constEnd());
108  FunctionArgument::List::const_iterator it(args.constBegin());
109 
110  for(; it != end; ++it)
111  result.append((*it)->type());
112  }
113  else
115 
116  return result;
117 }
118 
120  const SequenceType::Ptr &reqType)
121 {
122  /* The parser calls TypeChecker::applyFunctionConversion() on user function
123  * bodies, possibly indirectly, before all function call sites have been
124  * resolved. Hence it's possible that we're called before before the usual
125  * typeCheck() pass, and hence before we have been resolved/checked and
126  * subsequently m_functionDeclaration set. Therefore, encounter for that below.
127  *
128  * UnresolvedVariableReference::typeCheck() has the same dilemma.
129  */
130 
131  /* Ensure that the return value of the function is properly
132  * converted/does match from where it is called(which is here). */
134  return CallSite::typeCheck(context, reqType);
135  else
136  {
137  /* Update, such that we use a recent version of the body that has typeCheck()
138  * and compress() rewrites included. */
140 
141  /* Note, we can't assign to m_functionDeclaration->body() because UserFunction can apply
142  * to several different callsites. Hence we need our own version. */
143  m_body = m_body->typeCheck(context, reqType);
144 
145  /* We just act as a pipe for m_body, so we don't have to typecheck ourselves. However,
146  * the arguments must match the function declaration. */
147  typeCheckOperands(context);
148  return Expression::Ptr(this);
149  }
150 }
151 
153 {
154  if(!isRecursive())
155  rewrite(m_body, m_body->compress(context), context);
156 
157  return CallSite::compress(context);
158 }
159 
161 {
162  return DisableElimination;
163 }
164 
166 {
167  /* Our return type, is the static type of the function body. We could have also used
168  * m_functionDeclaration->signature()->returnType(), but it doesn't get updated
169  * when function conversion is applied.
170  * We can't use m_body's type if we're recursive, because m_body computes its type
171  * from its children, and we're at least one of the children. Hence, we would
172  * recurse infinitely if we did.
173  *
174  * m_body can be null here if we're called before setSource().
175  */
176  if(isRecursive() || !m_body)
177  return CommonSequenceTypes::ZeroOrMoreItems; // TODO use the declaration, it can have a type explicitly.
178  else
179  return m_body->staticType();
180 }
181 
183 {
184  return visitor->visit(this);
185 }
186 
188 {
189  return IDUserFunctionCallsite;
190 }
191 
193 {
194  Q_ASSERT(sign);
195 
196  return sign->name() == name()
197  &&
198  sign->isArityValid(m_arity);
199 }
200 
202 {
203  Q_ASSERT(sign);
204 
206  return isRecursive();
207 }
208 
210  const VariableSlotID cacheSlotOffset)
211 {
212  m_functionDeclaration = userFunction;
213  m_body = userFunction->body();
215 
216  const int len = m_operands.size();
217 
218  const VariableDeclaration::List varDecls(userFunction->argumentDeclarations());
219 
220  for(int i = 0; i < len; ++i)
221  {
222  /* We don't want evaluation caches for range variables, it's not necessary since
223  * the item is already cached in DynamicContext::rangeVariable(). */
225  continue;
226 
227  /* Note that we pass in cacheSlotOffset + i here instead of varDecls.at(i)->slot since
228  * we want independent caches for each callsite. */
230  varDecls.at(i).data(),
231  cacheSlotOffset + i));
232  }
233 }
234 
236 {
237  return m_arity;
238 }
239 
241 {
243 }
244 
virtual CallTargetDescription::Ptr callTargetDescription() const
qint32 VariableSlotID
FunctionSignature::Ptr signature() const
Abstract base-class for Expression instances that are callsites to other components, such as templates or user functions.
Definition: qcallsite_p.h:72
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
const FunctionSignature::Arity m_arity
VariableSlotID expressionSlotOffset() const
static const SequenceType::Ptr ZeroOrMoreItems
#define it(className, varName)
virtual Expression::Properties properties() const
virtual bool evaluateEBV(const DynamicContext::Ptr &context) const
virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const
virtual Expression::Ptr compress(const StaticContext::Ptr &context)
The QExplicitlySharedDataPointer class represents a pointer to an explicitly shared object...
Definition: qshareddata.h:136
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qlist.h:269
DynamicContext::Ptr createStack()
virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType)
Definition: qexpression.cpp:70
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
virtual SequenceType::List expectedOperandTypes() const
Returns the types declared in the function declaration.
virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const
virtual Expression::Ptr compress(const StaticContext::Ptr &context)
QXmlName name() const
Definition: qcallsite.cpp:53
DynamicContext::Ptr bindVariables(const DynamicContext::Ptr &context) const
static int sign(int x)
friend class const_iterator
Definition: qlist.h:264
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
FunctionArgument::List arguments() const
static void rewrite(Expression::Ptr &old, const Expression::Ptr &New, const StaticContext::Ptr &context)
virtual bool evaluateEBV(const DynamicContext::Ptr &context) const
UserFunctionCallsite(const QXmlName name, const FunctionSignature::Arity arity)
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.
bool isSignatureValid(const FunctionSignature::Ptr &sign) const
virtual SequenceType::Ptr staticType() const
virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const
virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType)
QExplicitlySharedDataPointer< Expression > Ptr
A smart pointer wrapping mutable Expression instances.
bool isRecursive() const
Definition: qcallsite.cpp:58
virtual SequenceType::Ptr staticType() const =0
The QXmlName class represents the name of an XML node, in an efficient, namespace-aware way...
Definition: qxmlname.h:58
Represents an item in the XPath 2.0 Data Model.
Definition: qitem_p.h:182
void setSource(const UserFunction::Ptr &userFunction, const VariableSlotID cacheSlotOffset)
Evaluates to the same result as its operand, but ensures the operand is evaluated once even if this E...
const Expression::Ptr & body() const
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
FunctionSignature::Arity arity() const
void setIsRecursive(const bool value)
Definition: qcallsite.cpp:63
virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const
Evaluates its operand with an assigned DynamicContext, not the one passed to one of the evaluation fu...
bool isArityValid(const xsInteger arity) const
The QFlags class provides a type-safe way of storing OR-combinations of enum values.
Definition: qglobal.h:2313
VariableDeclaration::List argumentDeclarations() const
static const KeyPair *const end
bool is(const ID id) const
virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const
virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const
virtual bool configureRecursion(const CallTargetDescription::Ptr &sign)
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) 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