diff options
Diffstat (limited to 'src/xmlpatterns/expr')
176 files changed, 24538 insertions, 0 deletions
diff --git a/src/xmlpatterns/expr/expr.pri b/src/xmlpatterns/expr/expr.pri new file mode 100644 index 0000000..81c3994 --- /dev/null +++ b/src/xmlpatterns/expr/expr.pri @@ -0,0 +1,173 @@ +HEADERS += $$PWD/qandexpression_p.h \ + $$PWD/qapplytemplate_p.h \ + $$PWD/qargumentreference_p.h \ + $$PWD/qarithmeticexpression_p.h \ + $$PWD/qattributeconstructor_p.h \ + $$PWD/qattributenamevalidator_p.h \ + $$PWD/qaxisstep_p.h \ + $$PWD/qcachecells_p.h \ + $$PWD/qcallsite_p.h \ + $$PWD/qcalltargetdescription_p.h \ + $$PWD/qcalltemplate_p.h \ + $$PWD/qcastableas_p.h \ + $$PWD/qcastas_p.h \ + $$PWD/qcastingplatform_p.h \ + $$PWD/qcollationchecker_p.h \ + $$PWD/qcombinenodes_p.h \ + $$PWD/qcommentconstructor_p.h \ + $$PWD/qcomparisonplatform_p.h \ + $$PWD/qcomputednamespaceconstructor_p.h \ + $$PWD/qcontextitem_p.h \ + $$PWD/qcopyof_p.h \ + $$PWD/qcurrentitemstore_p.h \ + $$PWD/qdocumentconstructor_p.h \ + $$PWD/qdocumentcontentvalidator_p.h \ + $$PWD/qdynamiccontextstore_p.h \ + $$PWD/qelementconstructor_p.h \ + $$PWD/qemptycontainer_p.h \ + $$PWD/qemptysequence_p.h \ + $$PWD/qevaluationcache_p.h \ + $$PWD/qexpressiondispatch_p.h \ + $$PWD/qexpressionfactory_p.h \ + $$PWD/qexpression_p.h \ + $$PWD/qexpressionsequence_p.h \ + $$PWD/qexpressionvariablereference_p.h \ + $$PWD/qexternalvariableloader_p.h \ + $$PWD/qexternalvariablereference_p.h \ + $$PWD/qfirstitempredicate_p.h \ + $$PWD/qforclause_p.h \ + $$PWD/qgeneralcomparison_p.h \ + $$PWD/qgenericpredicate_p.h \ + $$PWD/qifthenclause_p.h \ + $$PWD/qinstanceof_p.h \ + $$PWD/qletclause_p.h \ + $$PWD/qliteral_p.h \ + $$PWD/qliteralsequence_p.h \ + $$PWD/qnamespaceconstructor_p.h \ + $$PWD/qncnameconstructor_p.h \ + $$PWD/qnodecomparison_p.h \ + $$PWD/qnodesort_p.h \ + $$PWD/qoperandsiterator_p.h \ + $$PWD/qoptimizationpasses_p.h \ + $$PWD/qoptimizerblocks_p.h \ + $$PWD/qoptimizerframework_p.h \ + $$PWD/qorderby_p.h \ + $$PWD/qorexpression_p.h \ + $$PWD/qpaircontainer_p.h \ + $$PWD/qparentnodeaxis_p.h \ + $$PWD/qpath_p.h \ + $$PWD/qpositionalvariablereference_p.h \ + $$PWD/qprocessinginstructionconstructor_p.h \ + $$PWD/qqnameconstructor_p.h \ + $$PWD/qquantifiedexpression_p.h \ + $$PWD/qrangeexpression_p.h \ + $$PWD/qrangevariablereference_p.h \ + $$PWD/qreturnorderby_p.h \ + $$PWD/qsimplecontentconstructor_p.h \ + $$PWD/qsinglecontainer_p.h \ + $$PWD/qsourcelocationreflection_p.h \ + $$PWD/qstaticbaseuristore_p.h \ + $$PWD/qstaticcompatibilitystore_p.h \ + $$PWD/qtemplatemode_p.h \ + $$PWD/qtemplateparameterreference_p.h \ + $$PWD/qtemplatepattern_p.h \ + $$PWD/qtemplatepattern_p.h \ + $$PWD/qtemplate_p.h \ + $$PWD/qtextnodeconstructor_p.h \ + $$PWD/qtreatas_p.h \ + $$PWD/qtriplecontainer_p.h \ + $$PWD/qtruthpredicate_p.h \ + $$PWD/qunaryexpression_p.h \ + $$PWD/qunlimitedcontainer_p.h \ + $$PWD/qunresolvedvariablereference_p.h \ + $$PWD/quserfunctioncallsite_p.h \ + $$PWD/quserfunction_p.h \ + $$PWD/qvalidate_p.h \ + $$PWD/qvaluecomparison_p.h \ + $$PWD/qvariabledeclaration_p.h \ + $$PWD/qvariablereference_p.h \ + $$PWD/qwithparam_p.h \ + $$PWD/qxsltsimplecontentconstructor_p.h + +SOURCES += $$PWD/qandexpression.cpp \ + $$PWD/qapplytemplate.cpp \ + $$PWD/qargumentreference.cpp \ + $$PWD/qarithmeticexpression.cpp \ + $$PWD/qattributeconstructor.cpp \ + $$PWD/qattributenamevalidator.cpp \ + $$PWD/qaxisstep.cpp \ + $$PWD/qcallsite.cpp \ + $$PWD/qcalltargetdescription.cpp \ + $$PWD/qcalltemplate.cpp \ + $$PWD/qcastableas.cpp \ + $$PWD/qcastas.cpp \ + $$PWD/qcollationchecker.cpp \ + $$PWD/qcombinenodes.cpp \ + $$PWD/qcommentconstructor.cpp \ + $$PWD/qcomputednamespaceconstructor.cpp \ + $$PWD/qcontextitem.cpp \ + $$PWD/qcopyof.cpp \ + $$PWD/qcurrentitemstore.cpp \ + $$PWD/qdocumentconstructor.cpp \ + $$PWD/qdocumentcontentvalidator.cpp \ + $$PWD/qdynamiccontextstore.cpp \ + $$PWD/qelementconstructor.cpp \ + $$PWD/qemptycontainer.cpp \ + $$PWD/qemptysequence.cpp \ + $$PWD/qexpression.cpp \ + $$PWD/qexpressionfactory.cpp \ + $$PWD/qexpressionsequence.cpp \ + $$PWD/qexpressionvariablereference.cpp \ + $$PWD/qexternalvariableloader.cpp \ + $$PWD/qexternalvariablereference.cpp \ + $$PWD/qfirstitempredicate.cpp \ + $$PWD/qforclause.cpp \ + $$PWD/qgeneralcomparison.cpp \ + $$PWD/qgenericpredicate.cpp \ + $$PWD/qifthenclause.cpp \ + $$PWD/qinstanceof.cpp \ + $$PWD/qletclause.cpp \ + $$PWD/qliteral.cpp \ + $$PWD/qliteralsequence.cpp \ + $$PWD/qnamespaceconstructor.cpp \ + $$PWD/qncnameconstructor.cpp \ + $$PWD/qnodecomparison.cpp \ + $$PWD/qnodesort.cpp \ + $$PWD/qoptimizationpasses.cpp \ + $$PWD/qoptimizerblocks.cpp \ + $$PWD/qoptimizerframework.cpp \ + $$PWD/qorderby.cpp \ + $$PWD/qorexpression.cpp \ + $$PWD/qpaircontainer.cpp \ + $$PWD/qparentnodeaxis.cpp \ + $$PWD/qpath.cpp \ + $$PWD/qpositionalvariablereference.cpp \ + $$PWD/qprocessinginstructionconstructor.cpp \ + $$PWD/qqnameconstructor.cpp \ + $$PWD/qquantifiedexpression.cpp \ + $$PWD/qrangeexpression.cpp \ + $$PWD/qrangevariablereference.cpp \ + $$PWD/qreturnorderby.cpp \ + $$PWD/qsimplecontentconstructor.cpp \ + $$PWD/qsinglecontainer.cpp \ + $$PWD/qsourcelocationreflection.cpp \ + $$PWD/qstaticbaseuristore.cpp \ + $$PWD/qstaticcompatibilitystore.cpp \ + $$PWD/qtemplate.cpp \ + $$PWD/qtemplateinvoker.cpp \ + $$PWD/qtemplatemode.cpp \ + $$PWD/qtemplateparameterreference.cpp \ + $$PWD/qtextnodeconstructor.cpp \ + $$PWD/qtreatas.cpp \ + $$PWD/qtriplecontainer.cpp \ + $$PWD/qtruthpredicate.cpp \ + $$PWD/qunaryexpression.cpp \ + $$PWD/qunlimitedcontainer.cpp \ + $$PWD/qunresolvedvariablereference.cpp \ + $$PWD/quserfunctioncallsite.cpp \ + $$PWD/quserfunction.cpp \ + $$PWD/qvalidate.cpp \ + $$PWD/qvaluecomparison.cpp \ + $$PWD/qvariabledeclaration.cpp \ + $$PWD/qvariablereference.cpp \ + $$PWD/qxsltsimplecontentconstructor.cpp diff --git a/src/xmlpatterns/expr/qandexpression.cpp b/src/xmlpatterns/expr/qandexpression.cpp new file mode 100644 index 0000000..ae1d6f2 --- /dev/null +++ b/src/xmlpatterns/expr/qandexpression.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qboolean_p.h" +#include "qcommonsequencetypes_p.h" +#include "qcommonvalues_p.h" +#include "qliteral_p.h" + +#include "qandexpression_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +AndExpression::AndExpression(const Expression::Ptr &operand1, + const Expression::Ptr &operand2) : PairContainer(operand1, operand2) +{ +} + +bool AndExpression::evaluateEBV(const DynamicContext::Ptr &context) const +{ + return m_operand1->evaluateEBV(context) && m_operand2->evaluateEBV(context); +} + +Expression::Ptr AndExpression::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr newMe(PairContainer::compress(context)); + + if(newMe != this) + return newMe; + + /* Both operands mustn't be evaluated in order to be able to compress. */ + if(m_operand1->isEvaluated() && !m_operand1->evaluateEBV(context->dynamicContext())) + return wrapLiteral(CommonValues::BooleanFalse, context, this); + else if(m_operand2->isEvaluated() && !m_operand2->evaluateEBV(context->dynamicContext())) + return wrapLiteral(CommonValues::BooleanFalse, context, this); + else + return Expression::Ptr(this); +} + +SequenceType::List AndExpression::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::EBV); + result.append(CommonSequenceTypes::EBV); + return result; +} + +SequenceType::Ptr AndExpression::staticType() const +{ + return CommonSequenceTypes::ExactlyOneBoolean; +} + +ExpressionVisitorResult::Ptr AndExpression::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qandexpression_p.h b/src/xmlpatterns/expr/qandexpression_p.h new file mode 100644 index 0000000..b4fd87c --- /dev/null +++ b/src/xmlpatterns/expr/qandexpression_p.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** 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_AndExpression_H +#define Patternist_AndExpression_H + +#include "qpaircontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short Implements XPath 2.0's logical expression @c and. + * + * The @c and expression is the same in XQuery 1.0 as in XPath 2.0. + * + * @see <a href="http://www.w3.org/TR/xpath20/#id-logical-expressions">XML Path Language + * (XPath) 2.0, 3.6 Logical Expressions</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class AndExpression : public PairContainer + { + public: + AndExpression(const Expression::Ptr &operand1, + const Expression::Ptr &operand2); + + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + + virtual SequenceType::List expectedOperandTypes() const; + + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + /** + * @returns always CommonSequenceTypes::ExactlyOneBoolean + */ + virtual SequenceType::Ptr staticType() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qapplytemplate.cpp b/src/xmlpatterns/expr/qapplytemplate.cpp new file mode 100644 index 0000000..2a9f501 --- /dev/null +++ b/src/xmlpatterns/expr/qapplytemplate.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include <QtDebug> + +#include "qaxisstep_p.h" +#include "qcommonsequencetypes_p.h" +#include "qcommonvalues_p.h" +#include "qitemmappingiterator_p.h" +#include "qsequencemappingiterator_p.h" +#include "qpatternistlocale_p.h" + +#include "qapplytemplate_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ApplyTemplate::ApplyTemplate(const TemplateMode::Ptr &mode, + const WithParam::Hash &withParams, + const TemplateMode::Ptr &defaultMode) : TemplateInvoker(withParams) + , m_mode(mode) + , m_defaultMode(defaultMode) +{ + Q_ASSERT_X(m_mode || m_defaultMode, Q_FUNC_INFO, + "Either a mode, or the default mode must be supplied."); +} + +Item ApplyTemplate::mapToItem(const QXmlNodeModelIndex &node, + const DynamicContext::Ptr &) const +{ + return Item(node); +} + +Item::Iterator::Ptr ApplyTemplate::mapToSequence(const Item &item, + const DynamicContext::Ptr &context) const +{ + Q_UNUSED(item); + return evaluateSequence(context); +} + +TemplateMode::Ptr ApplyTemplate::effectiveMode(const DynamicContext::Ptr &context) const +{ + if(m_mode) + return m_mode; + else + { + const TemplateMode::Ptr currentMode(context->currentTemplateMode()); + + if(currentMode) + return currentMode; + else + return m_defaultMode; + } +} + +Template::Ptr ApplyTemplate::findTemplate(const DynamicContext::Ptr &context, + const TemplateMode::Ptr &templateMode) const +{ + const int count = templateMode->templatePatterns.count(); + Template::Ptr result; + /* It's redundant to initialize these values, but it suppresses false + * positives with GCC. */ + PatternPriority priority = 0; + TemplatePattern::ID id = -1; + + /* Possible optimization: detecting ambiguous rule matches could be forked off to a + * low prioirity thread. */ + for(int i = 0; i < count; ++i) + { + const TemplatePattern::Ptr &candidate = templateMode->templatePatterns.at(i); + if(candidate->matchPattern()->evaluateEBV(context)) + { + if(result) + { + if( candidate->id() != id + && candidate->priority() == priority + && candidate->templateTarget()->importPrecedence == + result->importPrecedence) + { + context->error(QtXmlPatterns::tr("Ambiguous rule match."), + ReportContext::XTRE0540, this); + } + else + break; + } + else + { + result = candidate->templateTarget(); + priority = candidate->priority(); + id = candidate->id(); + } + } + } + + return result; +} + +Item::Iterator::Ptr ApplyTemplate::evaluateSequence(const DynamicContext::Ptr &context) const +{ + const TemplateMode::Ptr templateMode(effectiveMode(context)); + const Template::Ptr &templateMatch = findTemplate(context, templateMode); + + if(templateMatch) + return templateMatch->body->evaluateSequence(templateMatch->createContext(this, context, false)); + else + { + /* None of our templates matched. Proceed with a built-in. */ + const Item current(context->contextItem()); + // TODO it can be an atomic value? + const QXmlNodeModelIndex::NodeKind kind(current.asNode().kind()); + + if(kind == QXmlNodeModelIndex::Element || kind == QXmlNodeModelIndex::Document) + { + pDebug() << "No template match, using builtin template for element() | document-node()"; + + const Item::Iterator::Ptr focusIterator(makeItemMappingIterator<Item>(ConstPtr(this), + current.asNode().iterate(QXmlNodeModelIndex::AxisChild), + context)); + + const DynamicContext::Ptr focus(context->createFocus()); + focus->setFocusIterator(focusIterator); + return makeSequenceMappingIterator<Item>(ConstPtr(this), focusIterator, focus); + } + return CommonValues::emptyIterator; + } +} + +Expression::Ptr ApplyTemplate::compress(const StaticContext::Ptr &context) +{ + /* If we have a mode, we will never need the default mode. */ + if(m_mode) + m_defaultMode.reset(); + + return TemplateInvoker::compress(context); +} + +SequenceType::Ptr ApplyTemplate::staticType() const +{ + return CommonSequenceTypes::ZeroOrMoreItems; +} + +ExpressionVisitorResult::Ptr ApplyTemplate::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::Properties ApplyTemplate::properties() const +{ + return RequiresFocus | DisableElimination; +} + +bool ApplyTemplate::configureRecursion(const CallTargetDescription::Ptr &sign) +{ + Q_ASSERT_X(false, Q_FUNC_INFO, "We're not expected to be called."); + Q_UNUSED(sign); + return false; +} + +Expression::Ptr ApplyTemplate::body() const +{ + Q_ASSERT_X(false, Q_FUNC_INFO, "We're not expected to be called."); + return Expression::Ptr(); +} + +CallTargetDescription::Ptr ApplyTemplate::callTargetDescription() const +{ + Q_ASSERT_X(false, Q_FUNC_INFO, "We're not expected to be called."); + return CallTargetDescription::Ptr(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qapplytemplate_p.h b/src/xmlpatterns/expr/qapplytemplate_p.h new file mode 100644 index 0000000..1398945 --- /dev/null +++ b/src/xmlpatterns/expr/qapplytemplate_p.h @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** 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_ApplyTemplate_H +#define Patternist_ApplyTemplate_H + +#include "qtemplatemode_p.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short When combined with other components, implements + * @c xsl:apply-templates. + * + * Note that ApplyTemplate isn't named ApplyTemplates. The reason for this + * is that ApplyTemplate doesn't do the iteration part. An @c + * <xsl:apply-templates/> instruction is rewritten into: + * + * @code + * child::node/() map apply-template() + * @endcode + * + * Hence, this expression requires a focus, although it can consist of + * atomic values. + * + * @since 4.5 + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ApplyTemplate : public TemplateInvoker + { + public: + typedef QExplicitlySharedDataPointer<ApplyTemplate> Ptr; + + /** + * @short @p mode may be @c null. If it is, ApplyTemplate interprets + * that as that it should use the #current mode. + * + * @see StaticContext::currentTemplateMode() + */ + ApplyTemplate(const TemplateMode::Ptr &mode, + const WithParam::Hash &withParams, + const TemplateMode::Ptr &defaultMode); + + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + + virtual SequenceType::Ptr staticType() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual Properties properties() const; + + /** + * The only reason this function exists, is in order to convert + * QXmlNodeModelIndex to QPatternist::Item. So, this is a huge + * performance setback. It applies for one of the builtin templates. + */ + inline Item mapToItem(const QXmlNodeModelIndex &node, + const DynamicContext::Ptr &context) const; + inline Item::Iterator::Ptr mapToSequence(const Item &item, + const DynamicContext::Ptr &context) const; + + inline TemplateMode::Ptr mode() const; + + virtual bool configureRecursion(const CallTargetDescription::Ptr &sign); + virtual Expression::Ptr body() const; + virtual CallTargetDescription::Ptr callTargetDescription() const; + + Expression::Ptr compress(const StaticContext::Ptr &context); + + private: + typedef QExplicitlySharedDataPointer<const ApplyTemplate> ConstPtr; + + Template::Ptr findTemplate(const DynamicContext::Ptr &context, + const TemplateMode::Ptr &templateMode) const; + /** + * @note You typically want to use effectiveMode(). + */ + const TemplateMode::Ptr m_mode; + + TemplateMode::Ptr m_defaultMode; + + inline TemplateMode::Ptr effectiveMode(const DynamicContext::Ptr &context) const; + }; + + TemplateMode::Ptr ApplyTemplate::mode() const + { + return m_mode; + } +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qargumentreference.cpp b/src/xmlpatterns/expr/qargumentreference.cpp new file mode 100644 index 0000000..d4c1bc6 --- /dev/null +++ b/src/xmlpatterns/expr/qargumentreference.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + + +#include "qargumentreference_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ArgumentReference::ArgumentReference(const SequenceType::Ptr &sourceType, + const VariableSlotID slotP) : VariableReference(slotP), + m_type(sourceType) +{ + Q_ASSERT(m_type); +} + +bool ArgumentReference::evaluateEBV(const DynamicContext::Ptr &context) const +{ + return context->expressionVariable(slot())->evaluateEBV(context); +} + +Item ArgumentReference::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + return context->expressionVariable(slot())->evaluateSingleton(context); +} + +Item::Iterator::Ptr ArgumentReference::evaluateSequence(const DynamicContext::Ptr &context) const +{ + return context->expressionVariable(slot())->evaluateSequence(context); +} + +SequenceType::Ptr ArgumentReference::staticType() const +{ + return m_type; +} + +ExpressionVisitorResult::Ptr ArgumentReference::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID ArgumentReference::id() const +{ + return IDArgumentReference; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qargumentreference_p.h b/src/xmlpatterns/expr/qargumentreference_p.h new file mode 100644 index 0000000..0fc51d3 --- /dev/null +++ b/src/xmlpatterns/expr/qargumentreference_p.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** 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_ArgumentReference_H +#define Patternist_ArgumentReference_H + +#include "qvariablereference_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A reference to an argument declared in a UserFunction. + * + * This is in other words a variable reference in side a function + * body, that references a function argument. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ArgumentReference : public VariableReference + { + public: + ArgumentReference(const SequenceType::Ptr &sourceType, + const VariableSlotID slot); + + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + virtual SequenceType::Ptr staticType() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual ID id() const; + + private: + const SequenceType::Ptr m_type; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qarithmeticexpression.cpp b/src/xmlpatterns/expr/qarithmeticexpression.cpp new file mode 100644 index 0000000..e424dc0 --- /dev/null +++ b/src/xmlpatterns/expr/qarithmeticexpression.cpp @@ -0,0 +1,363 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qboolean_p.h" +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qemptysequence_p.h" +#include "qgenericsequencetype_p.h" +#include "qliteral_p.h" +#include "qpatternistlocale_p.h" +#include "qschemanumeric_p.h" +#include "quntypedatomicconverter_p.h" + +#include "qarithmeticexpression_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ArithmeticExpression::ArithmeticExpression(const Expression::Ptr &op1, + const AtomicMathematician::Operator op, + const Expression::Ptr &op2) : PairContainer(op1, op2) + , m_op(op) + , m_isCompat(false) +{ +} + +Item ArithmeticExpression::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + const Item op1(m_operand1->evaluateSingleton(context)); + if(!op1) + return Item(); + + const Item op2(m_operand2->evaluateSingleton(context)); + if(!op2) + return Item(); + + return flexiblyCalculate(op1, m_op, op2, m_mather, context, this, + ReportContext::XPTY0004, m_isCompat); +} + +/** + * Since ArithmeticExpression::flexiblyCalculate() creates Expression instances + * at runtime, we have the problem of having SourceLocationReflections for them + * in the case that we run into a runtime error, since the locations are always + * located at compile time. + * + * This class simply delegates the reflection over to an existing expression. + * + * I only managed to trigger this with "current() + 1", where current() + * evaluates to an invalid representation for @c xs:double. + * + * @since 4.5 + * @author Frans Englich <frans.englich@nokia.com> + */ +class DelegatingReflectionExpression : public Literal +{ +public: + DelegatingReflectionExpression(const Item &item, + const SourceLocationReflection *const reflection) : Literal(item) + , m_reflection(reflection) + { + } + + virtual const SourceLocationReflection *actualReflection() const + { + return m_reflection; + } + +private: + const SourceLocationReflection *const m_reflection; +}; + +Item ArithmeticExpression::flexiblyCalculate(const Item &op1, + const AtomicMathematician::Operator op, + const Item &op2, + const AtomicMathematician::Ptr &mather, + const DynamicContext::Ptr &context, + const SourceLocationReflection *const reflection, + const ReportContext::ErrorCode code, + const bool isCompat) +{ + if(mather) + return mather->calculate(op1, op, op2, context); + + /* This is a very heavy code path. */ + Expression::Ptr a1(new DelegatingReflectionExpression(op1, reflection)); + Expression::Ptr a2(new DelegatingReflectionExpression(op2, reflection)); + + const AtomicMathematician::Ptr ingela(fetchMathematician(a1, a2, op, true, context, reflection, code, isCompat)); + + return ingela->calculate(a1->evaluateSingleton(context), + op, + a2->evaluateSingleton(context), + context); +} + +Expression::Ptr ArithmeticExpression::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + m_isCompat = context->compatModeEnabled(); + + const Expression::Ptr me(PairContainer::typeCheck(context, reqType)); + const ItemType::Ptr t1(m_operand1->staticType()->itemType()); + const ItemType::Ptr t2(m_operand2->staticType()->itemType()); + + if(*CommonSequenceTypes::Empty == *t1 || + *CommonSequenceTypes::Empty == *t2) + { + return EmptySequence::create(this, context); + } + + if(*BuiltinTypes::xsAnyAtomicType == *t1 || + *BuiltinTypes::xsAnyAtomicType == *t2 || + *BuiltinTypes::numeric == *t1 || + *BuiltinTypes::numeric == *t2) + { + /* The static type of (at least) one of the operands could not + * be narrowed further than xs:anyAtomicType, so we do the operator + * lookup at runtime. */ + return me; + } + + m_mather = fetchMathematician(m_operand1, m_operand2, m_op, true, context, this, + ReportContext::XPTY0004, m_isCompat); + + return me; +} + +AtomicMathematician::Ptr +ArithmeticExpression::fetchMathematician(Expression::Ptr &op1, + Expression::Ptr &op2, + const AtomicMathematician::Operator op, + const bool issueError, + const ReportContext::Ptr &context, + const SourceLocationReflection *const reflection, + const ReportContext::ErrorCode code, + const bool isCompat) +{ + ItemType::Ptr t1(op1->staticType()->itemType()); + ItemType::Ptr t2(op2->staticType()->itemType()); + + if(BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t1) + || (isCompat && (BuiltinTypes::xsString->xdtTypeMatches(t1) + || BuiltinTypes::xsDecimal->xdtTypeMatches(t1)))) + { + op1 = Expression::Ptr(new UntypedAtomicConverter(op1, BuiltinTypes::xsDouble)); + /* The types might have changed, reload. */ + t1 = op1->staticType()->itemType(); + } + + if(BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t2) + || (isCompat && (BuiltinTypes::xsString->xdtTypeMatches(t1) + || BuiltinTypes::xsDecimal->xdtTypeMatches(t1)))) + { + op2 = Expression::Ptr(new UntypedAtomicConverter(op2, BuiltinTypes::xsDouble)); + /* The types might have changed, reload. */ + t2 = op2->staticType()->itemType(); + } + + const AtomicMathematicianLocator::Ptr locator + (static_cast<const AtomicType *>(t1.data())->mathematicianLocator()); + + if(!locator) + { + if(!issueError) + return AtomicMathematician::Ptr(); + + context->error(QtXmlPatterns::tr( + "Operator %1 cannot be used on type %2.") + .arg(formatKeyword(AtomicMathematician::displayName(op))) + .arg(formatType(context->namePool(), t1)), + code, reflection); + return AtomicMathematician::Ptr(); + } + + const AtomicMathematician::Ptr comp + (static_cast<const AtomicType *>(t2.data())->accept(locator, op, reflection)); + + if(comp) + return comp; + + if(!issueError) + return AtomicMathematician::Ptr(); + + context->error(QtXmlPatterns::tr("Operator %1 cannot be used on " + "atomic values of type %2 and %3.") + .arg(formatKeyword(AtomicMathematician::displayName(op))) + .arg(formatType(context->namePool(), t1)) + .arg(formatType(context->namePool(), t2)), + code, reflection); + return AtomicMathematician::Ptr(); +} + +SequenceType::Ptr ArithmeticExpression::staticType() const +{ + Cardinality card; + + /* These variables are important because they ensure staticType() only + * gets called once from this function. Before, this lead to strange + * semi-infinite recursion involving many arithmetic expressions. */ + const SequenceType::Ptr st1(m_operand1->staticType()); + const SequenceType::Ptr st2(m_operand2->staticType()); + + if(st1->cardinality().allowsEmpty() || + st2->cardinality().allowsEmpty()) + { + card = Cardinality::zeroOrOne(); + } + else + card = Cardinality::exactlyOne(); + + if(m_op == AtomicMathematician::IDiv) + return makeGenericSequenceType(BuiltinTypes::xsInteger, card); + + const ItemType::Ptr t1(st1->itemType()); + const ItemType::Ptr t2(st2->itemType()); + ItemType::Ptr returnType; + + /* Please, make this beautiful? */ + if(BuiltinTypes::xsTime->xdtTypeMatches(t1) || + BuiltinTypes::xsDate->xdtTypeMatches(t1) || + BuiltinTypes::xsDateTime->xdtTypeMatches(t1)) + { + if(BuiltinTypes::xsDuration->xdtTypeMatches(t2)) + returnType = t1; + else + returnType = BuiltinTypes::xsDayTimeDuration; + } + else if(BuiltinTypes::xsYearMonthDuration->xdtTypeMatches(t1)) + { + if(m_op == AtomicMathematician::Div && + BuiltinTypes::xsYearMonthDuration->xdtTypeMatches(t2)) + { + returnType = BuiltinTypes::xsDecimal; + } + else if(BuiltinTypes::numeric->xdtTypeMatches(t2)) + returnType = BuiltinTypes::xsYearMonthDuration; + else + returnType = t2; + } + else if(BuiltinTypes::xsYearMonthDuration->xdtTypeMatches(t2)) + { + returnType = BuiltinTypes::xsYearMonthDuration; + } + else if(BuiltinTypes::xsDayTimeDuration->xdtTypeMatches(t1)) + { + if(m_op == AtomicMathematician::Div && + BuiltinTypes::xsDayTimeDuration->xdtTypeMatches(t2)) + { + returnType = BuiltinTypes::xsDecimal; + } + else if(BuiltinTypes::numeric->xdtTypeMatches(t2)) + returnType = BuiltinTypes::xsDayTimeDuration; + else + returnType = t2; + } + else if(BuiltinTypes::xsDayTimeDuration->xdtTypeMatches(t2)) + { + returnType = BuiltinTypes::xsDayTimeDuration; + } + else if(BuiltinTypes::xsDouble->xdtTypeMatches(t1) || + BuiltinTypes::xsDouble->xdtTypeMatches(t2)) + { + returnType = BuiltinTypes::xsDouble; + } + else if(BuiltinTypes::xsFloat->xdtTypeMatches(t1) || + BuiltinTypes::xsFloat->xdtTypeMatches(t2)) + { + if(m_isCompat) + returnType = BuiltinTypes::xsFloat; + else + returnType = BuiltinTypes::xsDouble; + } + else if(BuiltinTypes::xsInteger->xdtTypeMatches(t1) && + BuiltinTypes::xsInteger->xdtTypeMatches(t2)) + { + if(m_isCompat) + returnType = BuiltinTypes::xsDouble; + else + { + /* "A div B numeric numeric op:numeric-divide(A, B) + * numeric; but xs:decimal if both operands are xs:integer" */ + if(m_op == AtomicMathematician::Div) + returnType = BuiltinTypes::xsDecimal; + else + returnType = BuiltinTypes::xsInteger; + } + } + else if(m_isCompat && (BuiltinTypes::xsInteger->xdtTypeMatches(t1) && + BuiltinTypes::xsInteger->xdtTypeMatches(t2))) + { + returnType = BuiltinTypes::xsDouble; + } + else + { + /* If typeCheck() has been called, our operands conform to expectedOperandTypes(), and + * the types are hence either xs:decimals, or xs:anyAtomicType(meaning the static type could + * not be inferred), or empty-sequence(). So we use the union of the two types. The combinations + * could also be wrong.*/ + returnType = t1 | t2; + + /* However, if we're called before typeCheck(), we could potentially have nodes, so we need to make + * sure that the type is at least atomic. */ + if(!BuiltinTypes::xsAnyAtomicType->xdtTypeMatches(returnType)) + returnType = BuiltinTypes::xsAnyAtomicType; + } + + return makeGenericSequenceType(returnType, card); +} + +SequenceType::List ArithmeticExpression::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrOneAtomicType); + result.append(CommonSequenceTypes::ZeroOrOneAtomicType); + return result; +} + +ExpressionVisitorResult::Ptr ArithmeticExpression::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qarithmeticexpression_p.h b/src/xmlpatterns/expr/qarithmeticexpression_p.h new file mode 100644 index 0000000..a1621f7 --- /dev/null +++ b/src/xmlpatterns/expr/qarithmeticexpression_p.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** 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_ArithmeticExpression_H +#define Patternist_ArithmeticExpression_H + +#include "qatomicmathematician_p.h" +#include "qpaircontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Implements arithmetics, such as multiplication and subtraction. + * + * + * Optimizations: there's some operator/value combos that are no ops. For + * instance, 0 + <value>, which is the case of unary plus. We can't compile + * those away early due to that type checks needs to be done but one can + * check for them in compress(). + * + * @see <a href="http://www.w3.org/TR/xpath20/#id-arithmetic">XML Path Language + * (XPath) 2.0, 3.4 Arithmetic Expressions</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class Q_AUTOTEST_EXPORT ArithmeticExpression : public PairContainer + { + public: + ArithmeticExpression(const Expression::Ptr &operand1, + const AtomicMathematician::Operator op, + const Expression::Ptr &operand2); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + + virtual SequenceType::Ptr staticType() const; + virtual SequenceType::List expectedOperandTypes() const; + AtomicMathematician::Operator operatorID() const; + + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + + static Item flexiblyCalculate(const Item &op1, + const AtomicMathematician::Operator op, + const Item &op2, + const AtomicMathematician::Ptr &mather, + const DynamicContext::Ptr &context, + const SourceLocationReflection *const reflection, + const ReportContext::ErrorCode code = ReportContext::XPTY0004, + const bool isCompat = false); + + static AtomicMathematician::Ptr + fetchMathematician(Expression::Ptr &t1, + Expression::Ptr &t2, + const AtomicMathematician::Operator op, + const bool issueError, + const ReportContext::Ptr &context, + const SourceLocationReflection *const reflection, + const ReportContext::ErrorCode code = ReportContext::XPTY0004, + const bool isCompat = false); + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + protected: + + private: + const AtomicMathematician::Operator m_op; + AtomicMathematician::Ptr m_mather; + bool m_isCompat; + }; + + inline AtomicMathematician::Operator ArithmeticExpression::operatorID() const + { + return m_op; + } + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qattributeconstructor.cpp b/src/xmlpatterns/expr/qattributeconstructor.cpp new file mode 100644 index 0000000..fa41afd --- /dev/null +++ b/src/xmlpatterns/expr/qattributeconstructor.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include <QUrl> + +#include "qcommonsequencetypes_p.h" +#include "qnodebuilder_p.h" +#include "qqnamevalue_p.h" + +#include "qattributeconstructor_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +AttributeConstructor::AttributeConstructor(const Expression::Ptr &op1, + const Expression::Ptr &op2) : PairContainer(op1, op2) +{ +} + +QString AttributeConstructor::processValue(const QXmlName name, + const Item &value) +{ + if(!value) + return QString(); + else if(name == QXmlName(StandardNamespaces::xml, StandardLocalNames::id)) + return value.stringValue().simplified(); + else + return value.stringValue(); +} + +Item AttributeConstructor::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + const Item nameItem(m_operand1->evaluateSingleton(context)); + const Item content(m_operand2->evaluateSingleton(context)); + + const QXmlName name(nameItem.as<QNameValue>()->qName()); + const QString value(processValue(name, content)); + const NodeBuilder::Ptr nodeBuilder(context->nodeBuilder(QUrl())); + + nodeBuilder->attribute(name, QStringRef(&value)); + + const QAbstractXmlNodeModel::Ptr nm(nodeBuilder->builtDocument()); + context->addNodeModel(nm); + return nm->root(QXmlNodeModelIndex()); +} + +void AttributeConstructor::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + QAbstractXmlReceiver *const receiver = context->outputReceiver(); + const Item nameItem(m_operand1->evaluateSingleton(context)); + + const Item content(m_operand2->evaluateSingleton(context)); + const QXmlName name(nameItem.as<QNameValue>()->qName()); + const QString value(processValue(name, content)); + + receiver->attribute(name, QStringRef(&value)); +} + +SequenceType::Ptr AttributeConstructor::staticType() const +{ + return CommonSequenceTypes::ExactlyOneAttribute; +} + +SequenceType::List AttributeConstructor::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ExactlyOneQName); + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +Expression::Properties AttributeConstructor::properties() const +{ + return DisableElimination | IsNodeConstructor; +} + +ExpressionVisitorResult::Ptr +AttributeConstructor::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID AttributeConstructor::id() const +{ + return IDAttributeConstructor; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qattributeconstructor_p.h b/src/xmlpatterns/expr/qattributeconstructor_p.h new file mode 100644 index 0000000..055ad7f --- /dev/null +++ b/src/xmlpatterns/expr/qattributeconstructor_p.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** 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_AttributeConstructor_H +#define Patternist_AttributeConstructor_H + +#include "qpaircontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Constructs an element node. This covers both computed and directly constructed + * element nodes. + * + * @see <a href="http://www.w3.org/TR/xquery/#id-constructors">XQuery + * 1.0: An XML Query Language, 3.7 Constructors</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class AttributeConstructor : public PairContainer + { + public: + AttributeConstructor(const Expression::Ptr &operand1, + const Expression::Ptr &operand2); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + virtual SequenceType::Ptr staticType() const; + + /** + * The first operand must be exactly one @c xs:QName, and the second + * argument can be zero or more items. + */ + virtual SequenceType::List expectedOperandTypes() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + /** + * @returns always IDAttributeConstructor. + */ + virtual ID id() const; + + virtual Properties properties() const; + + private: + static inline QString processValue(const QXmlName name, + const Item &value); + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qattributenamevalidator.cpp b/src/xmlpatterns/expr/qattributenamevalidator.cpp new file mode 100644 index 0000000..1625bc1 --- /dev/null +++ b/src/xmlpatterns/expr/qattributenamevalidator.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qbuiltintypes_p.h" +#include "qcommonnamespaces_p.h" +#include "qcommonsequencetypes_p.h" +#include "qpatternistlocale_p.h" +#include "qqnamevalue_p.h" +#include "qatomicstring_p.h" + +#include "qattributenamevalidator_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +AttributeNameValidator::AttributeNameValidator(const Expression::Ptr &source) : SingleContainer(source) +{ +} + +Item AttributeNameValidator::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + const Item name(m_operand->evaluateSingleton(context)); + const QXmlName qName(name.as<QNameValue>()->qName()); + + if(qName.namespaceURI() == StandardNamespaces::xmlns) + { + context->error(QtXmlPatterns::tr("The namespace URI in the name for a " + "computed attribute cannot be %1.") + .arg(formatURI(CommonNamespaces::XMLNS)), + ReportContext::XQDY0044, this); + return Item(); /* Silence warning. */ + } + else if(qName.namespaceURI() == StandardNamespaces::empty && + qName.localName() == StandardLocalNames::xmlns) + { + context->error(QtXmlPatterns::tr("The name for a computed attribute " + "cannot have the namespace URI %1 " + "with the local name %2.") + .arg(formatURI(CommonNamespaces::XMLNS)) + .arg(formatKeyword("xmlns")), + ReportContext::XQDY0044, this); + return Item(); /* Silence warning. */ + } + else if(!qName.hasPrefix() && qName.hasNamespace()) + { + return Item(QNameValue::fromValue(context->namePool(), + QXmlName(qName.namespaceURI(), qName.localName(), StandardPrefixes::ns0))); + } + else + return name; +} + +SequenceType::Ptr AttributeNameValidator::staticType() const +{ + return m_operand->staticType(); +} + +SequenceType::List AttributeNameValidator::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ExactlyOneQName); + return result; +} + +ExpressionVisitorResult::Ptr AttributeNameValidator::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qattributenamevalidator_p.h b/src/xmlpatterns/expr/qattributenamevalidator_p.h new file mode 100644 index 0000000..ddf05ec --- /dev/null +++ b/src/xmlpatterns/expr/qattributenamevalidator_p.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** 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_AttributeNameValidator_H +#define Patternist_AttributeNameValidator_H + +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Ensures the lexical space of the string value of the Item returned + * from its child Expression is an NCName. Also possibly changes the name + * by generating a prefix if one is needed. + * + * @note It doesn't actually construct an @c xs:NCName. It only ensures the lexical + * space is an @c NCName. The atomic value can be of any string type, such as @c xs:untypedAtomic + * of @c xs:string. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class AttributeNameValidator : public SingleContainer + { + public: + AttributeNameValidator(const Expression::Ptr &source); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &) const; + + virtual SequenceType::List expectedOperandTypes() const; + + /** + * @returns the static type of its operand. This is returned as opposed + * CommonSequenceTypes::ExactlyOneQName, since the operand might return a subtype + * of @c xs:QName. + */ + virtual SequenceType::Ptr staticType() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qaxisstep.cpp b/src/xmlpatterns/expr/qaxisstep.cpp new file mode 100644 index 0000000..40fe694 --- /dev/null +++ b/src/xmlpatterns/expr/qaxisstep.cpp @@ -0,0 +1,247 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qitemmappingiterator_p.h" +#include "qgenericsequencetype_p.h" +#include "qparentnodeaxis_p.h" + +#include "qaxisstep_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +namespace QPatternist +{ + /** + * This operator is needed for the s_whenAxisNodeKindEmpty array. The @c int constructors + * ensure we invoke another operator| such that we don't get an infinite loop. + */ + static inline QXmlNodeModelIndex::NodeKind operator|(const QXmlNodeModelIndex::NodeKind &op1, const QXmlNodeModelIndex::NodeKind &op2) + { + return QXmlNodeModelIndex::NodeKind(int(op1) | int(op2)); + } +} + +/** + * @note The order is significant. It is of the same order as the values in QXmlNodeModelIndex::Axis is declared. + */ +const QXmlNodeModelIndex::NodeKind AxisStep::s_whenAxisNodeKindEmpty[] = +{ + QXmlNodeModelIndex::Attribute|QXmlNodeModelIndex::Text|QXmlNodeModelIndex::ProcessingInstruction|QXmlNodeModelIndex::Comment|QXmlNodeModelIndex::Namespace, // child; + QXmlNodeModelIndex::Attribute|QXmlNodeModelIndex::Text|QXmlNodeModelIndex::ProcessingInstruction|QXmlNodeModelIndex::Comment|QXmlNodeModelIndex::Namespace, // descendant; + QXmlNodeModelIndex::Document|QXmlNodeModelIndex::Attribute|QXmlNodeModelIndex::Text|QXmlNodeModelIndex::ProcessingInstruction|QXmlNodeModelIndex::Comment|QXmlNodeModelIndex::Namespace,// attribute; + QXmlNodeModelIndex::NodeKind(0), // self; + QXmlNodeModelIndex::NodeKind(0), // descendant-or-self; + QXmlNodeModelIndex::Document|QXmlNodeModelIndex::Attribute|QXmlNodeModelIndex::Text|QXmlNodeModelIndex::ProcessingInstruction|QXmlNodeModelIndex::Comment|QXmlNodeModelIndex::Namespace, // namespace; + QXmlNodeModelIndex::Document, // following; + QXmlNodeModelIndex::Document, // parent; + QXmlNodeModelIndex::Document, // ancestor + QXmlNodeModelIndex::Document|QXmlNodeModelIndex::Attribute|QXmlNodeModelIndex::Namespace, // preceding-sibling; + QXmlNodeModelIndex::Document|QXmlNodeModelIndex::Attribute|QXmlNodeModelIndex::Namespace, // following-sibling; + QXmlNodeModelIndex::Document, // preceding; + QXmlNodeModelIndex::NodeKind(0) // ancestor-or-self; +}; + +bool AxisStep::isAlwaysEmpty(const QXmlNodeModelIndex::Axis axis, const QXmlNodeModelIndex::NodeKind nodeKind) +{ + return (s_whenAxisNodeKindEmpty[(1 >> axis) - 1] & nodeKind) != 0; +} + +AxisStep::AxisStep(const QXmlNodeModelIndex::Axis a, + const ItemType::Ptr &nt) : m_axis(a), + m_nodeTest(nt) +{ + Q_ASSERT(m_nodeTest); + Q_ASSERT_X(BuiltinTypes::node->xdtTypeMatches(m_nodeTest), Q_FUNC_INFO, + "We assume we're a node type."); +} + +Item AxisStep::mapToItem(const QXmlNodeModelIndex &node, + const DynamicContext::Ptr &context) const +{ + Q_ASSERT(!node.isNull()); + Q_ASSERT(Item(node).isNode()); + Q_ASSERT(Item(node)); + Q_UNUSED(context); + + if(m_nodeTest->itemMatches(Item(node))) + return Item(node); + else + return Item(); +} + +Item::Iterator::Ptr AxisStep::evaluateSequence(const DynamicContext::Ptr &context) const +{ + /* If we don't have a focus, it's either a bug or our parent isn't a Path + * that have advanced the focus iterator. Hence, attempt to advance the focus on our own. */ + if(!context->contextItem()) + context->focusIterator()->next(); + + Q_ASSERT(context->contextItem()); + + const QXmlNodeModelIndex::Iterator::Ptr source(context->contextItem().asNode().iterate(m_axis)); + + return makeItemMappingIterator<Item>(ConstPtr(this), source, context); +} + +Item AxisStep::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + /* If we don't have a focus, it's either a bug or our parent isn't a Path + * that have advanced the focus iterator. Hence, attempt to advance the focus on our own. */ + if(!context->contextItem()) + context->focusIterator()->next(); + + Q_ASSERT(context->contextItem()); + + const QXmlNodeModelIndex::Iterator::Ptr it(context->contextItem().asNode().iterate(m_axis)); + QXmlNodeModelIndex next(it->next()); + + while(!next.isNull()) + { + const Item candidate(mapToItem(next, context)); + + if(candidate) + return candidate; + else + next = it->next(); + }; + + return Item(); +} + +Expression::Ptr AxisStep::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + if(m_axis == QXmlNodeModelIndex::AxisParent && *m_nodeTest == *BuiltinTypes::node) + { + /* We only rewrite parent::node() to ParentNodeAxis. */ + return rewrite(Expression::Ptr(new ParentNodeAxis()), context)->typeCheck(context, reqType); + } + /* TODO temporarily disabled + else if(isAlwaysEmpty(m_axis, static_cast<const AnyNodeType *>(m_nodeTest.data())->nodeKind())) + return EmptySequence::create(this, context); + */ + else + return EmptyContainer::typeCheck(context, reqType); +} + +SequenceType::Ptr AxisStep::staticType() const +{ + Cardinality cardinality; + + if(m_axis == QXmlNodeModelIndex::AxisSelf || m_axis == QXmlNodeModelIndex::AxisParent) + cardinality = Cardinality::zeroOrOne(); + else + cardinality = Cardinality::zeroOrMore(); + + return makeGenericSequenceType(m_nodeTest, + cardinality); +} + +SequenceType::List AxisStep::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreNodes); + return result; +} + +Expression::Properties AxisStep::properties() const +{ + return RequiresContextItem | DisableElimination; +} + +ItemType::Ptr AxisStep::expectedContextItemType() const +{ + return BuiltinTypes::node; +} + +ExpressionVisitorResult::Ptr AxisStep::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QXmlNodeModelIndex::Axis AxisStep::axis() const +{ + return m_axis; +} + +QString AxisStep::axisName(const QXmlNodeModelIndex::Axis axis) +{ + const char *result = 0; + + switch(axis) + { + /* These must not be translated. */ + case QXmlNodeModelIndex::AxisAncestorOrSelf: result = "ancestor-or-self"; break; + case QXmlNodeModelIndex::AxisAncestor: result = "ancestor"; break; + case QXmlNodeModelIndex::AxisAttributeOrTop: result = "attribute-or-top"; break; + case QXmlNodeModelIndex::AxisAttribute: result = "attribute"; break; + case QXmlNodeModelIndex::AxisChildOrTop: result = "child-or-top"; break; + case QXmlNodeModelIndex::AxisChild: result = "child"; break; + case QXmlNodeModelIndex::AxisDescendantOrSelf: result = "descendant-or-self"; break; + case QXmlNodeModelIndex::AxisDescendant: result = "descendant"; break; + case QXmlNodeModelIndex::AxisFollowing: result = "following"; break; + case QXmlNodeModelIndex::AxisFollowingSibling: result = "following-sibling"; break; + case QXmlNodeModelIndex::AxisNamespace: result = "namespace"; break; + case QXmlNodeModelIndex::AxisParent: result = "parent"; break; + case QXmlNodeModelIndex::AxisPreceding: result = "preceding"; break; + case QXmlNodeModelIndex::AxisPrecedingSibling: result = "preceding-sibling"; break; + case QXmlNodeModelIndex::AxisSelf: result = "self"; break; + } + + Q_ASSERT_X(result, Q_FUNC_INFO, "An unknown axis type was apparently encountered."); + return QString::fromLatin1(result); +} + +PatternPriority AxisStep::patternPriority() const +{ + return static_cast<const AnyNodeType *>(m_nodeTest.data())->patternPriority(); +} + +Expression::ID AxisStep::id() const +{ + return IDAxisStep; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qaxisstep_p.h b/src/xmlpatterns/expr/qaxisstep_p.h new file mode 100644 index 0000000..8f2ae27 --- /dev/null +++ b/src/xmlpatterns/expr/qaxisstep_p.h @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** 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_AxisStep_H +#define Patternist_AxisStep_H + +#include "qemptycontainer_p.h" +#include "qitem_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A step in a path expression that with an axis and a node test evaluates + * to a sequence of nodes from the context item. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class Q_AUTOTEST_EXPORT AxisStep : public EmptyContainer + { + public: + AxisStep(const QXmlNodeModelIndex::Axis axis, + const ItemType::Ptr &nodeTest); + + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &) const; + virtual Item evaluateSingleton(const DynamicContext::Ptr &) const; + + /** + * Returns @p node if it matches the node test this step is using, otherwise @c null. + */ + inline Item mapToItem(const QXmlNodeModelIndex &node, + const DynamicContext::Ptr &context) const; + + virtual SequenceType::List expectedOperandTypes() const; + virtual SequenceType::Ptr staticType() const; + + /** + * Rewrites to ParentNodeAxis, if possible. + */ + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + + /** + * @returns always BuiltinTypes::node; + */ + virtual ItemType::Ptr expectedContextItemType() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + virtual Properties properties() const; + + /** + * @returns the axis this step is using. + */ + QXmlNodeModelIndex::Axis axis() const; + + /** + * @returns the node test this step is using. + */ + inline ItemType::Ptr nodeTest() const + { + return m_nodeTest; + } + + void setNodeTest(const ItemType::Ptr &nev) + { + m_nodeTest = nev; + } + + /** + * @short Prints the EBNF name corresponding to @p axis. + * + * For instance, for QXmlNodeModelIndex::Child, "child" is returned. + * + * Apart from being used in this class, it is used in the SDK. + */ + static QString axisName(const QXmlNodeModelIndex::Axis axis); + + virtual ID id() const; + virtual PatternPriority patternPriority() const; + + inline void setAxis(const QXmlNodeModelIndex::Axis newAxis); + + private: + typedef QExplicitlySharedDataPointer<const AxisStep> ConstPtr; + + static const QXmlNodeModelIndex::NodeKind s_whenAxisNodeKindEmpty[]; + + /** + * @returns @c true when the axis @p axis and a node test testing node of + * type @p nodeKind always produces an empty sequence. One such example + * is <tt>attribute::comment()</tt>. + */ + static bool isAlwaysEmpty(const QXmlNodeModelIndex::Axis axis, + const QXmlNodeModelIndex::NodeKind nodeKind); + + /** + * The reason this variable is mutable, is that in the case of XSL-T patterns, + * we do quite some reordering. + */ + QXmlNodeModelIndex::Axis m_axis; + ItemType::Ptr m_nodeTest; + }; + + void AxisStep::setAxis(const QXmlNodeModelIndex::Axis newAxis) + { + m_axis = newAxis; + } + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qcachecells_p.h b/src/xmlpatterns/expr/qcachecells_p.h new file mode 100644 index 0000000..ec9ea8e --- /dev/null +++ b/src/xmlpatterns/expr/qcachecells_p.h @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** 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_CacheCells_H +#define Patternist_CacheCells_H + +#include <QList> +#include <QVector> + +#include "qitem_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short Represents a cache entry for a single Item, + * as opposed to for a sequence of items. + * + * A characteristic of the ItemCacheCell is that it has two states: + * either its full or it's not, since it only deals with a single + * item. + * + * Remember that cachedItem doesn't tell the state of the ItemCacheCell. + * For instance, it can have a null pointer, the empty sequence, and that + * can be the value of its cache. + * + * @author Frans Englich <frans.englich@nokia.com> + */ + class ItemCacheCell + { + public: + typedef QList<ItemCacheCell> List; + typedef QVector<ItemCacheCell> Vector; + enum CacheState + { + Full, + Empty + }; + + inline ItemCacheCell() : cacheState(Empty) + { + } + + Item cachedItem; + CacheState cacheState; + }; + + /** + * @short Represents a cache entry for a sequence of items. + * + * As opposed to ItemCacheCell, ItemSequenceCacheCell can be partially + * populated: e.g, four items is in the cache while three remains in the + * source. For that reason ItemSequenceCacheCell in addition to the source + * also carried an QAbstractXmlForwardIterator which is the source, such + * that it can continue to populate the cache when it runs out. + * + * @author Frans Englich <frans.englich@nokia.com> + */ + class ItemSequenceCacheCell + { + public: + typedef QList<ItemSequenceCacheCell> List; + typedef QVector<ItemSequenceCacheCell> Vector; + + enum CacheState + { + Full, + Empty, + PartiallyPopulated + }; + + inline ItemSequenceCacheCell() : cacheState(Empty) + , inUse(false) + { + } + + Item::List cachedItems; + Item::Iterator::Ptr sourceIterator; + CacheState cacheState; + /** + * In XSL-T, we can have circularity which we cannot detect statically. + * For instance, a global variable invokes a template, and the template + * uses the variable. We can't detect that, because we can't figure out + * what template will be invoked. + * + * For solution we have this toggle, which is set temporarily on the + * cell such that EvaluationCache can detect whether it's trashing + * itself. + * + * One might think that it would be sufficient to flag usage of the + * variable in an arbitrary template, but that would also flag valid + * cases. + */ + bool inUse; + }; +} + +Q_DECLARE_TYPEINFO(QPatternist::ItemCacheCell, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QPatternist::ItemSequenceCacheCell, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qcallsite.cpp b/src/xmlpatterns/expr/qcallsite.cpp new file mode 100644 index 0000000..7137bb4 --- /dev/null +++ b/src/xmlpatterns/expr/qcallsite.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcallsite_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +CallSite::CallSite(const QXmlName &name) : m_isRecursive(false) + , m_name(name) +{ +} + +QXmlName CallSite::name() const +{ + return m_name; +} + +bool CallSite::isRecursive() const +{ + return m_isRecursive; +} + +void CallSite::setIsRecursive(const bool value) +{ + m_isRecursive = value; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qcallsite_p.h b/src/xmlpatterns/expr/qcallsite_p.h new file mode 100644 index 0000000..6c0013c --- /dev/null +++ b/src/xmlpatterns/expr/qcallsite_p.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** 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_CallSite_H +#define Patternist_CallSite_H + +#include "qunlimitedcontainer_p.h" +#include "qcalltargetdescription_p.h" +#include "qxmlname.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Abstract base-class for Expression instances that are callsites + * to other components, such as templates or user functions. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + * @since 4.5 + */ + class CallSite : public UnlimitedContainer + { + public: + QXmlName name() const; + bool isRecursive() const; + void setIsRecursive(const bool value); + + /** + * Called in the earliest stages of the compilation process. @p sign can + * be any function signature for a user declared function. If @p sign + * matches this UserFunctionCallsite, it means the UserFunction represented + * by @p sign is recursive and that this UserFunctionCallsite should take + * appropriate measures. + * + * @returns @c true if is recursive, otherwise @c false + */ + virtual bool configureRecursion(const CallTargetDescription::Ptr &sign) = 0; + + /** + * @short Returns the body of the function/template/component that is + * being called. + */ + virtual Expression::Ptr body() const = 0; + + virtual CallTargetDescription::Ptr callTargetDescription() const = 0; + + protected: + CallSite(const QXmlName &name = QXmlName()); + + private: + Q_DISABLE_COPY(CallSite) + bool m_isRecursive; + const QXmlName m_name; + }; +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qcalltargetdescription.cpp b/src/xmlpatterns/expr/qcalltargetdescription.cpp new file mode 100644 index 0000000..0e14469 --- /dev/null +++ b/src/xmlpatterns/expr/qcalltargetdescription.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcallsite_p.h" + +#include "qcalltargetdescription_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +CallTargetDescription::CallTargetDescription(const QXmlName &name) : m_name(name) +{ + Q_ASSERT(!m_name.isNull()); +} + +QXmlName CallTargetDescription::name() const +{ + return m_name; +} + +void CallTargetDescription::checkArgumentsCircularity(CallTargetDescription::List &signList, + const Expression::Ptr callsite) +{ + /* Check the arguments. */ + const Expression::List ops(callsite->operands()); + const Expression::List::const_iterator end(ops.constEnd()); + Expression::List::const_iterator it(ops.constBegin()); + + for(; it != end; ++it) + checkCallsiteCircularity(signList, *it); +} + +void CallTargetDescription::checkCallsiteCircularity(CallTargetDescription::List &signList, + const Expression::Ptr expr) +{ + Q_ASSERT(expr); + + if(expr->is(Expression::IDUserFunctionCallsite)) + { + CallTargetDescription::List::const_iterator it(signList.constBegin()); + const CallTargetDescription::List::const_iterator end(signList.constEnd()); + CallSite *const callsite = static_cast<CallSite *>(expr.data()); + + for(; it != end; ++it) + { + if(callsite->configureRecursion(*it)) + { + /* A callsite inside the function body to the function. This user function + * is recursive if it's to the same function, in other words. Which it was + * if configureRecursion() returned true. */ + + /* Now we continue and check the arguments of the callsite. That is, the arguments. + * This catches for instance local:foo(local:foo(3)). */ + checkArgumentsCircularity(signList, expr); + return; + } + } + /* Check the body of the function so this callsite isn't "indirectly" a + * recursive call to the function we're checking. XQTS test case + * default_namespace-011 is an example of this. */ + signList.append(callsite->callTargetDescription()); + checkCallsiteCircularity(signList, callsite->body()); + } + + checkArgumentsCircularity(signList, expr); /* We're done in this case. */ +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qcalltargetdescription_p.h b/src/xmlpatterns/expr/qcalltargetdescription_p.h new file mode 100644 index 0000000..ac614be --- /dev/null +++ b/src/xmlpatterns/expr/qcalltargetdescription_p.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** 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_CallTargetDescription_H +#define Patternist_CallTargetDescription_H + +template<typename Key, typename Value> class QHash; +template<typename T> class QList; + +#include <QSharedData> + +#include "qexpression_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + class CallSite; + + /** + * @short Contains metadata for a callable component, such as a function or + * template. + * + * CallTargetDescription can be used directly and is so for templates, but + * can also be sub-classed which FunctionSignature do. + * + * @ingroup Patternist_expr + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_AUTOTEST_EXPORT CallTargetDescription : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer<CallTargetDescription> Ptr; + typedef QList<Ptr> List; + + CallTargetDescription(const QXmlName &name); + + /** + * The function's name. For example, the name of the signature + * <tt>fn:string() as xs:string</tt> is <tt>fn:string</tt>. + */ + QXmlName name() const; + + /** + * Flags callsites to be aware of their recursion by calling + * UserFunctionCallsite::configureRecursion(), if that is the case. + * + * @note We pass @p expr by value here intentionally. + */ + static void checkCallsiteCircularity(CallTargetDescription::List &signList, + const Expression::Ptr expr); + private: + /** + * Helper function for checkCallsiteCircularity(). If C++ allowed it, + * it would have been local to it. + */ + static void checkArgumentsCircularity(CallTargetDescription::List &signList, + const Expression::Ptr callsite); + + Q_DISABLE_COPY(CallTargetDescription) + const QXmlName m_name; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif + diff --git a/src/xmlpatterns/expr/qcalltemplate.cpp b/src/xmlpatterns/expr/qcalltemplate.cpp new file mode 100644 index 0000000..f16ffcf --- /dev/null +++ b/src/xmlpatterns/expr/qcalltemplate.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" + +#include "qcalltemplate_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +CallTemplate::CallTemplate(const QXmlName &name, + const WithParam::Hash &withParams) : TemplateInvoker(withParams, name) +{ +} + +Item::Iterator::Ptr CallTemplate::evaluateSequence(const DynamicContext::Ptr &context) const +{ + Q_ASSERT(m_template); + return m_template->body->evaluateSequence(m_template->createContext(this, context, true)); +} + +bool CallTemplate::evaluateEBV(const DynamicContext::Ptr &context) const +{ + Q_ASSERT(m_template); + return m_template->body->evaluateEBV(m_template->createContext(this, context, true)); +} + +void CallTemplate::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + Q_ASSERT(m_template); + m_template->body->evaluateToSequenceReceiver(m_template->createContext(this, context, true)); +} + +Expression::Ptr CallTemplate::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + /* Check XTSE0680, that every @c xsl:with-param has a corresponding @c + * xsl:param declaration. */ + { + const WithParam::Hash::const_iterator end(m_withParams.constEnd()); + + for(WithParam::Hash::const_iterator it(m_withParams.constBegin()); + it != end; + ++it) + { + if(!VariableDeclaration::contains(m_template->templateParameters, it.value()->name())) + Template::raiseXTSE0680(context, it.value()->name(), this); + } + } + + const Expression::Ptr me(TemplateInvoker::typeCheck(context, reqType)); + + const VariableDeclaration::List args(m_template->templateParameters); + const VariableDeclaration::List::const_iterator end(args.constEnd()); + VariableDeclaration::List::const_iterator it(args.constBegin()); + + for(; it != end; ++it) + { + // TODO + Q_ASSERT((*it)->sequenceType); + } + + return me; +} + +Expression::Properties CallTemplate::properties() const +{ + Q_ASSERT(!m_template || m_template->body); + + /* We may be called before our m_template is resolved, namely when we're + * the body of a variable. In that case querytransformparser.ypp will + * manually call TypeChecker::applyFunctionConversion(), which is before + * ExpressionFactory::createExpression() has resolved us. */ + if(m_template && !isRecursive()) + return m_template->properties(); + else + return Properties(); +} + +Expression::Properties CallTemplate::dependencies() const +{ + if(m_template && !isRecursive()) + return m_template->dependencies(); + else + return Properties(); +} + +SequenceType::Ptr CallTemplate::staticType() const +{ + return CommonSequenceTypes::ZeroOrMoreItems; +} + +ExpressionVisitorResult::Ptr CallTemplate::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +bool CallTemplate::configureRecursion(const CallTargetDescription::Ptr &sign) +{ + Q_UNUSED(sign); + return false; +} + +Expression::Ptr CallTemplate::body() const +{ + return m_template->body; +} + +CallTargetDescription::Ptr CallTemplate::callTargetDescription() const +{ + return CallTargetDescription::Ptr(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qcalltemplate_p.h b/src/xmlpatterns/expr/qcalltemplate_p.h new file mode 100644 index 0000000..df67121 --- /dev/null +++ b/src/xmlpatterns/expr/qcalltemplate_p.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** 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_CallTemplate_H +#define Patternist_CallTemplate_H + +#include "qcallsite_p.h" +#include "qtemplateinvoker_p.h" +#include "qtemplate_p.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Implements @c xsl:call-template. + * + * @since 4.5 + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class CallTemplate : public TemplateInvoker + { + public: + typedef QExplicitlySharedDataPointer<CallTemplate> Ptr; + + CallTemplate(const QXmlName &name, + const WithParam::Hash &withParams); + + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + virtual SequenceType::Ptr staticType() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual Properties properties() const; + virtual Properties dependencies() const; + + /** + * This is a bit complicated by that we have two required types, one + * specified by @c xsl:param in the template declaration, and one on @c + * xsl:with-param. + * + * @see UserFunctionCallsite::expectedOperandTypes() + * @see <a href="http://www.w3.org/TR/xslt20/#with-param">XSL + * Transformations (XSLT) Version 2.0, 10.1.1 Passing Parameters to Templates</a> + */ + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + + + inline void setTemplate(const Template::Ptr &templ) + { + m_template = templ; + } + + virtual bool configureRecursion(const CallTargetDescription::Ptr &sign); + virtual Expression::Ptr body() const; + virtual CallTargetDescription::Ptr callTargetDescription() const; + private: + Template::Ptr m_template; + }; +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qcastableas.cpp b/src/xmlpatterns/expr/qcastableas.cpp new file mode 100644 index 0000000..65b5305 --- /dev/null +++ b/src/xmlpatterns/expr/qcastableas.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qatomictype_p.h" +#include "qitem_p.h" +#include "qboolean_p.h" +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qcommonvalues_p.h" +#include "qliteral_p.h" + +#include "qcastableas_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +CastableAs::CastableAs(const Expression::Ptr &operand, + const SequenceType::Ptr &tType) : SingleContainer(operand), + m_targetType(tType) +{ + Q_ASSERT(tType); + Q_ASSERT(!tType->cardinality().allowsMany()); + Q_ASSERT(tType->itemType()->isAtomicType()); +} + +bool CastableAs::evaluateEBV(const DynamicContext::Ptr &context) const +{ + Item item; + + if(m_operand->staticType()->cardinality().allowsMany()) + { + const Item::Iterator::Ptr it(m_operand->evaluateSequence(context)); + item = it->next(); + + if(it->next()) + return false; + } + else + item = m_operand->evaluateSingleton(context); + + if(item) + return !cast(item, context).as<AtomicValue>()->hasError(); + else + return m_targetType->cardinality().allowsEmpty(); +} + +Expression::Ptr CastableAs::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr me(SingleContainer::compress(context)); + + if(me != this) /* We already managed to const fold, how convenient. */ + return me; + + const AtomicType::Ptr t(m_targetType->itemType()); + + const SequenceType::Ptr opType(m_operand->staticType()); + + /* Casting to these always succeeds, assuming the cardinality also matches, + * although the cardinality can fail. */ + if(( *t == *BuiltinTypes::xsString + || *t == *BuiltinTypes::xsUntypedAtomic + || *t == *opType->itemType()) + &&(m_targetType->cardinality().isMatch(opType->cardinality()))) + { + return wrapLiteral(CommonValues::BooleanTrue, context, this); + } + else + return me; +} + +Expression::Ptr CastableAs::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + checkTargetType(context); + const Expression::Ptr me(SingleContainer::typeCheck(context, reqType)); + + return me; + if(BuiltinTypes::xsQName->xdtTypeMatches(m_targetType->itemType())) + { + const SequenceType::Ptr seqt(m_operand->staticType()); + /* We can cast a string literal, an xs:QName value, and an + * empty sequence(if empty is allowed), to xs:QName. */ + if(m_operand->is(IDStringValue) || + BuiltinTypes::xsQName->xdtTypeMatches(seqt->itemType()) || + (*seqt->itemType() == *CommonSequenceTypes::Empty && m_targetType->cardinality().allowsEmpty())) + { + return wrapLiteral(CommonValues::BooleanTrue, context, this)->typeCheck(context, reqType); + } + else + return wrapLiteral(CommonValues::BooleanFalse, context, this)->typeCheck(context, reqType); + } + else + { + /* Let the CastingPlatform look up its AtomicCaster. */ + prepareCasting(context, m_operand->staticType()->itemType()); + + return me; + } +} + +SequenceType::List CastableAs::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreAtomicTypes); + return result; +} + +SequenceType::Ptr CastableAs::staticType() const +{ + return CommonSequenceTypes::ExactlyOneBoolean; +} + +ExpressionVisitorResult::Ptr CastableAs::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qcastableas_p.h b/src/xmlpatterns/expr/qcastableas_p.h new file mode 100644 index 0000000..fe216b1 --- /dev/null +++ b/src/xmlpatterns/expr/qcastableas_p.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** 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_CastableAs_H +#define Patternist_CastableAs_H + +#include "qsinglecontainer_p.h" +#include "qcastingplatform_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short Implements XPath 2.0's <tt>castable as</tt> expression. + * + * @see <a href="http://www.w3.org/TR/xpath20/#id-castable">XML Path Language + * (XPath) 2.0, 3.10.3 Castable</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class CastableAs : public SingleContainer, + public CastingPlatform<CastableAs, false> + { + public: + CastableAs(const Expression::Ptr &operand, + const SequenceType::Ptr &targetType); + + virtual bool evaluateEBV(const DynamicContext::Ptr &) const; + + /** + * Overridden to const fold to @c true when the target type + * is a type which casting to always succeeds. This is + * the type identical to the target type, <tt>xs:string</tt>, + * and <tt>xs:untypedAtomic</tt>. + */ + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + + virtual SequenceType::List expectedOperandTypes() const; + virtual SequenceType::Ptr staticType() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + inline ItemType::Ptr targetType() const + { + return m_targetType->itemType(); + } + + private: + const SequenceType::Ptr m_targetType; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qcastas.cpp b/src/xmlpatterns/expr/qcastas.cpp new file mode 100644 index 0000000..741d052 --- /dev/null +++ b/src/xmlpatterns/expr/qcastas.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qitem_p.h" +#include "qbuiltintypes_p.h" +#include "qcardinalityverifier_p.h" +#include "qcommonsequencetypes_p.h" +#include "qemptysequence_p.h" +#include "qgenericsequencetype_p.h" +#include "qliteral_p.h" +#include "qpatternistlocale_p.h" +#include "qnamespaceresolver_p.h" +#include "qqnameconstructor_p.h" +#include "qqnamevalue_p.h" +#include "qatomicstring_p.h" +#include "qvalidationerror_p.h" + +#include "qcastas_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +CastAs::CastAs(const Expression::Ptr &source, + const SequenceType::Ptr &tType) : SingleContainer(source), + m_targetType(tType) +{ + Q_ASSERT(source); + Q_ASSERT(tType); + Q_ASSERT(!tType->cardinality().allowsMany()); + Q_ASSERT(tType->itemType()->isAtomicType()); +} + +Item CastAs::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + Q_ASSERT(context); + const Item val(m_operand->evaluateSingleton(context)); + + if(val) + return cast(val, context); + else + { + /* No item supplied, let's handle the cardinality part. */ + + if(m_targetType->cardinality().allowsEmpty()) + return Item(); + else + { + Q_ASSERT(context); + context->error(QtXmlPatterns::tr("Type error in cast, expected %1, " + "received %2.") + .arg(formatType(Cardinality::exactlyOne())) + .arg(formatType(Cardinality::empty())), + ReportContext::XPTY0004, this); + return Item(); + } + } +} + +Expression::Ptr CastAs::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + checkTargetType(context); + const SequenceType::Ptr seqt(m_operand->staticType()); + ItemType::Ptr t(seqt->itemType()); + + /* Special case xs:QName */ + if(BuiltinTypes::xsQName->xdtTypeMatches(m_targetType->itemType())) + { + /* Ok, We're casting to xs:QName. */ + if(m_operand->is(IDStringValue)) /* A valid combination, let's do the cast. */ + return castToQName(context)->typeCheck(context, reqType); + else if(BuiltinTypes::xsQName->xdtTypeMatches(t)) + return m_operand->typeCheck(context, reqType); + else if(seqt->cardinality().isEmpty() && m_targetType->cardinality().allowsEmpty()) + return EmptySequence::create(this, context); + else if(!(seqt->cardinality().isEmpty() && !m_targetType->cardinality().allowsEmpty())) + { + context->error(QtXmlPatterns::tr("When casting to %1 or types " + "derived from it, the source " + "value must be of the same type, " + "or it must be a string literal. " + "Type %2 is not allowed.") + .arg(formatType(context->namePool(), BuiltinTypes::xsQName)) + .arg(formatType(context->namePool(), seqt)), + ReportContext::XPTY0004, this); + return Expression::Ptr(this); + } + } + + const Expression::Ptr me(SingleContainer::typeCheck(context, reqType)); + /* Type may have changed, such as that atomization has been applied. */ + t = m_operand->staticType()->itemType(); + + if(m_targetType->itemType()->xdtTypeMatches(t) && + !BuiltinTypes::xsDayTimeDuration->xdtTypeMatches(t) && + !BuiltinTypes::xsYearMonthDuration->xdtTypeMatches(t)) + { /* At least casting is superflorous. */ + if(m_operand->staticType()->cardinality().isMatch(m_targetType->cardinality())) + return m_operand; /* The whole cast expression is redundant. */ + else + { /* Only cardinality check is needed, rewrite to CardinalityVerifier. */ + return Expression::Ptr(new CardinalityVerifier(m_operand, + m_targetType->cardinality(), + ReportContext::FORG0001)); + } + } + + /* Let the CastingPlatform look up its AtomicCaster. */ + prepareCasting(context, t); + + return me; +} + +Expression::Ptr CastAs::compress(const StaticContext::Ptr &context) +{ + /* Simplify casts to itself. */ + if(*m_targetType->itemType() == *m_operand->staticType()->itemType()) + return m_operand->compress(context); + else + return SingleContainer::compress(context); +} + +Expression::Ptr CastAs::castToQName(const StaticContext::Ptr &context) const +{ + /* Apply the whitespace facet by calling trimmed(). */ + /* We can assume m_operand is an Expression because this is a requirement + * for casting to xs:QName. */ + const QString lexQName(m_operand->as<Literal>()->item().as<AtomicValue>()->stringValue().trimmed()); + + const QXmlName + expName(QNameConstructor::expandQName<StaticContext::Ptr, + ReportContext::FORG0001, + ReportContext::FONS0004>(lexQName, + context, + context->namespaceBindings(), this)); + return wrapLiteral(toItem(QNameValue::fromValue(context->namePool(), expName)), context, this); +} + +SequenceType::Ptr CastAs::staticType() const +{ + if(m_operand->staticType()->cardinality().allowsEmpty()) + return m_targetType; + else + return makeGenericSequenceType(m_targetType->itemType(), + Cardinality::exactlyOne()); +} + +SequenceType::List CastAs::expectedOperandTypes() const +{ + SequenceType::List result; + + if(m_targetType->cardinality().allowsEmpty()) + result.append(CommonSequenceTypes::ZeroOrOneAtomicType); + else + result.append(CommonSequenceTypes::ExactlyOneAtomicType); + + return result; +} + +ExpressionVisitorResult::Ptr CastAs::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qcastas_p.h b/src/xmlpatterns/expr/qcastas_p.h new file mode 100644 index 0000000..892b064 --- /dev/null +++ b/src/xmlpatterns/expr/qcastas_p.h @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** 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_CastAs_H +#define Patternist_CastAs_H + +#include "qsinglecontainer_p.h" +#include "qcastingplatform_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Implements XPath 2.0's <tt>cast as</tt> expression. + * + * Implements the casting expression, such as <tt>'3' cast as xs:integer</tt>. This class also + * implements constructor functions, which are created in the ConstructorFunctionsFactory. + * + * CastAs uses CastingPlatform for carrying out the actual casting. + * + * @see <a href="http://www.w3.org/TR/xpath-functions/#casting">XQuery 1.0 + * and XPath 2.0 Functions and Operators, 7 Casting</a> + * @see <a href="http://www.w3.org/TR/xpath20/#id-cast">XML Path Language + * (XPath) 2.0, 3.10.2 Cast</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class CastAs : public SingleContainer, + public CastingPlatform<CastAs, true /* issueError */> + { + public: + + /** + * @todo Wrong/old documentation + * + * Creates a cast expression for the type @p name via the schema type + * factory @p factory. This function is used by parser when creating + * 'cast to' expressions, and the ConstructorFunctionsFactory, when creating + * constructor functions. + * + * @param targetType the type which the CastAs should cast to + * @param source the operand to evaluate and then cast from + */ + CastAs(const Expression::Ptr &source, + const SequenceType::Ptr &targetType); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &) const; + + virtual SequenceType::List expectedOperandTypes() const; + + /** + * @returns a SequenceType where the ItemType is this CastAs's + * target type, as per targetType(), and the Cardinality is inferred from the + * source operand to reflect whether this CastAs always will evaluate to + * exactly-one or zero-or-one values. + */ + virtual SequenceType::Ptr staticType() const; + + /** + * Overridden in order to check that casting to an abstract type + * is not attempted. + */ + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + + /** + * If the target type is the same as the source type, it is rewritten + * to the operand. + */ + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + inline ItemType::Ptr targetType() const + { + return m_targetType->itemType(); + } + + inline SequenceType::Ptr targetSequenceType() const + { + return m_targetType; + } + + private: + /** + * Performs casting to @c xs:QName. This case is special, and is always done at compile time. + */ + Expression::Ptr castToQName(const StaticContext::Ptr &context) const; + + const SequenceType::Ptr m_targetType; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qcastingplatform.cpp b/src/xmlpatterns/expr/qcastingplatform.cpp new file mode 100644 index 0000000..04b6349 --- /dev/null +++ b/src/xmlpatterns/expr/qcastingplatform.cpp @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +/** + * @file + * @short This file is included by qcastingplatform_p.h. + * If you need includes in this file, put them in CasttingPlatform.h, outside of the namespace. + */ + +template <typename TSubClass, const bool issueError> +Item CastingPlatform<TSubClass, issueError>::castWithCaster(const Item &sourceValue, + const AtomicCaster::Ptr &caster, + const ReportContext::Ptr &context) const +{ + Q_ASSERT(sourceValue); + Q_ASSERT(caster); + Q_ASSERT(context); + + const Item retval(caster->castFrom(sourceValue, context)); + + if(issueError) + { + if(retval.template as<AtomicValue>()->hasError()) + { + issueCastError(retval, sourceValue, context); + return Item(); + } + else + return retval; + } + else + return retval; +} + +template <typename TSubClass, const bool issueError> +Item CastingPlatform<TSubClass, issueError>::cast(const Item &sourceValue, + const ReportContext::Ptr &context) const +{ + Q_ASSERT(sourceValue); + Q_ASSERT(context); + Q_ASSERT(targetType()); + + if(m_caster) + return castWithCaster(sourceValue, m_caster, context); + else + { + bool castImpossible = false; + const AtomicCaster::Ptr caster(locateCaster(sourceValue.type(), context, castImpossible, static_cast<const TSubClass *>(this), targetType())); + + if(!issueError && castImpossible) + { + /* If we're supposed to issue an error(issueError) then this + * line will never be reached, because locateCaster() will in + * that case throw. */ + return ValidationError::createError(); + } + else + return castWithCaster(sourceValue, caster, context); + } +} + +template <typename TSubClass, const bool issueError> +bool CastingPlatform<TSubClass, issueError>::prepareCasting(const ReportContext::Ptr &context, + const ItemType::Ptr &sourceType) +{ + Q_ASSERT(sourceType); + Q_ASSERT(context); + + if(*sourceType == *BuiltinTypes::xsAnyAtomicType || + *sourceType == *BuiltinTypes::item || + *sourceType == *CommonSequenceTypes::Empty || + *sourceType == *BuiltinTypes::numeric) + return true; /* The type could not be narrowed better than xs:anyAtomicType + or numeric at compile time. We'll do lookup at runtime instead. */ + + bool castImpossible = false; + m_caster = locateCaster(sourceType, context, castImpossible, static_cast<const TSubClass *>(this), targetType()); + + return !castImpossible; +} + +template <typename TSubClass, const bool issueError> +AtomicCaster::Ptr CastingPlatform<TSubClass, issueError>::locateCaster(const ItemType::Ptr &sourceType, + const ReportContext::Ptr &context, + bool &castImpossible, + const SourceLocationReflection *const location, + const ItemType::Ptr &targetType) +{ + Q_ASSERT(sourceType); + Q_ASSERT(targetType); + + const AtomicCasterLocator::Ptr locator(static_cast<AtomicType *>( + targetType.data())->casterLocator()); + if(!locator) + { + if(issueError) + { + context->error(QtXmlPatterns::tr("No casting is possible with %1 as the target type.") + .arg(formatType(context->namePool(), targetType)), + ReportContext::XPTY0004, location); + } + else + castImpossible = true; + + return AtomicCaster::Ptr(); + } + + const AtomicCaster::Ptr caster(static_cast<const AtomicType *>(sourceType.data())->accept(locator, location)); + if(!caster) + { + if(issueError) + { + context->error(QtXmlPatterns::tr("It is not possible to cast from %1 to %2.") + .arg(formatType(context->namePool(), sourceType)) + .arg(formatType(context->namePool(), targetType)), + ReportContext::XPTY0004, location); + } + else + castImpossible = true; + + return AtomicCaster::Ptr(); + } + + return caster; +} + +template <typename TSubClass, const bool issueError> +void CastingPlatform<TSubClass, issueError>::checkTargetType(const ReportContext::Ptr &context) const +{ + Q_ASSERT(context); + + const ItemType::Ptr tType(targetType()); + Q_ASSERT(tType); + Q_ASSERT(tType->isAtomicType()); + const AtomicType::Ptr asAtomic(tType); + + /* This catches casting to xs:NOTATION and xs:anyAtomicType. */ + if(asAtomic->isAbstract()) + { + context->error(QtXmlPatterns::tr("Casting to %1 is not possible because it " + "is an abstract type, and can therefore never be instantiated.") + .arg(formatType(context->namePool(), tType)), + ReportContext::XPST0080, + static_cast<const TSubClass*>(this)); + } +} + +template <typename TSubClass, const bool issueError> +void CastingPlatform<TSubClass, issueError>::issueCastError(const Item &validationError, + const Item &sourceValue, + const ReportContext::Ptr &context) const +{ + Q_ASSERT(validationError); + Q_ASSERT(context); + Q_ASSERT(validationError.isAtomicValue()); + Q_ASSERT(validationError.template as<AtomicValue>()->hasError()); + + const ValidationError::Ptr err(validationError.template as<ValidationError>()); + QString msg(err->message()); + + if(msg.isNull()) + { + msg = QtXmlPatterns::tr("It's not possible to cast the value %1 of type %2 to %3") + .arg(formatData(sourceValue.stringValue())) + .arg(formatType(context->namePool(), sourceValue.type())) + .arg(formatType(context->namePool(), targetType())); + } + else + { + Q_ASSERT(!msg.isEmpty()); + msg = QtXmlPatterns::tr("Failure when casting from %1 to %2: %3") + .arg(formatType(context->namePool(), sourceValue.type())) + .arg(formatType(context->namePool(), targetType())) + .arg(msg); + } + + /* If m_errorCode is FORG0001, we assume our sub-classer doesn't have a + * special wish about error code, so then we use the error object's code. + */ + context->error(msg, m_errorCode == ReportContext::FORG0001 ? err->errorCode() : m_errorCode, + static_cast<const TSubClass*>(this)); +} + diff --git a/src/xmlpatterns/expr/qcastingplatform_p.h b/src/xmlpatterns/expr/qcastingplatform_p.h new file mode 100644 index 0000000..415003f --- /dev/null +++ b/src/xmlpatterns/expr/qcastingplatform_p.h @@ -0,0 +1,206 @@ +/**************************************************************************** +** +** 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_CastingPlatform_H +#define Patternist_CastingPlatform_H + +#include "qatomiccasterlocator_p.h" +#include "qatomiccaster_p.h" +#include "qatomicstring_p.h" +#include "qatomictype_p.h" +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qpatternistlocale_p.h" +#include "qqnamevalue_p.h" +#include "qschematypefactory_p.h" +#include "qstaticcontext_p.h" +#include "qvalidationerror_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Provides casting functionality for classes, such as CastAs or NumberFN, which + * needs to perform casting. + * + * Classes which need to perform casting can simply from this class and gain + * access to casting functinality wrapped in a convenient way. At the center of this + * class is the cast() function, which is used at runtime to perform the actual cast. + * + * The actual circumstances where casting is used, such as in the 'castable as' + * expression or the <tt>fn:number()</tt> function, often have other things to handle as well, + * error handling and cardinality checks for example. This class handles only casting + * and leaves the other case-specific details to the sub-class such that this class only + * do one thing well. + * + * This template class takes two parameters: + * - TSubClass This should be the class inheriting from CastingPlatform. + * - issueError if true, errors are issued via ReportContext, otherwise + * ValidationError instances are returned appropriately. + * + * The class inheriting CastingPlatform must implement the following function: + * @code + * ItemType::Ptr targetType() const + * @endcode + * + * that returns the type that should be cast to. The type must be an AtomicType. + * Typically, it is appropriate to declare this function @c inline. + * + * A sub-class calls prepareCasting() at compile time(such that CastingPlatform can attempt + * to lookup the proper AtomicCaster) and then it simply uses the cast() function at runtime. The + * function targetType() must be implemented such that CastingPlatform knows + * what type it shall cast to. + * + * @see ValueFactory + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + template<typename TSubClass, const bool issueError> + class CastingPlatform + { + protected: + /** + * @note issueCastError() depends on the default value. + */ + inline CastingPlatform(const ReportContext::ErrorCode code = ReportContext::FORG0001) : m_errorCode(code) + { + } + + /** + * Attempts to cast @p sourceValue to targetType(), and returns + * the created value. Remember that prepareCasting() should have been + * called at compile time, otherwise this function will be slow. + * + * Error reporting is done in two ways. If a cast fails because + * of an error in lexical representation a ValidationError is returned. + * If the cause of failure is that the casting combination is invalid(such as + * when attempting to cast @c xs:date to @c xs:integer), a ValidationError + * is returned if @c false was passed in the template instantiation, + * an error is issued via @p context. + * + * @param sourceValue the value to cast. Must be non @c null. + * @param context the usual ReportContext, used for error reporting. + * @returns the new value which was the result of the cast. If the + * cast failed, an ValidationError is returned. + */ + Item cast(const Item &sourceValue, + const ReportContext::Ptr &context) const; + + /** + * This function should be called at compiled time, it attempts to determine + * what AtomicCaster that should be used when casting from @p sourceType to + * targetType(). If that is not possible, because the @p sourceType is + * @c xs:anyAtomicType for instance, the AtomicCaster lookup will done at + * runtime on a case-per-case basis. + * + * @returns @c true if the requested casting combination is valid or might be valid. + * If it is guranteed to be invalid, @c false is returned. + */ + bool prepareCasting(const ReportContext::Ptr &context, + const ItemType::Ptr &sourceType); + + /** + * Checks that the targetType() is a valid target type for <tt>castable as</tt> + * and <tt>cast as</tt>. For example, that it is not abstract. If the type is + * invalid, an error is raised via the @p context. Note that it is assumed the type + * is atomic. + */ + void checkTargetType(const ReportContext::Ptr &context) const; + + private: + inline Item castWithCaster(const Item &sourceValue, + const AtomicCaster::Ptr &caster, + const ReportContext::Ptr &context) const; + + /** + * Locates the caster for casting values of type @p sourceType to targetType(), if + * possible. + * + * @p castImpossible is not initialized. Initialize it to @c false. + */ + static AtomicCaster::Ptr locateCaster(const ItemType::Ptr &sourceType, + const ReportContext::Ptr &context, + bool &castImpossible, + const SourceLocationReflection *const location, + const ItemType::Ptr &targetType); + private: + inline Item castWithCaster(const Item &sourceValue, + const AtomicCaster::Ptr &caster, + const DynamicContext::Ptr &context) const; + + + inline ItemType::Ptr targetType() const + { + Q_ASSERT(static_cast<const TSubClass *>(this)->targetType()); + return static_cast<const TSubClass *>(this)->targetType(); + } + + void issueCastError(const Item &validationError, + const Item &sourceValue, + const ReportContext::Ptr &context) const; + + Q_DISABLE_COPY(CastingPlatform) + AtomicCaster::Ptr m_caster; + const ReportContext::ErrorCode m_errorCode; + }; + +#include "qcastingplatform.cpp" + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qcollationchecker.cpp b/src/xmlpatterns/expr/qcollationchecker.cpp new file mode 100644 index 0000000..91e4848 --- /dev/null +++ b/src/xmlpatterns/expr/qcollationchecker.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qxpathhelper_p.h" + +#include "qcollationchecker_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +CollationChecker::CollationChecker(const Expression::Ptr &source) : SingleContainer(source) +{ +} + +Item CollationChecker::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + const Item val(m_operand->evaluateSingleton(context)); + XPathHelper::checkCollationSupport<ReportContext::FOCH0002>(val.stringValue(), context, this); + return val; +} + +SequenceType::List CollationChecker::expectedOperandTypes() const +{ + SequenceType::List list; + list.append(CommonSequenceTypes::ExactlyOneString); + return list; +} + +SequenceType::Ptr CollationChecker::staticType() const +{ + return m_operand->staticType(); +} + +ExpressionVisitorResult::Ptr CollationChecker::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qcollationchecker_p.h b/src/xmlpatterns/expr/qcollationchecker_p.h new file mode 100644 index 0000000..b57e8c9 --- /dev/null +++ b/src/xmlpatterns/expr/qcollationchecker_p.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** 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_CollationChecker_H +#define Patternist_CollationChecker_H + +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Checks that its operand evaluates to a supported string collation. + * + * CollationChecker is inserted in the AST when an Expression has LastOperandIsCollation + * set. If the argument that CollationChecker is a string literal the CollationChecker + * will const-fold as usual, but otherwise will simply pipe through the value of its argument, + * if it's a supported collation. Otherwise it raise an error, with code ReportContext::FOCH0002. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class CollationChecker : public SingleContainer + { + public: + CollationChecker(const Expression::Ptr &source); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &) const; + + /** + * Expects exactly one string. + */ + virtual SequenceType::List expectedOperandTypes() const; + + /** + * @returns its operand's static type. + */ + virtual SequenceType::Ptr staticType() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qcombinenodes.cpp b/src/xmlpatterns/expr/qcombinenodes.cpp new file mode 100644 index 0000000..0670faf --- /dev/null +++ b/src/xmlpatterns/expr/qcombinenodes.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qexceptiterator_p.h" +#include "qgenericsequencetype_p.h" +#include "qintersectiterator_p.h" +#include "qitemmappingiterator_p.h" +#include "qnodesort_p.h" +#include "qunioniterator_p.h" + +#include "qcombinenodes_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +CombineNodes::CombineNodes(const Expression::Ptr &operand1, + const Operator op, + const Expression::Ptr &operand2) : PairContainer(operand1, operand2), + m_operator(op) +{ + Q_ASSERT(op == Union || + op == Except || + op == Intersect); +} + +Item::Iterator::Ptr CombineNodes::evaluateSequence(const DynamicContext::Ptr &context) const +{ + const Item::Iterator::Ptr op1(m_operand1->evaluateSequence(context)); + const Item::Iterator::Ptr op2(m_operand2->evaluateSequence(context)); + + switch(m_operator) + { + case Intersect: + return Item::Iterator::Ptr(new IntersectIterator(op1, op2)); + case Except: + return Item::Iterator::Ptr(new ExceptIterator(op1, op2)); + default: + { + Q_ASSERT(m_operator == Union); + return Item::Iterator::Ptr(new UnionIterator(op1, op2)); + } + } +} + +Item CombineNodes::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + return evaluateSequence(context)->next(); +} + +Expression::Ptr CombineNodes::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + + const Expression::Ptr me(PairContainer::typeCheck(context, reqType)); + + m_operand1 = NodeSortExpression::wrapAround(m_operand1, context); + m_operand2 = NodeSortExpression::wrapAround(m_operand2, context); + + return me; +} + +bool CombineNodes::evaluateEBV(const DynamicContext::Ptr &context) const +{ + /* If it's the union operator, we can possibly avoid + * evaluating the second operand. */ + + if(m_operator == Union) + { + return m_operand1->evaluateEBV(context) || + m_operand2->evaluateEBV(context); + } + else + return PairContainer::evaluateEBV(context); +} + +QString CombineNodes::displayName(const Operator op) +{ + switch(op) + { + case Intersect: + return QLatin1String("intersect"); + case Except: + return QLatin1String("except"); + default: + { + Q_ASSERT(op == Union); + return QLatin1String("union"); + } + } +} + +SequenceType::Ptr CombineNodes::staticType() const +{ + const SequenceType::Ptr t1(m_operand1->staticType()); + const SequenceType::Ptr t2(m_operand2->staticType()); + + Cardinality card; + + /* Optimization: the cardinality can be better inferred for + * Intersect and Except, although it's not trivial code. */ + if(m_operator == Union) + card = t1->cardinality() | t2->cardinality(); + else /* Except. */ + card = Cardinality::zeroOrMore(); + + return makeGenericSequenceType(t1->itemType() | t2->itemType(), card); +} + +SequenceType::List CombineNodes::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreNodes); + result.append(CommonSequenceTypes::ZeroOrMoreNodes); + return result; +} + +CombineNodes::Operator CombineNodes::operatorID() const +{ + return m_operator; +} + +ExpressionVisitorResult::Ptr CombineNodes::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID CombineNodes::id() const +{ + return IDCombineNodes; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qcombinenodes_p.h b/src/xmlpatterns/expr/qcombinenodes_p.h new file mode 100644 index 0000000..4baf196 --- /dev/null +++ b/src/xmlpatterns/expr/qcombinenodes_p.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** 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_CombineNodes_H +#define Patternist_CombineNodes_H + +#include "qpaircontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Implements XPath 2.0's operators for combining node sequences: @c union, + * @c intersect and @c except. + * + * @see <a href="http://www.w3.org/TR/xquery/#combining_seq">XQuery 1.0: An XML Query + * Language, 3.3.3 Combining QXmlNodeModelIndex Sequences</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class Q_AUTOTEST_EXPORT CombineNodes : public PairContainer + { + public: + enum Operator + { + Union = 1, + Intersect = 2, + Except = 4 + }; + + CombineNodes(const Expression::Ptr &operand1, + const Operator op, + const Expression::Ptr &operand2); + + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + virtual SequenceType::Ptr staticType() const; + virtual SequenceType::List expectedOperandTypes() const; + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + + Operator operatorID() const; + virtual ID id() const; + + /** + * Determines the string representation for operator @p op. + * + * @return "union" if @p op is Union, "intersect" if @p op + * is Intersect and "except" if @p op is Except. + */ + static QString displayName(const Operator op); + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + private: + const Operator m_operator; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qcommentconstructor.cpp b/src/xmlpatterns/expr/qcommentconstructor.cpp new file mode 100644 index 0000000..8d7144f --- /dev/null +++ b/src/xmlpatterns/expr/qcommentconstructor.cpp @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qpatternistlocale_p.h" +#include "qnodebuilder_p.h" + +#include "qcommentconstructor_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +CommentConstructor::CommentConstructor(const Expression::Ptr &op) : SingleContainer(op) +{ +} + +QString CommentConstructor::evaluateContent(const DynamicContext::Ptr &context) const +{ + const Item item(m_operand->evaluateSingleton(context)); + + if(!item) + return QString(); + + const QString content(item.stringValue()); + + if(content.contains(QLatin1String("--"))) + { + context->error(QtXmlPatterns::tr("A comment cannot contain %1") + .arg(formatData("--")), + ReportContext::XQDY0072, this); + } + else if(content.endsWith(QLatin1Char('-'))) + { + context->error(QtXmlPatterns::tr("A comment cannot end with a %1.") + .arg(formatData(QLatin1Char('-'))), + ReportContext::XQDY0072, this); + } + + return content; +} + +Item CommentConstructor::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + const QString content(evaluateContent(context)); + const NodeBuilder::Ptr nodeBuilder(context->nodeBuilder(QUrl())); + nodeBuilder->comment(content); + + const QAbstractXmlNodeModel::Ptr nm(nodeBuilder->builtDocument()); + context->addNodeModel(nm); + + return nm->root(QXmlNodeModelIndex()); +} + +void CommentConstructor::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + const QString content(evaluateContent(context)); + QAbstractXmlReceiver *const receiver = context->outputReceiver(); + + receiver->comment(content); +} + +SequenceType::Ptr CommentConstructor::staticType() const +{ + return CommonSequenceTypes::ExactlyOneComment; +} + +SequenceType::List CommentConstructor::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrOneString); + return result; +} + +Expression::Properties CommentConstructor::properties() const +{ + return DisableElimination | IsNodeConstructor; +} + +ExpressionVisitorResult::Ptr +CommentConstructor::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qcommentconstructor_p.h b/src/xmlpatterns/expr/qcommentconstructor_p.h new file mode 100644 index 0000000..75467ec --- /dev/null +++ b/src/xmlpatterns/expr/qcommentconstructor_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** 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_CommentConstructor_H +#define Patternist_CommentConstructor_H + +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Constructs a comment node. This covers both computed and directly constructed + * text nodes. + * + * @see <a href="http://www.w3.org/TR/xquery/#id-constructors">XQuery + * 1.0: An XML Query Language, 3.7 Constructors</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class CommentConstructor : public SingleContainer + { + public: + CommentConstructor(const Expression::Ptr &operand); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + virtual SequenceType::Ptr staticType() const; + + /** + * The first operand must be exactly one @c xs:string. + */ + virtual SequenceType::List expectedOperandTypes() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + virtual Properties properties() const; + + private: + inline QString evaluateContent(const DynamicContext::Ptr &context) const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qcomparisonplatform.cpp b/src/xmlpatterns/expr/qcomparisonplatform.cpp new file mode 100644 index 0000000..625dd01 --- /dev/null +++ b/src/xmlpatterns/expr/qcomparisonplatform.cpp @@ -0,0 +1,199 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +/** + * @file + * @short This file is included by qcomparisonplatform_p.h. + * If you need includes in this file, put them in qcomparisonplatform_p.h, outside of the namespace. + */ + +template <typename TSubClass, bool issueError, + AtomicComparator::ComparisonType comparisonType, ReportContext::ErrorCode errorCode> +bool ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>:: +flexibleCompare(const Item &it1, + const Item &it2, + const DynamicContext::Ptr &context) const +{ + if(m_comparator) + /* The comparator was located at compile time. */ + return compare(it1, it2, m_comparator, operatorID()); + else + { + const AtomicComparator::Ptr cp(fetchComparator(it1.type(), + it2.type(), + context)); + + return cp ? compare(it1, it2, cp, operatorID()) : false; + } +} + +template <typename TSubClass, bool issueError, + AtomicComparator::ComparisonType comparisonType, ReportContext::ErrorCode errorCode> +AtomicComparator::ComparisonResult +ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>:: +detailedFlexibleCompare(const Item &it1, + const Item &it2, + const DynamicContext::Ptr &context) const +{ + AtomicComparator::Ptr comp; + + if(m_comparator) + comp = m_comparator; + else + { + comp = fetchComparator(it1.type(), + it2.type(), + context); + } + + Q_ASSERT_X(operatorID() == AtomicComparator::OperatorLessThanNaNLeast || operatorID() == AtomicComparator::OperatorLessThanNaNGreatest, + Q_FUNC_INFO, "Only OperatorLessThan is currently supported for this function."); + return comp->compare(it1, operatorID(), it2); +} + +template <typename TSubClass, bool issueError, + AtomicComparator::ComparisonType comparisonType, ReportContext::ErrorCode errorCode> +bool ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>:: +compare(const Item &oand1, + const Item &oand2, + const AtomicComparator::Ptr &comp, + const AtomicComparator::Operator op) const +{ + Q_ASSERT(oand1); + Q_ASSERT(oand2); + Q_ASSERT(comp); + + switch(op) + { + case AtomicComparator::OperatorEqual: + return comp->equals(oand1, oand2); + case AtomicComparator::OperatorNotEqual: + return !comp->equals(oand1, oand2); + case AtomicComparator::OperatorLessThanNaNLeast: + case AtomicComparator::OperatorLessThanNaNGreatest: + /* Fallthrough. */ + case AtomicComparator::OperatorLessThan: + return comp->compare(oand1, op, oand2) == AtomicComparator::LessThan; + case AtomicComparator::OperatorGreaterThan: + return comp->compare(oand1, op, oand2) == AtomicComparator::GreaterThan; + case AtomicComparator::OperatorLessOrEqual: + { + const AtomicComparator::ComparisonResult ret = comp->compare(oand1, op, oand2); + return ret == AtomicComparator::LessThan || ret == AtomicComparator::Equal; + } + case(AtomicComparator::OperatorGreaterOrEqual): + { + const AtomicComparator::ComparisonResult ret = comp->compare(oand1, op, oand2); + return ret == AtomicComparator::GreaterThan || ret == AtomicComparator::Equal; + } + } + + /* GCC unbarfer, this line should never be reached. */ + Q_ASSERT(false); + return false; +} + +template <typename TSubClass, bool issueError, + AtomicComparator::ComparisonType comparisonType, ReportContext::ErrorCode errorCode> +AtomicComparator::Ptr ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>:: +fetchComparator(const ItemType::Ptr &t1, + const ItemType::Ptr &t2, + const ReportContext::Ptr &context) const +{ + Q_ASSERT(t1); + Q_ASSERT(t2); + + if(*BuiltinTypes::xsAnyAtomicType == *t1 || + *BuiltinTypes::xsAnyAtomicType == *t2 || + *BuiltinTypes::item == *t1 || + *BuiltinTypes::item == *t2 || + *BuiltinTypes::numeric == *t1 || + *BuiltinTypes::numeric == *t2 || + *CommonSequenceTypes::Empty == *t1 || + *CommonSequenceTypes::Empty == *t2) + { + /* The static type of(at least) one of the operands could not + * be narrowed further, so we do the operator + * lookup at runtime. + */ + return AtomicComparator::Ptr(); + } + + const AtomicComparatorLocator::Ptr locator + (static_cast<const AtomicType *>(t1.data())->comparatorLocator()); + + if(!locator) + { + if(issueError) + { + context->error(QtXmlPatterns::tr("No comparisons can be done involving the type %1.") + .arg(formatType(context->namePool(), t1)), + errorCode, static_cast<const TSubClass *>(this)->actualReflection()); + } + return AtomicComparator::Ptr(); + } + + const AtomicComparator::Ptr comp(static_cast<const AtomicType *>(t2.data())->accept(locator, operatorID(), + static_cast<const TSubClass *>(this)->actualReflection())); + + if(comp) + return comp; + else if(issueError) + { + context->error(QtXmlPatterns::tr("Operator %1 is not available between atomic values of type %2 and %3.") + .arg(formatKeyword(AtomicComparator::displayName(operatorID(), + comparisonType)), + formatType(context->namePool(), t1), + formatType(context->namePool(), t2)), + errorCode, static_cast<const TSubClass *>(this)->actualReflection()); + } + + return AtomicComparator::Ptr(); +} + +template <typename TSubClass, bool issueError, + AtomicComparator::ComparisonType comparisonType, ReportContext::ErrorCode errorCode> +void ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>:: +prepareComparison(const AtomicComparator::Ptr &c) +{ + m_comparator = c; +} + diff --git a/src/xmlpatterns/expr/qcomparisonplatform_p.h b/src/xmlpatterns/expr/qcomparisonplatform_p.h new file mode 100644 index 0000000..359e247 --- /dev/null +++ b/src/xmlpatterns/expr/qcomparisonplatform_p.h @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** 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_ComparisonPlatform_H +#define Patternist_ComparisonPlatform_H + +#include "qatomiccomparators_p.h" +#include "qitem_p.h" +#include "qcommonsequencetypes_p.h" +#include "qdynamiccontext_p.h" +#include "qbuiltintypes_p.h" +#include "qitemtype_p.h" +#include "qpatternistlocale_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Provides comparison functionality for classes that compare Items, + * such as ValueComparison or MaxFN. + * + * Classes which need comparison functionalities should inherit from this class. + * + * The parameter of this template class is the class inheriting from ComparisonPlatform. + * + * The class inheriting ComparisonPlatform must implement the following function: + * @code + * AtomicComparator::Operator operatorID() const + * @endcode + * + * @author Vincent Ricard <magic@magicninja.org> + * @ingroup Patternist_expressions + */ + template <typename TSubClass, + bool issueError, + AtomicComparator::ComparisonType comparisonType = AtomicComparator::AsValueComparison, + ReportContext::ErrorCode errorCode = ReportContext::XPTY0004> + class ComparisonPlatform + { + protected: + /** + * Makes ComparisonPlatform use the AtomicComparator @p comparator. + */ + void prepareComparison(const AtomicComparator::Ptr &comparator); + + /** + * Default constructor. Does nothing. It is implemented in order make template + * instantiation easier. + */ + inline ComparisonPlatform() + { + } + + /** + * Utility function for fetching the appropriate AtomicComparator + * for two atomic values of type @p type1 and @p type2, for the operator @p op. + * + * This function is used throughout the implementation, ranging from the ValueComparison + * itself, to for example the aggregate functions. + * + * @param context the ordinary ReportContext, used for issuing errors. + * @param type1 the type of the first operand value in a comparison for which the + * returned AtomicComparator is intended for + * @param type2 the type of the second operand value in a comparison for which the + * returned AtomicComparator is intended for. Whether @p type1 and @p type2 corresponds + * to what is the first second operand type does not have significance, the order + * can be arbitrary + */ + AtomicComparator::Ptr + fetchComparator(const ItemType::Ptr &type1, + const ItemType::Ptr &type2, + const ReportContext::Ptr &context) const; + + /** + * @short Compares @p i1 and @p i2 with operator @p op, using comparator @p + * comp. All input arguments must be valid, and not @c null. + * + * This is a fast, raw function which has the requirement that the + * caller knows what to compare and with what. + */ + bool compare(const Item &i1, + const Item &i2, + const AtomicComparator::Ptr &comp, + const AtomicComparator::Operator op) const; + + /** + * @short Compares @p it1 against @p it2, using comparator() and operatorID(). + * + * If the comparator wasn't looked up at compile time, it will be + * attempted before comparing. If this fails, errors are reported via + * @p context. + */ + bool + flexibleCompare(const Item &it1, + const Item &it2, + const DynamicContext::Ptr &context) const; + + /** + * @short like flexibleCompare(), but returns the result + * as an AtomicComparator::Operator instead of @c bool. + * + * This is useful when it is significant how a less than comparison + * fails; whether the two values are equal or greater than. + */ + AtomicComparator::ComparisonResult + detailedFlexibleCompare(const Item &it1, + const Item &it2, + const DynamicContext::Ptr &context) const; + + /** + * @returns the AtomicComparator that has been allocated at compile time, + * with prepareComparison(). If no AtomicComparator has been allocated + * for some reason, this function returns @c null. + */ + inline const AtomicComparator::Ptr &comparator() const + { + return m_comparator; + } + + /** + * Calling this function makes ComparisonPlatform use a comparator that + * compares strings case insensitively. + * + * @see ValueComparison::isCaseInsensitiveCompare() + */ + inline void useCaseInsensitiveComparator() + { + m_comparator = AtomicComparator::Ptr(new CaseInsensitiveStringComparator()); + } + + private: + /** + * @returns the operator that is used. + */ + inline AtomicComparator::Operator operatorID() const + { + Q_ASSERT(static_cast<const TSubClass *>(this)->operatorID()); + return static_cast<const TSubClass *>(this)->operatorID(); + } + + /** + * The comparator that is used for comparing atomic values. The AtomicComparator + * that is used, depends on the static type of the operands. m_comparator can be + * @c null if it wasn't possible to determine what comparator to use at compile time. + */ + AtomicComparator::Ptr m_comparator; + }; + +#include "qcomparisonplatform.cpp" + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qcomputednamespaceconstructor.cpp b/src/xmlpatterns/expr/qcomputednamespaceconstructor.cpp new file mode 100644 index 0000000..6eb0c0e --- /dev/null +++ b/src/xmlpatterns/expr/qcomputednamespaceconstructor.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qanyuri_p.h" +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qpatternistlocale_p.h" +#include "private/qxmlutils_p.h" + +#include "qcomputednamespaceconstructor_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ComputedNamespaceConstructor::ComputedNamespaceConstructor(const Expression::Ptr &prefix, + const Expression::Ptr &namespaceURI) : PairContainer(prefix, namespaceURI) +{ +} + +void ComputedNamespaceConstructor::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + const Item prefixItem(m_operand1->evaluateSingleton(context)); + const QString prefix(prefixItem ? prefixItem.stringValue() : QString()); + + const Item namespaceItem(m_operand2->evaluateSingleton(context)); + const QString namespaceURI(namespaceItem ? namespaceItem.stringValue() : QString()); + + if(namespaceURI.isEmpty()) + { + context->error(QtXmlPatterns::tr("In a namespace constructor, the value for a namespace cannot be an empty string."), + ReportContext::XTDE0930, + this); + } + + /* One optimization could be to store a pointer to + * the name pool as a member in order to avoid the virtual call(s). */ + const NamePool::Ptr np(context->namePool()); + + if(!prefix.isEmpty() && !QXmlUtils::isNCName(prefix)) + { + context->error(QtXmlPatterns::tr("The prefix must be a valid %1, which %2 is not.") + .arg(formatType(np, BuiltinTypes::xsNCName), + formatKeyword(prefix)), + ReportContext::XTDE0920, + this); + } + const QXmlName binding(np->allocateBinding(prefix, namespaceURI)); + + AnyURI::toQUrl<ReportContext::XTDE0905, DynamicContext::Ptr>(namespaceURI, + context, + this); + + if(binding.prefix() == StandardPrefixes::xmlns) + { + context->error(QtXmlPatterns::tr("The prefix %1 cannot be bound.") + .arg(formatKeyword(prefix)), + ReportContext::XTDE0920, + this); + } + + if((binding.prefix() == StandardPrefixes::xml && binding.namespaceURI() != StandardNamespaces::xml) + || + (binding.prefix() != StandardPrefixes::xml && binding.namespaceURI() == StandardNamespaces::xml)) + { + context->error(QtXmlPatterns::tr("Only the prefix %1 can be bound to %2 and vice versa.") + .arg(formatKeyword(prefix), formatKeyword(namespaceURI)), + ReportContext::XTDE0925, + this); + } + + context->outputReceiver()->namespaceBinding(binding); +} + +SequenceType::Ptr ComputedNamespaceConstructor::staticType() const +{ + return CommonSequenceTypes::ExactlyOneAttribute; +} + +SequenceType::List ComputedNamespaceConstructor::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrOneString); + result.append(CommonSequenceTypes::ZeroOrOneString); + return result; +} + +Expression::Properties ComputedNamespaceConstructor::properties() const +{ + return DisableElimination | IsNodeConstructor; +} + +ExpressionVisitorResult::Ptr ComputedNamespaceConstructor::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qcomputednamespaceconstructor_p.h b/src/xmlpatterns/expr/qcomputednamespaceconstructor_p.h new file mode 100644 index 0000000..3950052 --- /dev/null +++ b/src/xmlpatterns/expr/qcomputednamespaceconstructor_p.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** 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_ComputedNamespaceConstructor_H +#define Patternist_ComputedNamespaceConstructor_H + +#include "qpaircontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Constructs a namespace on an element, and naturally only appears + * as a child of ElementConstructor. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + * @since 4.5 + */ + class ComputedNamespaceConstructor : public PairContainer + { + public: + ComputedNamespaceConstructor(const Expression::Ptr &prefix, + const Expression::Ptr &namespaceURI); + + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + /** + * @returns a list containing one CommonSequenceTypes::ExactlyOneString instance. + */ + virtual SequenceType::List expectedOperandTypes() const; + + /** + * The static type is exactly one attribute node. It's unclear what + * affects the static type has, but specifying anything else could lead + * to complications wrt. node order, XQTY0024. Of course, it's not + * conceptually correct, since a namespace node isn't an attribute + * node. + */ + virtual SequenceType::Ptr staticType() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual Expression::Properties properties() const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qcontextitem.cpp b/src/xmlpatterns/expr/qcontextitem.cpp new file mode 100644 index 0000000..caa6653 --- /dev/null +++ b/src/xmlpatterns/expr/qcontextitem.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qgenericsequencetype_p.h" + +#include "qcontextitem_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +Item ContextItem::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + return context->contextItem(); +} + +Expression::Ptr ContextItem::compress(const StaticContext::Ptr &context) +{ + m_itemType = context->contextItemType(); + return EmptyContainer::compress(context); +} + +Expression::Ptr ContextItem::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + m_itemType = context->contextItemType(); + return EmptyContainer::typeCheck(context, reqType); +} + +SequenceType::Ptr ContextItem::staticType() const +{ + /* We test m_itemType here because Patternist View calls staticType() before the typeCheck() + * stage. */ + if(m_itemType) + return makeGenericSequenceType(m_itemType, Cardinality::exactlyOne()); + else + return CommonSequenceTypes::ExactlyOneItem; +} + +Expression::Properties ContextItem::properties() const +{ + return DisableElimination | RequiresContextItem | EvaluationCacheRedundant; +} + +ExpressionVisitorResult::Ptr ContextItem::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID ContextItem::id() const +{ + return IDContextItem; +} + +ItemType::Ptr ContextItem::expectedContextItemType() const +{ + return BuiltinTypes::item; +} + +const SourceLocationReflection *ContextItem::actualReflection() const +{ + if(m_expr) + return m_expr.data(); + else + return this; +} + +void ContextItem::announceFocusType(const ItemType::Ptr &type) +{ + Q_ASSERT(type); + m_itemType = type; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qcontextitem_p.h b/src/xmlpatterns/expr/qcontextitem_p.h new file mode 100644 index 0000000..e3ae81e --- /dev/null +++ b/src/xmlpatterns/expr/qcontextitem_p.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** 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_ContextItem_H +#define Patternist_ContextItem_H + +#include "qemptycontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Implements the context item, the dot: <tt>.</tt>. + * + * @see <a href="http://www.w3.org/TR/xpath20/#id-context-item-expression">XML Path Language + * (XPath) 2.0, 3.1.4 Context Item Expression</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ContextItem : public EmptyContainer + { + public: + /** + * @p expr is possibly used for error reporting. If this context item has been + * created implicitly, such as for the expression <tt>fn:string()</tt>, @p expr + * should be passed a valid pointer to the Expression that this context + * item is generated for. + */ + inline ContextItem(const Expression::Ptr &expr = Expression::Ptr()) : m_expr(expr) + { + } + + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual SequenceType::Ptr staticType() const; + + /** + * @returns always DisableElimination and RequiresContextItem + */ + virtual Expression::Properties properties() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + /** + * Overridden to store a pointer to StaticContext::contextItemType(). + */ + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + + /** + * Overridden to store a pointer to StaticContext::contextItemType(). + */ + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + + /** + * @returns always IDContextItem + */ + virtual ID id() const; + + /** + * @returns always BuiltinTypes::item; + */ + virtual ItemType::Ptr expectedContextItemType() const; + + virtual const SourceLocationReflection *actualReflection() const; + virtual void announceFocusType(const ItemType::Ptr &type); + + private: + ItemType::Ptr m_itemType; + const Expression::Ptr m_expr; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qcopyof.cpp b/src/xmlpatterns/expr/qcopyof.cpp new file mode 100644 index 0000000..ddb5a2c --- /dev/null +++ b/src/xmlpatterns/expr/qcopyof.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qitemmappingiterator_p.h" + +#include "qcopyof_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +CopyOf::CopyOf(const Expression::Ptr &operand, + const bool inheritNSS, + const bool preserveNSS) : SingleContainer(operand) + , m_inheritNamespaces(inheritNSS) + , m_preserveNamespaces(preserveNSS) + , m_settings((m_inheritNamespaces ? QAbstractXmlNodeModel::InheritNamespaces : QAbstractXmlNodeModel::NodeCopySettings()) | + (m_preserveNamespaces ? QAbstractXmlNodeModel::PreserveNamespaces : QAbstractXmlNodeModel::NodeCopySettings())) +{ +} + +Expression::Ptr CopyOf::compress(const StaticContext::Ptr &context) +{ + /* We have zero effect if we have these settings. */ + if(m_inheritNamespaces && m_preserveNamespaces) + return m_operand->compress(context); + else + { + const ItemType::Ptr t(m_operand->staticType()->itemType()); + /* We have no effect on the empty sequence or atomic values. */ + if(BuiltinTypes::xsAnyAtomicType->xdtTypeMatches(t) + || *t == *CommonSequenceTypes::Empty) + return m_operand->compress(context); + else + return SingleContainer::compress(context); + } +} + +void CopyOf::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + /* Optimization: this completely breaks streaming. We get a call to + * evaluateToSequenceReceiver() but we require heap allocations by calling + * evaluateSequence(). */ + + const Item::Iterator::Ptr it(m_operand->evaluateSequence(context)); + QAbstractXmlReceiver *const receiver = context->outputReceiver(); + Item next(it->next()); + + while(next) + { + if(next.isNode()) + { + const QXmlNodeModelIndex &asNode = next.asNode(); + asNode.model()->copyNodeTo(asNode, receiver, m_settings); + } + else + receiver->item(next); + + next = it->next(); + } +} + +ExpressionVisitorResult::Ptr CopyOf::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +SequenceType::Ptr CopyOf::staticType() const +{ + return m_operand->staticType(); +} + +SequenceType::List CopyOf::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +Expression::Properties CopyOf::properties() const +{ + /* We have the content of node constructors as children, but even though + * createCopyOf() typically avoids creating us, we can still end up with an operand + * that allows compression. We must always avoid that, because we don't have + * implementation of evaluateSequence(), and so on. */ + return (m_operand->properties() & ~CreatesFocusForLast) | DisableElimination; +} + +ItemType::Ptr CopyOf::expectedContextItemType() const +{ + return m_operand->expectedContextItemType(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qcopyof_p.h b/src/xmlpatterns/expr/qcopyof_p.h new file mode 100644 index 0000000..7a89b69 --- /dev/null +++ b/src/xmlpatterns/expr/qcopyof_p.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** 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_CopyOf_H +#define Patternist_CopyOf_H + +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Does node copying in a parameterized way, in order to deal with + * namespace preservation/inheritance. + * + * If someone tries to call evaluateEBV(), evaluateSingleton() or + * evaluateSequence() on us, we will infinitely loop. But apparently + * that's not possible because we're always a child of ElementConstructor, + * currently. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class CopyOf : public SingleContainer + { + public: + /** + * Creats a CopyOf where it is checked that the expression @p operand conforms + * to the type @p reqType. + */ + CopyOf(const Expression::Ptr &operand, + const bool inheritNSS, + const bool preserveNSS); + + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + /** + * @returns always the SequenceType passed in the constructor to this class. That is, the + * SequenceType that the operand must conform to. + */ + virtual SequenceType::Ptr staticType() const; + + /** + * @returns a list containing one CommonSequenceTypes::ZeroOrMoreItems + */ + virtual SequenceType::List expectedOperandTypes() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + inline Item mapToItem(const Item &source, + const DynamicContext::Ptr &context) const; + + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + + virtual Properties properties() const; + virtual ItemType::Ptr expectedContextItemType() const; + + private: + typedef QExplicitlySharedDataPointer<const CopyOf> ConstPtr; + const bool m_inheritNamespaces; + const bool m_preserveNamespaces; + const QAbstractXmlNodeModel::NodeCopySettings m_settings; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qcurrentitemstore.cpp b/src/xmlpatterns/expr/qcurrentitemstore.cpp new file mode 100644 index 0000000..0bfab8b --- /dev/null +++ b/src/xmlpatterns/expr/qcurrentitemstore.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qcurrentitemcontext_p.h" +#include "qstaticcurrentcontext_p.h" + +#include "qcurrentitemstore_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +CurrentItemStore::CurrentItemStore(const Expression::Ptr &operand) : SingleContainer(operand) +{ +} + +DynamicContext::Ptr CurrentItemStore::createContext(const DynamicContext::Ptr &old) const +{ + return DynamicContext::Ptr(new CurrentItemContext(old->contextItem(), old)); +} + +bool CurrentItemStore::evaluateEBV(const DynamicContext::Ptr &context) const +{ + return m_operand->evaluateEBV(createContext(context)); +} + +Item::Iterator::Ptr CurrentItemStore::evaluateSequence(const DynamicContext::Ptr &context) const +{ + return m_operand->evaluateSequence(createContext(context)); +} + +Item CurrentItemStore::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + return m_operand->evaluateSingleton(createContext(context)); +} + +SequenceType::Ptr CurrentItemStore::staticType() const +{ + return m_operand->staticType(); +} + +SequenceType::List CurrentItemStore::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +StaticContext::Ptr CurrentItemStore::newStaticContext(const StaticContext::Ptr &context) +{ + /* It might be we are generated despite there is no focus. In that case + * an error will reported in case current() is used, but in any case we cannot + * crash, so use item() in case we have no focus. + * + * Such a case is when we're inside a named template, and it's invoked + * without focus. */ + const ItemType::Ptr t(context->contextItemType()); + return StaticContext::Ptr(new StaticCurrentContext(t ? t : BuiltinTypes::item, context)); +} + +Expression::Ptr CurrentItemStore::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr me(SingleContainer::compress(newStaticContext(context))); + + if(me != this) + return me; + else + { + /* If fn:current() isn't called, there's no point in us sticking + * around. */ + if(m_operand->deepProperties().testFlag(RequiresCurrentItem)) + return me; + else + return m_operand; + } +} + +Expression::Ptr CurrentItemStore::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + return SingleContainer::typeCheck(newStaticContext(context), reqType); +} + +ExpressionVisitorResult::Ptr CurrentItemStore::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +const SourceLocationReflection *CurrentItemStore::actualReflection() const +{ + return m_operand->actualReflection(); +} + +Expression::Properties CurrentItemStore::properties() const +{ + return m_operand->properties() & (RequiresFocus | IsEvaluated | DisableElimination); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qcurrentitemstore_p.h b/src/xmlpatterns/expr/qcurrentitemstore_p.h new file mode 100644 index 0000000..f7cc5d8 --- /dev/null +++ b/src/xmlpatterns/expr/qcurrentitemstore_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** 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_CurrentItemStore_H +#define Patternist_CurrentItemStore_H + +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Creates a DynamicContext which provides the focus item for the + * function @c fn:current(). + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + * @since 4.5 + */ + class CurrentItemStore : public SingleContainer + { + public: + CurrentItemStore(const Expression::Ptr &operand); + + virtual bool evaluateEBV(const DynamicContext::Ptr &) const; + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &) const; + virtual Item evaluateSingleton(const DynamicContext::Ptr &) const; + + virtual SequenceType::List expectedOperandTypes() const; + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + + virtual Properties properties() const; + + /** + * @returns the staticType() of its operand. + */ + virtual SequenceType::Ptr staticType() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual const SourceLocationReflection *actualReflection() const; + + private: + static inline StaticContext::Ptr newStaticContext(const StaticContext::Ptr &context); + inline DynamicContext::Ptr createContext(const DynamicContext::Ptr &old) const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qdocumentconstructor.cpp b/src/xmlpatterns/expr/qdocumentconstructor.cpp new file mode 100644 index 0000000..9dfbe09 --- /dev/null +++ b/src/xmlpatterns/expr/qdocumentconstructor.cpp @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qdocumentcontentvalidator_p.h" +#include "qnodebuilder_p.h" + +#include "qdocumentconstructor_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +DocumentConstructor::DocumentConstructor(const Expression::Ptr &op) : SingleContainer(op) +{ +} + +Item DocumentConstructor::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + NodeBuilder::Ptr nodeBuilder(context->nodeBuilder(m_staticBaseURI)); + + DocumentContentValidator validator(nodeBuilder.data(), context, ConstPtr(this)); + const DynamicContext::Ptr receiverContext(context->createReceiverContext(&validator)); + + validator.startDocument(); + m_operand->evaluateToSequenceReceiver(receiverContext); + validator.endDocument(); + + const QAbstractXmlNodeModel::Ptr nm(nodeBuilder->builtDocument()); + context->addNodeModel(nm); + + return nm->root(QXmlNodeModelIndex()); +} + +void DocumentConstructor::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + QAbstractXmlReceiver *const receiver = context->outputReceiver(); + + DocumentContentValidator validator(receiver, context, ConstPtr(this)); + + const DynamicContext::Ptr receiverContext(context->createReceiverContext(&validator)); + + validator.startDocument(); + m_operand->evaluateToSequenceReceiver(receiverContext); + validator.endDocument(); +} + +Expression::Ptr DocumentConstructor::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + m_staticBaseURI = context->baseURI(); + return SingleContainer::typeCheck(context, reqType); +} + +SequenceType::Ptr DocumentConstructor::staticType() const +{ + return CommonSequenceTypes::ExactlyOneDocumentNode; +} + +SequenceType::List DocumentConstructor::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +Expression::Properties DocumentConstructor::properties() const +{ + return DisableElimination | IsNodeConstructor; +} + +ExpressionVisitorResult::Ptr +DocumentConstructor::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qdocumentconstructor_p.h b/src/xmlpatterns/expr/qdocumentconstructor_p.h new file mode 100644 index 0000000..8b685f9 --- /dev/null +++ b/src/xmlpatterns/expr/qdocumentconstructor_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** 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_DocumentConstructor_H +#define Patternist_DocumentConstructor_H + +#include <QUrl> + +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Constructs a text node. This covers both computed and directly constructed + * text nodes. + * + * @see <a href="http://www.w3.org/TR/xquery/#id-constructors">XQuery + * 1.0: An XML Query Language, 3.7 Constructors</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class DocumentConstructor : public SingleContainer + { + public: + DocumentConstructor(const Expression::Ptr &operand); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + /** + * The first operand must be exactly one @c xs:string. + */ + virtual SequenceType::List expectedOperandTypes() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + + virtual Properties properties() const; + virtual SequenceType::Ptr staticType() const; + + private: + QUrl m_staticBaseURI; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qdocumentcontentvalidator.cpp b/src/xmlpatterns/expr/qdocumentcontentvalidator.cpp new file mode 100644 index 0000000..75e9ae6 --- /dev/null +++ b/src/xmlpatterns/expr/qdocumentcontentvalidator.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qpatternistlocale_p.h" + +#include "qdocumentcontentvalidator_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +DocumentContentValidator:: +DocumentContentValidator(QAbstractXmlReceiver *const receiver, + const DynamicContext::Ptr &context, + const Expression::ConstPtr &expr) : m_receiver(receiver) + , m_context(context) + , m_expr(expr) + , m_elementDepth(0) +{ + Q_ASSERT(receiver); + Q_ASSERT(m_expr); + Q_ASSERT(context); +} + +void DocumentContentValidator::namespaceBinding(const QXmlName &nb) +{ + m_receiver->namespaceBinding(nb); +} + +void DocumentContentValidator::startElement(const QXmlName &name) +{ + ++m_elementDepth; + m_receiver->startElement(name); +} + +void DocumentContentValidator::endElement() +{ + Q_ASSERT(m_elementDepth > 0); + --m_elementDepth; + m_receiver->endElement(); +} + +void DocumentContentValidator::attribute(const QXmlName &name, + const QStringRef &value) +{ + if(m_elementDepth == 0) + { + m_context->error(QtXmlPatterns::tr("An attribute node cannot be a " + "child of a document node. " + "Therefore, the attribute %1 " + "is out of place.") + .arg(formatKeyword(m_context->namePool(), name)), + ReportContext::XPTY0004, m_expr.data()); + } + else + m_receiver->attribute(name, value); +} + +void DocumentContentValidator::comment(const QString &value) +{ + m_receiver->comment(value); +} + +void DocumentContentValidator::characters(const QStringRef &value) +{ + m_receiver->characters(value); +} + +void DocumentContentValidator::processingInstruction(const QXmlName &name, + const QString &value) +{ + m_receiver->processingInstruction(name, value); +} + +void DocumentContentValidator::item(const Item &outputItem) +{ + /* We can't send outputItem directly to m_receiver since its item() function + * won't dispatch to this DocumentContentValidator, but to itself. We're not sub-classing here, + * we're delegating. */ + + if(outputItem.isNode()) + sendAsNode(outputItem); + else + m_receiver->item(outputItem); +} + +void DocumentContentValidator::startDocument() +{ + m_receiver->startDocument(); +} + +void DocumentContentValidator::endDocument() +{ + m_receiver->endDocument(); +} + +void DocumentContentValidator::atomicValue(const QVariant &value) +{ + Q_UNUSED(value); +} + +void DocumentContentValidator::startOfSequence() +{ +} + +void DocumentContentValidator::endOfSequence() +{ +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qdocumentcontentvalidator_p.h b/src/xmlpatterns/expr/qdocumentcontentvalidator_p.h new file mode 100644 index 0000000..92bee3f --- /dev/null +++ b/src/xmlpatterns/expr/qdocumentcontentvalidator_p.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** 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_DocumentContentValidator_H +#define Patternist_DocumentContentValidator_H + +#include "qdynamiccontext_p.h" +#include "qexpression_p.h" +#include "qabstractxmlreceiver.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Receives QAbstractXmlReceiver events and validates that they are correct, + * before sending them on to a second QAbstractXmlReceiver. + * + * @ingroup Patternist_xdm + * @author Frans Englich <frans.englich@nokia.com> + * @todo Escape data + */ + class DocumentContentValidator : public QAbstractXmlReceiver + { + public: + /** + * DocumentContentValidator does not own @p receiver. + */ + DocumentContentValidator(QAbstractXmlReceiver *const receiver, + const DynamicContext::Ptr &context, + const Expression::ConstPtr &expr); + + virtual void namespaceBinding(const QXmlName &nb); + virtual void characters(const QStringRef &value); + virtual void comment(const QString &value); + + virtual void startElement(const QXmlName &name); + + virtual void endElement(); + + virtual void attribute(const QXmlName &name, + const QStringRef &value); + + virtual void processingInstruction(const QXmlName &name, + const QString &value); + + virtual void item(const Item &item); + + virtual void startDocument(); + virtual void endDocument(); + virtual void atomicValue(const QVariant &value); + virtual void startOfSequence(); + virtual void endOfSequence(); + + private: + QAbstractXmlReceiver *const m_receiver; + const DynamicContext::Ptr m_context; + const Expression::ConstPtr m_expr; + xsInteger m_elementDepth; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qdynamiccontextstore.cpp b/src/xmlpatterns/expr/qdynamiccontextstore.cpp new file mode 100644 index 0000000..762b7d6 --- /dev/null +++ b/src/xmlpatterns/expr/qdynamiccontextstore.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qboolean_p.h" +#include "qcommonsequencetypes_p.h" +#include "qcommonvalues_p.h" + +#include "qdynamiccontextstore_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +DynamicContextStore::DynamicContextStore(const Expression::Ptr &operand, + const DynamicContext::Ptr &context) : SingleContainer(operand), + m_context(context) +{ + Q_ASSERT(context); +} + +bool DynamicContextStore::evaluateEBV(const DynamicContext::Ptr &) const +{ + return m_operand->evaluateEBV(m_context); +} + +Item::Iterator::Ptr DynamicContextStore::evaluateSequence(const DynamicContext::Ptr &) const +{ + return m_operand->evaluateSequence(m_context); +} + +Item DynamicContextStore::evaluateSingleton(const DynamicContext::Ptr &) const +{ + return m_operand->evaluateSingleton(m_context); +} + +SequenceType::Ptr DynamicContextStore::staticType() const +{ + return m_operand->staticType(); +} + +SequenceType::List DynamicContextStore::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +ExpressionVisitorResult::Ptr DynamicContextStore::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +const SourceLocationReflection *DynamicContextStore::actualReflection() const +{ + return m_operand->actualReflection(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qdynamiccontextstore_p.h b/src/xmlpatterns/expr/qdynamiccontextstore_p.h new file mode 100644 index 0000000..1d5d035 --- /dev/null +++ b/src/xmlpatterns/expr/qdynamiccontextstore_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** 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_DynamicContextStore_H +#define Patternist_DynamicContextStore_H + +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Evaluates its operand with an assigned DynamicContext, not + * the one passed to one of the evaluation functions. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class DynamicContextStore : public SingleContainer + { + public: + DynamicContextStore(const Expression::Ptr &operand, + const DynamicContext::Ptr &context); + + virtual bool evaluateEBV(const DynamicContext::Ptr &) const; + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &) const; + virtual Item evaluateSingleton(const DynamicContext::Ptr &) const; + + virtual SequenceType::List expectedOperandTypes() const; + /** + * @returns the staticType() of its operand. + */ + virtual SequenceType::Ptr staticType() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual const SourceLocationReflection *actualReflection() const; + + private: + const DynamicContext::Ptr m_context; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qelementconstructor.cpp b/src/xmlpatterns/expr/qelementconstructor.cpp new file mode 100644 index 0000000..41f7b11 --- /dev/null +++ b/src/xmlpatterns/expr/qelementconstructor.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qdelegatingnamespaceresolver_p.h" +#include "qnamespaceconstructor_p.h" +#include "qnodebuilder_p.h" +#include "qoutputvalidator_p.h" +#include "qqnamevalue_p.h" +#include "qstaticnamespacecontext_p.h" + +#include "qelementconstructor_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ElementConstructor::ElementConstructor(const Expression::Ptr &op1, + const Expression::Ptr &op2, + const bool isXSLT) : PairContainer(op1, op2) + , m_isXSLT(isXSLT) +{ +} + +Item ElementConstructor::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + const Item name(m_operand1->evaluateSingleton(context)); + + const NodeBuilder::Ptr nodeBuilder(context->nodeBuilder(m_staticBaseURI)); + OutputValidator validator(nodeBuilder.data(), context, this, m_isXSLT); + + const DynamicContext::Ptr receiverContext(context->createReceiverContext(&validator)); + + nodeBuilder->startElement(name.as<QNameValue>()->qName()); + m_operand2->evaluateToSequenceReceiver(receiverContext); + nodeBuilder->endElement(); + + const QAbstractXmlNodeModel::Ptr nm(nodeBuilder->builtDocument()); + context->addNodeModel(nm); + + return nm->root(QXmlNodeModelIndex()); +} + +void ElementConstructor::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + /* We create an OutputValidator here too. If we're serializing(a common + * case, unfortunately) the receiver is already validating in order to + * catch cases where a computed attribute constructor is followed by an + * element constructor, but in the cases where we're not serializing it's + * necessary that we validate in this step. */ + const Item name(m_operand1->evaluateSingleton(context)); + QAbstractXmlReceiver *const receiver = context->outputReceiver(); + + OutputValidator validator(receiver, context, this, m_isXSLT); + const DynamicContext::Ptr receiverContext(context->createReceiverContext(&validator)); + + receiver->startElement(name.as<QNameValue>()->qName()); + m_operand2->evaluateToSequenceReceiver(receiverContext); + receiver->endElement(); +} + +Expression::Ptr ElementConstructor::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + /* What does this code do? When type checking our children, our namespace + * bindings, which are also children of the form of NamespaceConstructor + * instances, must be statically in-scope for them, so find them and + * shuffle their bindings into the StaticContext. */ + + m_staticBaseURI = context->baseURI(); + + /* Namespace declarations changes the in-scope bindings, so let's + * first lookup our child NamespaceConstructors. */ + const ID operandID = m_operand2->id(); + + NamespaceResolver::Bindings overrides; + if(operandID == IDExpressionSequence) + { + const Expression::List operands(m_operand2->operands()); + const int len = operands.count(); + + for(int i = 0; i < len; ++i) + { + if(operands.at(i)->is(IDNamespaceConstructor)) + { + const QXmlName &nb = operands.at(i)->as<NamespaceConstructor>()->namespaceBinding(); + overrides.insert(nb.prefix(), nb.namespaceURI()); + } + } + } + + const NamespaceResolver::Ptr newResolver(new DelegatingNamespaceResolver(context->namespaceBindings(), overrides)); + const StaticContext::Ptr augmented(new StaticNamespaceContext(newResolver, context)); + + return PairContainer::typeCheck(augmented, reqType); +} + +SequenceType::Ptr ElementConstructor::staticType() const +{ + return CommonSequenceTypes::ExactlyOneElement; +} + +SequenceType::List ElementConstructor::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ExactlyOneQName); + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +Expression::Properties ElementConstructor::properties() const +{ + return DisableElimination | IsNodeConstructor; +} + +ExpressionVisitorResult::Ptr +ElementConstructor::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qelementconstructor_p.h b/src/xmlpatterns/expr/qelementconstructor_p.h new file mode 100644 index 0000000..55c18a2 --- /dev/null +++ b/src/xmlpatterns/expr/qelementconstructor_p.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** 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_ElementConstructor_H +#define Patternist_ElementConstructor_H + +#include <QUrl> + +#include "qpaircontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Constructs an element node. This covers both computed and directly constructed + * element nodes. + * + * @see <a href="http://www.w3.org/TR/xquery/#id-constructors">XQuery + * 1.0: An XML Query Language, 3.7 Constructors</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ElementConstructor : public PairContainer + { + public: + ElementConstructor(const Expression::Ptr &operand1, + const Expression::Ptr &operand2, + const bool isXSLT); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + virtual SequenceType::Ptr staticType() const; + + /** + * The first operand must be exactly one @c xs:QName, and the second + * argument can be zero or more items. + */ + virtual SequenceType::List expectedOperandTypes() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + virtual Properties properties() const; + + private: + QUrl m_staticBaseURI; + const bool m_isXSLT; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qemptycontainer.cpp b/src/xmlpatterns/expr/qemptycontainer.cpp new file mode 100644 index 0000000..4681fc0 --- /dev/null +++ b/src/xmlpatterns/expr/qemptycontainer.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include <QList> + +#include "qemptycontainer_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +Expression::List EmptyContainer::operands() const +{ + return Expression::List(); +} + +SequenceType::List EmptyContainer::expectedOperandTypes() const +{ + return SequenceType::List(); +} + +void EmptyContainer::setOperands(const Expression::List &) +{ +} + +bool EmptyContainer::compressOperands(const StaticContext::Ptr &) +{ + return true; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qemptycontainer_p.h b/src/xmlpatterns/expr/qemptycontainer_p.h new file mode 100644 index 0000000..d1eace6 --- /dev/null +++ b/src/xmlpatterns/expr/qemptycontainer_p.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** 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_EmptyContainer_H +#define Patternist_EmptyContainer_H + +#include "qexpression_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Base class for expressions that has no operands. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class Q_AUTOTEST_EXPORT EmptyContainer : public Expression + { + public: + /** + * @returns always an empty list. + */ + virtual Expression::List operands() const; + + /** + * Does nothing, since sub-classes has no operands. Calling + * it makes hence no sense, and it also results in an assert crash. + */ + virtual void setOperands(const Expression::List &); + + protected: + /** + * @returns always @c true + */ + virtual bool compressOperands(const StaticContext::Ptr &context); + + /** + * @returns always an empty list since it has no operands. + */ + virtual SequenceType::List expectedOperandTypes() const; + + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qemptysequence.cpp b/src/xmlpatterns/expr/qemptysequence.cpp new file mode 100644 index 0000000..66b6381 --- /dev/null +++ b/src/xmlpatterns/expr/qemptysequence.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonvalues_p.h" +#include "qcommonsequencetypes_p.h" +#include "qemptysequencetype_p.h" + +#include "qemptysequence_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +Expression::Ptr EmptySequence::create(const Expression *const replacementFor, + const StaticContext::Ptr &context) +{ + Q_ASSERT(replacementFor); + Q_ASSERT(context); + + const Expression::Ptr retval(new EmptySequence()); + context->wrapExpressionWith(replacementFor, retval); + return retval; +} + +Item::Iterator::Ptr EmptySequence::evaluateSequence(const DynamicContext::Ptr &) const +{ + return CommonValues::emptyIterator; +} + +Item EmptySequence::evaluateSingleton(const DynamicContext::Ptr &) const +{ + return Item(); +} + +void EmptySequence::evaluateToSequenceReceiver(const DynamicContext::Ptr &) const +{ +} + +ItemType::Ptr EmptySequence::type() const +{ + return CommonSequenceTypes::Empty; +} + +SequenceType::Ptr EmptySequence::staticType() const +{ + return CommonSequenceTypes::Empty; +} + +bool EmptySequence::evaluateEBV(const DynamicContext::Ptr &) const +{ + return false; +} + +QString EmptySequence::stringValue() const +{ + return QString(); +} + +ExpressionVisitorResult::Ptr EmptySequence::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID EmptySequence::id() const +{ + return IDEmptySequence; +} + +Expression::Properties EmptySequence::properties() const +{ + return IsEvaluated; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qemptysequence_p.h b/src/xmlpatterns/expr/qemptysequence_p.h new file mode 100644 index 0000000..d6a72a2 --- /dev/null +++ b/src/xmlpatterns/expr/qemptysequence_p.h @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** 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_EmptySequence_H +#define Patternist_EmptySequence_H + +#include "qemptycontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Implements the value instance of empty sequence: <tt>()</tt>. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_xdm + */ + class EmptySequence : public EmptyContainer + { + public: + /** + * @short Creates an EmptySequence that is a replacement for @p + * replacementFor. + * + * @see EmptySequence() + */ + static Expression::Ptr create(const Expression *const replacementFor, + const StaticContext::Ptr &context); + + + /** + * @short Creates an instance of EmptySequence. + * + * @note In most cases create() should be used, since it takes care of + * adjusting source location annotations. + * + * @see create() + */ + inline EmptySequence() + { + } + + virtual QString stringValue() const; + + /** + * @returns always an empty iterator, an instance of EmptyIterator. + */ + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &) const; + + /** + * @returns always @c null. + */ + virtual Item evaluateSingleton(const DynamicContext::Ptr &) const; + + /** + * Does nothing. + */ + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &) const; + + /** + * @returns always @c false. + */ + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + + /** + * @returns always CommonSequenceTypes::Empty + */ + virtual ItemType::Ptr type() const; + + /** + * @returns always CommonSequenceTypes::Empty + */ + virtual SequenceType::Ptr staticType() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual ID id() const; + virtual Properties properties() const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qevaluationcache.cpp b/src/xmlpatterns/expr/qevaluationcache.cpp new file mode 100644 index 0000000..2d1bb56 --- /dev/null +++ b/src/xmlpatterns/expr/qevaluationcache.cpp @@ -0,0 +1,274 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +/** + * @file + * @short This file is included by qevaluationcache_p.h. + * If you need includes in this file, put them in qevaluationcache_p.h, outside of the namespace. + */ + +template<bool IsForGlobal> +EvaluationCache<IsForGlobal>::EvaluationCache(const Expression::Ptr &op, + const VariableDeclaration::Ptr &varDecl, + const VariableSlotID aSlot) : SingleContainer(op) + , m_declaration(varDecl) + , m_varSlot(aSlot) +{ + Q_ASSERT(m_declaration); + Q_ASSERT(m_varSlot > -1); +} + +template<bool IsForGlobal> +DynamicContext::Ptr EvaluationCache<IsForGlobal>::topFocusContext(const DynamicContext::Ptr &context) +{ + DynamicContext::Ptr result(context); + + while(true) + { + DynamicContext::Ptr candidate(result->previousContext()); + + /* We want the top focus, not GenericDynamicContext. */ + if(candidate && candidate->focusIterator()) + result = candidate; + else + return result; + } +} + +template<bool IsForGlobal> +Item EvaluationCache<IsForGlobal>::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + ItemCacheCell &cell = IsForGlobal ? context->globalItemCacheCell(m_varSlot) : context->itemCacheCell(m_varSlot); + + if(cell.cacheState == ItemCacheCell::Full) + return cell.cachedItem; + else + { + Q_ASSERT(cell.cacheState == ItemCacheCell::Empty); + cell.cachedItem = m_operand->evaluateSingleton(IsForGlobal ? topFocusContext(context) : context); + cell.cacheState = ItemCacheCell::Full; + return cell.cachedItem; + } +} + +#if defined(Q_OS_IRIX) && defined(Q_CC_MIPS) +/** + * @short Compile workaround for MIPSPro on IRIX. + * + * This function is never called. + * + * It's mere presence means the MIPSPro compiler can accept some other code below. + * + * I recommend Buddism. + */ +static inline Item::Iterator::Ptr workaroundIrixMIPSPro(const ItemSequenceCacheCell &cell) +{ + return Item::Iterator::Ptr(new ListIterator<Item, Item::List>(cell.cachedItems)); +} +#endif + +template<bool IsForGlobal> +Item::Iterator::Ptr EvaluationCache<IsForGlobal>::evaluateSequence(const DynamicContext::Ptr &context) const +{ + ItemSequenceCacheCell::Vector &cells = IsForGlobal ? context->globalItemSequenceCacheCells(m_varSlot) : context->itemSequenceCacheCells(m_varSlot); + ItemSequenceCacheCell &cell = cells[m_varSlot]; + + + if(cell.inUse) + { + context->error(QtXmlPatterns::tr("Circularity detected"), + ReportContext::XTDE0640, this); + } + + switch(cell.cacheState) + { + case ItemSequenceCacheCell::Full: + { + /** + * We don't use makeListIterator() here because the MIPSPro compiler can't handle it. + */ + return Item::Iterator::Ptr(new ListIterator<Item, Item::List>(cell.cachedItems)); + } + case ItemSequenceCacheCell::Empty: + { + cell.inUse = true; + cell.sourceIterator = m_operand->evaluateSequence(IsForGlobal ? topFocusContext(context) : context); + cell.cacheState = ItemSequenceCacheCell::PartiallyPopulated; + /* Fallthrough. */ + } + case ItemSequenceCacheCell::PartiallyPopulated: + { + cell.inUse = false; + Q_ASSERT_X(cells.at(m_varSlot).sourceIterator, Q_FUNC_INFO, + "This trigger for a cache bug which hasn't yet been analyzed."); + return Item::Iterator::Ptr(new CachingIterator(cells, m_varSlot, IsForGlobal ? topFocusContext(context) : context)); + } + default: + { + Q_ASSERT_X(false, Q_FUNC_INFO, "This path is not supposed to be run."); + return Item::Iterator::Ptr(); + } + } +} + +template<bool IsForGlobal> +Expression::Ptr EvaluationCache<IsForGlobal>::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + /* It's important that we do the typeCheck() before checking for the use of local variables, + * because ExpressionVariableReference can reference an expression that is a local variable, + * so it must rewrite itself to it operand before, and it does that in EvaluationCache::typeCheck(). */ + const Expression::Ptr me(SingleContainer::typeCheck(context, reqType)); + + OperandsIterator it(me, OperandsIterator::ExcludeParent); + Expression::Ptr next(it.next()); + + /* If our operand or any sub operand gets its value from a for-loop, we cannot + * cache it since then our cache would be filled -- but not invalidated -- on the + * first for-iteration. Consider this query: + * + * <tt>for $i in expr + * let $v := $i/p + * return ($v, $v)</tt> + * + * An evaluation cache is inserted for the two operands in the return clause. However, + * $i changes for each iteration so the cache can only be active on a per-iteration basis, + * it it's possible(which it isn't). + * + * This means that for some queries we don't cache what we really should, and hence evaluate + * in a sub-optimal way, since this DependsOnLocalVariable don't communicate whether it references + * a loop that affects us. The correct fix for this would be to let ForExpression reset the + * relevant caches only, but we don't know which ones that are. */ + while(next) + { + if(next->has(DependsOnLocalVariable)) + return m_operand->typeCheck(context, reqType); + + next = it.next(); + } + + return me; +} + +template<bool IsForGlobal> +Expression::Ptr EvaluationCache<IsForGlobal>::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr me(SingleContainer::compress(context)); + + if(me != this) + return me; + + if(m_operand->is(IDRangeVariableReference)) + return m_operand; + + if(m_declaration->usedByMany()) + { + /* If it's only an atomic value an EvaluationCache is overkill. However, + * it's still needed for functions like fn:current-time() that must adhere to + * query stability. */ + const Properties props(m_operand->properties()); + + if(props.testFlag(EvaluationCacheRedundant) || + ((props.testFlag(IsEvaluated)) && + !props.testFlag(DisableElimination) && + CommonSequenceTypes::ExactlyOneAtomicType->matches(m_operand->staticType()))) + { + return m_operand; + } + else + return me; + } + else + { + /* If we're only used once, there's no need for an EvaluationCache. */ + return m_operand; + } +} + +template<bool IsForGlobal> +SequenceType::Ptr EvaluationCache<IsForGlobal>::staticType() const +{ + return m_operand->staticType(); +} + +template<bool IsForGlobal> +SequenceType::List EvaluationCache<IsForGlobal>::expectedOperandTypes() const +{ + /* Remember that EvaluationCache::typeCheck() will be called from multiple locations, + * which potentially have different type requirements. For instance, one wants a node, + * and another requires atomization and casting. + * + * Returning ZeroOrMoreItems is safe here because staticType() returns the operand's type + * and therefore the convertors like Atomizer will be parents to us, and hence only affect + * the relevant path. + * + * ZeroOrMoreItems also make sense logically since we're actually only used where the + * variable references reference us. */ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + + return result; +} + +template<bool IsForGlobal> +Expression::Properties EvaluationCache<IsForGlobal>::properties() const +{ + /* We cannot return the operand's properties unconditionally, because some + * doesn't hold for this Expression. + * + * However, some of the properties must propagate through, which are the ones being OR'd here. + */ + return m_operand->properties() & (DisableElimination | IsEvaluated | DisableTypingDeduction); +} + +template<bool IsForGlobal> +ExpressionVisitorResult::Ptr +EvaluationCache<IsForGlobal>::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +template<bool IsForGlobal> +const SourceLocationReflection *EvaluationCache<IsForGlobal>::actualReflection() const +{ + return m_operand->actualReflection(); +} + diff --git a/src/xmlpatterns/expr/qevaluationcache_p.h b/src/xmlpatterns/expr/qevaluationcache_p.h new file mode 100644 index 0000000..86aeaf8 --- /dev/null +++ b/src/xmlpatterns/expr/qevaluationcache_p.h @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** 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_EvaluationCache_H +#define Patternist_EvaluationCache_H + +#include "qcachingiterator_p.h" +#include "qcommonsequencetypes_p.h" +#include "qnodebuilder_p.h" +#include "qoperandsiterator_p.h" +#include "qsinglecontainer_p.h" +#include "qvariabledeclaration_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Evaluates to the same result as its operand, but ensures the + * operand is evaluated once even if this Expression is evaluated several + * times. + * + * EvaluationCache does this in a pipelined way, by delivering items from + * its cache, which is stored in the DynamicContext. If the cache has less + * items than what the caller requests, EvaluationCache continues to + * deliver but this time from the source, which it also populates into the + * cache. + * + * EvaluationCache is used as an optimization in order to avoid running + * expensive code paths multiple times, but also is sometimes a necessity: + * for instance, when objects must be unique, such as potentially in the + * case of node identity. + * + * EvaluationCache is in particular used for variables, whose sole purpose + * is to store it once(at least conceptually) and then use it in multiple + * places. + * + * In some cases an EvaluationCache isn't necessary. For instance, when a + * variable is only referenced once. In those cases EvaluationCache removes + * itself as an optimization; implemented in compress(). + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + template<bool IsForGlobal> + class EvaluationCache : public SingleContainer + { + public: + EvaluationCache(const Expression::Ptr &operand, + const VariableDeclaration::Ptr &varDecl, + const VariableSlotID slot); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + + virtual SequenceType::Ptr staticType() const; + + /** + * The first operand must be exactly one @c xs:string. + */ + virtual SequenceType::List expectedOperandTypes() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual Properties properties() const; + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + virtual const SourceLocationReflection *actualReflection() const; + + inline VariableSlotID slot() const + { + return m_varSlot; + } + + private: + static DynamicContext::Ptr topFocusContext(const DynamicContext::Ptr &context); + const VariableDeclaration::Ptr m_declaration; + /** + * This variable must not be called m_slot. If it so, a compiler bug on + * HP-UX-aCC-64 is triggered in the constructor initializor. See the + * preprocessor output. + * + * Note that this is the cache slot, and is disjoint to any variable's + * regular slot. + */ + const VariableSlotID m_varSlot; + }; + +#include "qevaluationcache.cpp" +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qexpression.cpp b/src/xmlpatterns/expr/qexpression.cpp new file mode 100644 index 0000000..7a045e8 --- /dev/null +++ b/src/xmlpatterns/expr/qexpression.cpp @@ -0,0 +1,414 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qboolean_p.h" +#include "qcommonvalues_p.h" +#include "qemptysequence_p.h" +#include "qliteral_p.h" +#include "qliteralsequence_p.h" +#include "qoperandsiterator_p.h" +#include "qoptimizerframework_p.h" +#include "qstaticfocuscontext_p.h" +#include "qtypechecker_p.h" + +#include "qexpression_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +Expression::~Expression() +{ +} + +StaticContext::Ptr Expression::finalizeStaticContext(const StaticContext::Ptr &context) const +{ + Q_ASSERT(context); + const ItemType::Ptr focusType(newFocusType()); + Q_ASSERT(focusType); + return StaticContext::Ptr(new StaticFocusContext(focusType, context)); +} + +Expression::Ptr Expression::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + Q_ASSERT(reqType); + typeCheckOperands(context); + return TypeChecker::applyFunctionConversion(Expression::Ptr(this), reqType, context); +} + +void Expression::typeCheckOperands(const StaticContext::Ptr &context) +{ + const Expression::List ops(operands()); + + /* Check if this expression has any operands at all. */ + if(ops.isEmpty()) + return; /* We're done, early exit. */ + + const SequenceType::List opTypes(expectedOperandTypes()); + Expression::List result; + + /* If we create a focus, we handle the last one specially, so avoid it in the loop. */ + const bool createsFocus = has(CreatesFocusForLast); + const SequenceType::List::const_iterator typeEnd(createsFocus ? --opTypes.constEnd() + : opTypes.constEnd()); + const Expression::List::const_iterator end(createsFocus ? --ops.constEnd() + : ops.constEnd()); + + SequenceType::List::const_iterator reqType(opTypes.constBegin()); + SequenceType::Ptr t(*reqType); + // TODO we assign twice to t here(also below in loop) when ops.size() > 1 + + Expression::List::const_iterator it(ops.constBegin()); + + for(; it != end; ++it) + { + /* This ensures that the last expectedOperandType stays, and is + * used for all other operands. This is used for expressions that + * have an infinite amount of operands, such as the concat() function. */ + if(reqType != typeEnd) + { + t = *reqType; + ++reqType; + } + + /* Let the child & its children typecheck. */ + result.append((*it)->typeCheck(context, t)); + } + + if(createsFocus) + { + const StaticContext::Ptr newContext(finalizeStaticContext(context)); + result.append(ops.last()->typeCheck(newContext, opTypes.last())); + } + + setOperands(result); +} + +Expression::Ptr Expression::invokeOptimizers(const Expression::Ptr &expr, + const StaticContext::Ptr &context) +{ + Q_ASSERT(expr); + + const OptimizationPass::List opts(expr->optimizationPasses()); + + if(opts.isEmpty()) /* Early exit. */ + { + return expr; + } + + const OptimizationPass::List::const_iterator passEnd(opts.constEnd()); + const OptimizationPass::List::const_iterator end(opts.constEnd()); + OptimizationPass::List::const_iterator passIt(opts.constBegin()); + + for(; passIt != passEnd; ++passIt) /* Invoke each optimization pass. */ + { + const OptimizationPass::Ptr pass(*passIt); /* Alias, for readability. */ + OptimizationPass::ExpressionMarker sourceMarker(pass->sourceExpression); + + if(pass->startIdentifier && !pass->startIdentifier->matches(expr)) + { + /* This pass specified a start identifier and it did + * not match -- let's try the next OptimizationPass. */ + continue; + } + + const ExpressionIdentifier::List::const_iterator idEnd(pass->operandIdentifiers.constEnd()); + ExpressionIdentifier::List::const_iterator idIt(pass->operandIdentifiers.constBegin()); + const Expression::List ops(expr->operands()); + const Expression::List::const_iterator opEnd(ops.constEnd()); + Expression::List::const_iterator opIt(ops.constBegin()); + + switch(pass->operandsMatchMethod) + { + case OptimizationPass::Sequential: + { + for(; opIt != opEnd; ++opIt) + { + const Expression::Ptr operand(*opIt); /* Alias, for readability. */ + const ExpressionIdentifier::Ptr opIdentifier(*idIt); /* Alias, for readability. */ + if(opIdentifier && !opIdentifier->matches(operand)) + { + break; + } + + ++idIt; + } + + if(opIt == opEnd) + break; /* All operands matched, so this pass matched. */ + else + { + /* The loop above did not finish which means all operands did not match. + Therefore, this OptimizationPass did not match -- let's try the next one. */ + continue; + } + } + case OptimizationPass::AnyOrder: + { + Q_ASSERT_X(ops.count() == 2, Q_FUNC_INFO, + "AnyOrder is currently only supported for Expressions with two operands."); + if(pass->operandIdentifiers.first()->matches(ops.first()) && + pass->operandIdentifiers.last()->matches(ops.last())) + { + break; + } + else if(pass->operandIdentifiers.first()->matches(ops.last()) && + pass->operandIdentifiers.last()->matches(ops.first())) + { + sourceMarker.first() = 1; + sourceMarker[1] = 0; + break; /* This pass matched. */ + } + else + continue; /* This pass didn't match, let's loop through the next pass. */ + } + } + + /* Figure out the source Expression, if any. */ + Expression::List operands; + Expression::Ptr sourceExpr; + + if(!sourceMarker.isEmpty()) + { + const OptimizationPass::ExpressionMarker::const_iterator mEnd(sourceMarker.constEnd()); + OptimizationPass::ExpressionMarker::const_iterator mIt(sourceMarker.constBegin()); + sourceExpr = expr; + + for(; mIt != mEnd; ++mIt) + { + Q_ASSERT(*mIt >= 0); + sourceExpr = sourceExpr->operands().at(*mIt); + } + + operands.append(sourceExpr); + } + + if(operands.isEmpty()) + { + Q_ASSERT(pass->resultCreator); + return pass->resultCreator->create(Expression::List(), context, expr.data())->compress(context); + } + else if(pass->resultCreator) + return pass->resultCreator->create(operands, context, expr.data())->compress(context); + else + { + return sourceExpr; + } + } + + return expr; +} + +Expression::Ptr Expression::compress(const StaticContext::Ptr &context) +{ + if(!compressOperands(context)) + { + /* At least one of the operands cannot be evaluated at compile, so + * 'this' Expression cannot const fold. */ + return invokeOptimizers(Expression::Ptr(this), context); + } + + Expression::Ptr retval; + + if(hasDependency(DisableElimination)) + retval = Expression::Ptr(this); + else + retval = constantPropagate(context); + + return invokeOptimizers(retval, context); +} + +Expression::Ptr Expression::constantPropagate(const StaticContext::Ptr &context) const +{ + Q_ASSERT(context); + + /* Optimization: We rewrite literals to literals here, which is pointless. + * Maybe we should have a property which says "doesn't disable elimination + * but don't eliminate me." */ + if(staticType()->cardinality().allowsMany()) + { + Item::Iterator::Ptr it(evaluateSequence(context->dynamicContext())); + Item::List result; + Item item(it->next()); + + while(item) + { + result.append(item); + item = it->next(); + } + + switch(result.count()) + { + case 0: + return EmptySequence::create(this, context); + case 1: + return rewrite(Expression::Ptr(new Literal(result.first())), context); + default: + return rewrite(Expression::Ptr(new LiteralSequence(result)), context); + } + } + else + { + const Item item(evaluateSingleton(context->dynamicContext())); + + if(item) + return rewrite(Expression::Ptr(new Literal(item)), context); + else + return EmptySequence::create(this, context); + } +} + +Item::Iterator::Ptr Expression::evaluateSequence(const DynamicContext::Ptr &context) const +{ + const Item item(evaluateSingleton(context)); + + if(item) + return makeSingletonIterator(item); + else + return CommonValues::emptyIterator; +} + +Item Expression::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + return Boolean::fromValue(evaluateEBV(context)); +} + +bool Expression::evaluateEBV(const DynamicContext::Ptr &context) const +{ + return Boolean::evaluateEBV(evaluateSequence(context), context); +} + +void Expression::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + QAbstractXmlReceiver *const receiver = context->outputReceiver(); + const Item::Iterator::Ptr it(evaluateSequence(context)); + Item next(it->next()); + + while(next) + { + receiver->item(next); + next = it->next(); + } +} + +ItemType::Ptr Expression::expectedContextItemType() const +{ + Q_ASSERT_X(false, Q_FUNC_INFO, + "expectedContextItemType() must be overridden when RequiresContextItem is set."); + return ItemType::Ptr(); +} + +Expression::Properties Expression::properties() const +{ + return Properties(); +} + +Expression::Properties Expression::dependencies() const +{ + OperandsIterator it(Ptr(const_cast<Expression *>(this)), OperandsIterator::ExcludeParent); + Expression::Ptr next(it.next()); + + Properties dependencies(properties()); + + while(next) + { + dependencies |= next->dependencies(); + next = it.next(); + } + + return dependencies & (Expression::RequiresFocus | Expression::IsEvaluated | Expression::DisableElimination); +} + +void Expression::announceFocusType(const ItemType::Ptr &itemType) +{ + const Expression::List ops(operands()); + const int len = ops.count(); + + for(int i = 0; i < len; ++i) + ops.at(i)->announceFocusType(itemType); +} + +Expression::Properties Expression::deepProperties() const +{ + Properties props(properties()); + const Expression::List ops(operands()); + const int len = ops.count(); + + for(int i = 0; i < len; ++i) + props |= ops.at(i)->deepProperties(); + + return props; +} + +Expression::ID Expression::id() const +{ + return IDIgnorableExpression; +} + +OptimizationPass::List Expression::optimizationPasses() const +{ + return OptimizationPass::List(); +} + +ItemType::Ptr Expression::newFocusType() const +{ + Q_ASSERT_X(false, Q_FUNC_INFO, + "This function must be overridden when CreatesFocusForLast is set."); + return ItemType::Ptr(); +} + +const SourceLocationReflection *Expression::actualReflection() const +{ + return this; +} + +QString Expression::description() const +{ + return QString::fromLatin1("Expression, id: %1").arg(QString::number(id())); +} + +PatternPriority Expression::patternPriority() const +{ + return 0.5; +} + +QT_END_NAMESPACE 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 diff --git a/src/xmlpatterns/expr/qexpressiondispatch_p.h b/src/xmlpatterns/expr/qexpressiondispatch_p.h new file mode 100644 index 0000000..23b2408 --- /dev/null +++ b/src/xmlpatterns/expr/qexpressiondispatch_p.h @@ -0,0 +1,241 @@ +/**************************************************************************** +** +** 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_ExpressionDispatch_H +#define Patternist_ExpressionDispatch_H + +#include <QSharedData> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + class AndExpression; + class ApplyTemplate; + class ArgumentConverter; + class ArgumentReference; + class ArithmeticExpression; + class Atomizer; + class AttributeConstructor; + class AttributeNameValidator; + class AxisStep; + class CallTemplate; + class CardinalityVerifier; + class CardinalityVerifier; + class CastableAs; + class CastableAs; + class CastAs; + class CastAs; + class CollationChecker; + class CollationChecker; + class CombineNodes; + class CombineNodes; + class CommentConstructor; + class CommentConstructor; + class ComputedNamespaceConstructor; + class ContextItem; + class CopyOf; + class CurrentItemStore; + class DocumentConstructor; + class DynamicContextStore; + class EBVExtractor; + class ElementConstructor; + class EmptySequence; + class ExpressionSequence; + class ExpressionVariableReference; + class ExternalVariableReference; + class FirstItemPredicate; + class ForClause; + class FunctionCall; + class GeneralComparison; + class GenericPredicate; + class IfThenClause; + class InstanceOf; + class ItemVerifier; + class LetClause; + class Literal; + class LiteralSequence; + class NamespaceConstructor; + class NCNameConstructor; + class NodeComparison; + class NodeSortExpression; + class OrderBy; + class OrExpression; + class ParentNodeAxis; + class Path; + class PositionalVariableReference; + class ProcessingInstructionConstructor; + class QNameConstructor; + class QuantifiedExpression; + class RangeExpression; + class RangeVariableReference; + class ReturnOrderBy; + class SimpleContentConstructor; + class StaticBaseURIStore; + class StaticCompatibilityStore; + class TemplateParameterReference; + class TextNodeConstructor; + class TreatAs; + class TruthPredicate; + class UnresolvedVariableReference; + class UntypedAtomicConverter; + class UserFunctionCallsite; + class ValidationError; + class ValueComparison; + template<bool IsForGlobal> class EvaluationCache; + + /** + * @todo Documentation's missing + * + * @defgroup Patternist_expr_dispatch Expression Dispatching + */ + + /** + * @ingroup Patternist_expr_dispatch + * @author Frans Englich <frans.englich@nokia.com> + */ + class ExpressionVisitorResult : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer<ExpressionVisitorResult> Ptr; + ExpressionVisitorResult() {} + virtual ~ExpressionVisitorResult() {} + }; + + /** + * @ingroup Patternist_expr_dispatch + * @author Frans Englich <frans.englich@nokia.com> + */ + class ExpressionVisitor : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer<ExpressionVisitor> Ptr; + virtual ~ExpressionVisitor() {} + + virtual ExpressionVisitorResult::Ptr visit(const AndExpression *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ApplyTemplate *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ArgumentConverter *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ArgumentReference *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ArithmeticExpression *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const Atomizer *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const AttributeConstructor *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const AttributeNameValidator *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const AxisStep *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const CallTemplate *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const CardinalityVerifier *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const CastableAs *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const CastAs *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const CollationChecker *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const CombineNodes *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const CommentConstructor *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ComputedNamespaceConstructor *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ContextItem *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const CopyOf *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const CurrentItemStore *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const DocumentConstructor *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const DynamicContextStore *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const EBVExtractor *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ElementConstructor *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const EmptySequence *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const EvaluationCache<false> *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const EvaluationCache<true> *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ExpressionSequence *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ExpressionVariableReference *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ExternalVariableReference *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const FirstItemPredicate *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ForClause *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const FunctionCall *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const GeneralComparison *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const GenericPredicate *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const IfThenClause *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const InstanceOf *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ItemVerifier *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const LetClause *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const Literal *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const LiteralSequence *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const NamespaceConstructor *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const NCNameConstructor *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const NodeComparison *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const NodeSortExpression *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const OrderBy *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const OrExpression *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ParentNodeAxis *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const Path *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const PositionalVariableReference *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ProcessingInstructionConstructor *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const QNameConstructor *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const QuantifiedExpression *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const RangeExpression *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const RangeVariableReference *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ReturnOrderBy *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const SimpleContentConstructor *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const StaticBaseURIStore *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const StaticCompatibilityStore *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const TemplateParameterReference *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const TextNodeConstructor *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const TreatAs *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const TruthPredicate *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const UnresolvedVariableReference *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const UntypedAtomicConverter *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const UserFunctionCallsite *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ValidationError *) const = 0; + virtual ExpressionVisitorResult::Ptr visit(const ValueComparison *) const = 0; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qexpressionfactory.cpp b/src/xmlpatterns/expr/qexpressionfactory.cpp new file mode 100644 index 0000000..861b980 --- /dev/null +++ b/src/xmlpatterns/expr/qexpressionfactory.cpp @@ -0,0 +1,473 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include <QBuffer> +#include <QByteArray> + +#include "qcalltemplate_p.h" +#include "qcommonsequencetypes_p.h" +#include "qdebug_p.h" +#include "qexpression_p.h" +#include "qgenericstaticcontext_p.h" +#include "qoperandsiterator_p.h" +#include "qoptimizationpasses_p.h" +#include "qparsercontext_p.h" +#include "qpath_p.h" +#include "qquerytransformparser_p.h" +#include "qstaticfocuscontext_p.h" +#include "qtokenrevealer_p.h" +#include "qxquerytokenizer_p.h" +#include "qxslttokenizer_p.h" + +#include "qexpressionfactory_p.h" + +QT_BEGIN_NAMESPACE + +namespace QPatternist { + +/** + * @short The entry point to the parser. + * + * @param info supplies the information the parser & scanner + * needs to create expressions. The created expression, if everything + * succeeds, can be retrieved via the object @p info points to. + * @returns non-negative if the parser fails. + * @see ExpressionFactory::createExpression() + */ +extern int XPathparse(QPatternist::ParserContext *const info); + +Expression::Ptr ExpressionFactory::createExpression(const QString &expr, + const StaticContext::Ptr &context, + const QXmlQuery::QueryLanguage lang, + const SequenceType::Ptr &requiredType, + const QUrl &queryURI, + const QXmlName &initialTemplateName) +{ + if(lang == QXmlQuery::XSLT20) + { + QByteArray query(expr.toUtf8()); + QBuffer buffer(&query); + buffer.open(QIODevice::ReadOnly); + + return createExpression(&buffer, + context, + lang, + requiredType, + queryURI, + initialTemplateName); + } + else + { + return createExpression(Tokenizer::Ptr(new XQueryTokenizer(expr, queryURI)), + context, + lang, + requiredType, + queryURI, + initialTemplateName); + } +} + +Expression::Ptr ExpressionFactory::createExpression(QIODevice *const device, + const StaticContext::Ptr &context, + const QXmlQuery::QueryLanguage lang, + const SequenceType::Ptr &requiredType, + const QUrl &queryURI, + const QXmlName &initialTemplateName) +{ + Q_ASSERT(device); + Q_ASSERT(device->isReadable()); + + Tokenizer::Ptr tokenizer; + + if(lang == QXmlQuery::XSLT20) + tokenizer = Tokenizer::Ptr(new XSLTTokenizer(device, queryURI, context, context->namePool())); + else + tokenizer = Tokenizer::Ptr(new XQueryTokenizer(QString::fromUtf8(device->readAll()), queryURI)); + + return createExpression(tokenizer, context, lang, requiredType, queryURI, initialTemplateName); +} + +Expression::Ptr ExpressionFactory::createExpression(const Tokenizer::Ptr &tokenizer, + const StaticContext::Ptr &context, + const QXmlQuery::QueryLanguage lang, + const SequenceType::Ptr &requiredType, + const QUrl &queryURI, + const QXmlName &initialTemplateName) +{ + Q_ASSERT(context); + Q_ASSERT(requiredType); + Q_ASSERT(queryURI.isValid()); + + Tokenizer::Ptr effectiveTokenizer(tokenizer); +#ifdef Patternist_DEBUG + effectiveTokenizer = Tokenizer::Ptr(new TokenRevealer(queryURI, tokenizer)); +#endif + + OptimizationPasses::Coordinator::init(); + + const ParserContext::Ptr info(new ParserContext(context, lang, effectiveTokenizer.data())); + info->initialTemplateName = initialTemplateName; + + effectiveTokenizer->setParserContext(info); + + const int bisonRetval = XPathparse(info.data()); + + Q_ASSERT_X(bisonRetval == 0, Q_FUNC_INFO, + "We shouldn't be able to get an error, because we throw exceptions."); + Q_UNUSED(bisonRetval); /* Needed when not compiled in debug mode, since bisonRetval won't + * be used in the Q_ASSERT_X above. */ + + Expression::Ptr result(info->queryBody); + + if(!result) + { + context->error(QtXmlPatterns::tr("A library module cannot be evaluated " + "directly. It must be imported from a " + "main module."), + ReportContext::XPST0003, + QSourceLocation(queryURI, 1, 1)); + } + + /* Optimization: I think many things are done in the wrong order below. We + * probably want everything typechecked before compressing, since we can + * have references all over the place(variable references, template + * invocations, function callsites). This could even be a source to bugs. + */ + + /* Here, we type check user declared functions and global variables. This + * means that variables and functions that are not used are type + * checked(which they otherwise wouldn't have been), and those which are + * used, are type-checked twice, unfortunately. */ + + const bool hasExternalFocus = context->contextItemType(); + + if(lang == QXmlQuery::XSLT20) + { + /* Bind xsl:call-template instructions to their template bodies. + * + * We do this before type checking and compressing them, because a + * CallTemplate obviously needs its template before being compressed. + * + * Also, we do this before type checking and compressing user + * functions, since they can contain template call sites. + */ + for(int i = 0; i < info->templateCalls.count(); ++i) + { + CallTemplate *const site = info->templateCalls.at(i)->as<CallTemplate>(); + const QXmlName targetName(site->name()); + const Template::Ptr t(info->namedTemplates.value(targetName)); + + if(t) + site->setTemplate(t); + else + { + context->error(QtXmlPatterns::tr("No template by name %1 exists.").arg(formatKeyword(context->namePool(), targetName)), + ReportContext::XTSE0650, + site); + } + } + } + + /* Type check and compress user functions. */ + { + const UserFunction::List::const_iterator end(info->userFunctions.constEnd()); + UserFunction::List::const_iterator it(info->userFunctions.constBegin()); + + /* If the query has a focus(which is common, in the case of a + * stylesheet), we must ensure that the focus isn't visible in the + * function body. */ + StaticContext::Ptr effectiveContext; + + if(hasExternalFocus) + { + effectiveContext = StaticContext::Ptr(new StaticFocusContext(ItemType::Ptr(), + context)); + } + else + effectiveContext = context; + + for(; it != end; ++it) + { + pDebug() << "----- User Function Typecheck -----"; + registerLastPath((*it)->body()); + + /* We will most likely call body()->typeCheck() again, once for + * each callsite. That is, it will be called from + * UserFunctionCallsite::typeCheck(), which will be called + * indirectly when we check the query body. */ + const Expression::Ptr typeCheck((*it)->body()->typeCheck(effectiveContext, + (*it)->signature()->returnType())); + /* We don't have to call (*it)->setBody(typeCheck) here since it's + * only used directly below. */ + processTreePass(typeCheck, UserFunctionTypeCheck); + pDebug() << "------------------------------"; + + pDebug() << "----- User Function Compress -----"; + const Expression::Ptr comp(typeCheck->compress(effectiveContext)); + (*it)->setBody(comp); + processTreePass(comp, UserFunctionCompression); + pDebug() << "------------------------------"; + } + } + + /* Type check and compress global variables. */ + { + const VariableDeclaration::Stack::const_iterator vend(info->variables.constEnd()); + VariableDeclaration::Stack::const_iterator vit(info->variables.constBegin()); + for(; vit != vend; ++vit) + { + Q_ASSERT(*vit); + /* This is a bit murky, the global variable will have it + * Expression::typeCheck() function called from all its references, + * but we also want to check it here globally, so we do + * typechecking using a proper focus. */ + if((*vit)->type == VariableDeclaration::ExternalVariable) + continue; + + pDebug() << "----- Global Variable Typecheck -----"; + Q_ASSERT((*vit)->expression()); + /* We supply ZeroOrMoreItems, meaning the variable can evaluate to anything. */ + // FIXME which is a source to bugs + // TODO What about compressing variables? + const Expression::Ptr + nev((*vit)->expression()->typeCheck(context, CommonSequenceTypes::ZeroOrMoreItems)); + processTreePass(nev, GlobalVariableTypeCheck); + pDebug() << "------------------------------"; + } + } + + /* Do all tests specific to XSL-T. */ + if(lang == QXmlQuery::XSLT20) + { + /* Type check and compress named templates. */ + { + pDebug() << "Have " << info->namedTemplates.count() << "named templates"; + + QMutableHashIterator<QXmlName, Template::Ptr> it(info->namedTemplates); + + while(it.hasNext()) + { + it.next(); + processNamedTemplate(it.key(), it.value()->body, TemplateInitial); + + it.value()->body = it.value()->body->typeCheck(context, CommonSequenceTypes::ZeroOrMoreItems); + processNamedTemplate(it.key(), it.value()->body, TemplateTypeCheck); + + it.value()->body = it.value()->body->compress(context); + processNamedTemplate(it.key(), it.value()->body, TemplateCompress); + + it.value()->compileParameters(context); + } + } + + /* Type check and compress template rules. */ + { + QHashIterator<QXmlName, TemplateMode::Ptr> it(info->templateRules); + + /* Since a pattern can exist of AxisStep, its typeCheck() stage + * requires a focus. In the case that we're invoked with a name but + * no focus, this will yield a compile error, unless we declare a + * focus manually. This only needs to be done for the pattern + * expression, since the static type of the pattern is used as the + * static type for the focus of the template body. */ + StaticContext::Ptr patternContext; + if(hasExternalFocus) + patternContext = context; + else + patternContext = StaticContext::Ptr(new StaticFocusContext(BuiltinTypes::node, context)); + + /* For each template pattern. */ + while(it.hasNext()) + { + it.next(); + const TemplateMode::Ptr &mode = it.value(); + const int len = mode->templatePatterns.count(); + TemplatePattern::ID currentTemplateID = -1; + bool hasDoneItOnce = false; + + /* For each template pattern. */ + for(int i = 0; i < len; ++i) + { + /* We can't use references for these two members, since we + * assign to them. */ + const TemplatePattern::Ptr &pattern = mode->templatePatterns.at(i); + Expression::Ptr matchPattern(pattern->matchPattern()); + + processTemplateRule(pattern->templateTarget()->body, + pattern, mode->name(), TemplateInitial); + + matchPattern = matchPattern->typeCheck(patternContext, CommonSequenceTypes::ZeroOrMoreItems); + matchPattern = matchPattern->compress(patternContext); + pattern->setMatchPattern(matchPattern); + + if(currentTemplateID == -1 && hasDoneItOnce) + { + currentTemplateID = pattern->id(); + continue; + } + else if(currentTemplateID == pattern->id() && hasDoneItOnce) + { + hasDoneItOnce = false; + continue; + } + + hasDoneItOnce = true; + currentTemplateID = pattern->id(); + Expression::Ptr body(pattern->templateTarget()->body); + + /* Patterns for a new template has started, we must + * deal with the body & parameters. */ + { + /* TODO type is wrong, it has to be the union of all + * patterns. */ + const StaticContext::Ptr focusContext(new StaticFocusContext(matchPattern->staticType()->itemType(), + context)); + body = body->typeCheck(focusContext, CommonSequenceTypes::ZeroOrMoreItems); + + pattern->templateTarget()->compileParameters(focusContext); + } + + processTemplateRule(body, pattern, mode->name(), TemplateTypeCheck); + + body = body->compress(context); + + pattern->templateTarget()->body = body; + processTemplateRule(body, pattern, mode->name(), TemplateCompress); + } + + mode->finalize(); + } + } + + /* Add templates in mode #all to all other modes. + * + * We do this after the templates has been typechecked and compressed, + * since otherwise it will be done N times for the built-in templates, + * where N is the count of different templates, instead of once. */ + { + const QXmlName nameModeAll(QXmlName(StandardNamespaces::InternalXSLT, + StandardLocalNames::all)); + const TemplateMode::Ptr &modeAll = info->templateRules[nameModeAll]; + + Q_ASSERT_X(modeAll, Q_FUNC_INFO, + "We should at least have the builtin templates."); + QHashIterator<QXmlName, TemplateMode::Ptr> it(info->templateRules); + + while(it.hasNext()) + { + it.next(); + + /* Don't add mode #all to mode #all. */ + if(it.key() == nameModeAll) + continue; + + it.value()->addMode(modeAll); + } + } + } + + /* Type check and compress the query body. */ + { + pDebug() << "----- Initial AST build. -----"; + processTreePass(result, QueryBodyInitial); + pDebug() << "------------------------------"; + + pDebug() << "----- Type Check -----"; + registerLastPath(result); + result->rewrite(result, result->typeCheck(context, requiredType), context); + processTreePass(result, QueryBodyTypeCheck); + pDebug() << "------------------------------"; + + pDebug() << "----- Compress -----"; + result->rewrite(result, result->compress(context), context); + processTreePass(result, QueryBodyCompression); + pDebug() << "------------------------------"; + } + + return result; +} + +void ExpressionFactory::registerLastPath(const Expression::Ptr &operand) +{ + OperandsIterator it(operand, OperandsIterator::IncludeParent); + Expression::Ptr next(it.next()); + + while(next) + { + if(next->is(Expression::IDPath)) + { + next->as<Path>()->setLast(); + next = it.skipOperands(); + } + else + next = it.next(); + } +} + +void ExpressionFactory::processTreePass(const Expression::Ptr &, + const CompilationStage) +{ +} + +void ExpressionFactory::processTemplateRule(const Expression::Ptr &body, + const TemplatePattern::Ptr &pattern, + const QXmlName &mode, + const TemplateCompilationStage stage) +{ + Q_UNUSED(body); + Q_UNUSED(pattern); + Q_UNUSED(mode); + Q_UNUSED(stage); +} + +void ExpressionFactory::processNamedTemplate(const QXmlName &name, + const Expression::Ptr &tree, + const TemplateCompilationStage stage) +{ + Q_UNUSED(name); + Q_UNUSED(tree); + Q_UNUSED(stage); +} + +} // namespace QPatternist + +QT_END_NAMESPACE + diff --git a/src/xmlpatterns/expr/qexpressionfactory_p.h b/src/xmlpatterns/expr/qexpressionfactory_p.h new file mode 100644 index 0000000..07235bb --- /dev/null +++ b/src/xmlpatterns/expr/qexpressionfactory_p.h @@ -0,0 +1,187 @@ +/**************************************************************************** +** +** 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_ExpressionFactory_H +#define Patternist_ExpressionFactory_H + +#include <QXmlQuery> + +#include "qexpression_p.h" +#include "qtokenizer_p.h" + +#include <QSharedData> +#include <QUrl> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QIODevice; + +namespace QPatternist +{ + /** + * @short The central entry point for compiling expressions. + * + * @ingroup Patternist_expressions + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_AUTOTEST_EXPORT ExpressionFactory : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer<ExpressionFactory> Ptr; + + /** + * @short This constructor cannot be synthesized since we + * use the Q_DISABLE_COPY macro. + */ + inline ExpressionFactory() + { + } + + virtual ~ExpressionFactory() + { + } + + enum CompilationStage + { + QueryBodyInitial = 1, + QueryBodyTypeCheck = 1 << 1, + QueryBodyCompression = 1 << 2, + UserFunctionTypeCheck = 1 << 3, + UserFunctionCompression = 1 << 4, + GlobalVariableTypeCheck = 1 << 5 + }; + + /** + * Creates a compiled representation of the XPath expression @p expr, with Static + * Context information supplied via @p context. This is for example whether the expression + * is an XPath 1.0 or XPath 2.0 expression, or what functions that are available. + * + * @p requiredType specifies what type results of the evaluating the expression + * must match. Passing CommonValues::ZeroOrMoreItems allows anything as result, while + * passing CommonSequenceTypes::EBV means anything but an Effective %Boolean Value extractable + * result is a type error, for example. + * + * @note An empty @p expr is an invalid XPath expression. It will be reported as such, + * but it is neverthless the caller's resonsibility to ensure that it's not that(since + * it is likely invalid already in the medium it was stored). + */ + virtual Expression::Ptr createExpression(const QString &expr, + const StaticContext::Ptr &context, + const QXmlQuery::QueryLanguage lang, + const SequenceType::Ptr &requiredType, + const QUrl &queryURI, + const QXmlName &initialTemplateName); + + virtual Expression::Ptr createExpression(QIODevice *const device, + const StaticContext::Ptr &context, + const QXmlQuery::QueryLanguage lang, + const SequenceType::Ptr &requiredType, + const QUrl &queryURI, + const QXmlName &initialTemplateName); + + /** + * Finds the last paths of a set of paths(if any) and tells the Path + * so, such that it can generate the code for checking XPTY0018. + * + * Must be called before typeCheck() is called on the operand, since + * the typeCheck() uses the information for type checking. + */ + static void registerLastPath(const Expression::Ptr &operand); + + protected: + enum TemplateCompilationStage + { + TemplateInitial = 1, + TemplateTypeCheck = 1 << 1, + TemplateCompress = 1 << 2 + }; + + /** + * This function is called by createExpression() each time + * after a pass on the AST has been completed. Under a typical + * compilation this function is thus called three times: after the initial + * build, after the Expression::typeCheck() stage, and after + * Expression::compress(). @p tree is the AST after each pass. + * + * This mechanism is currently used for debugging, since it provides a + * way of introspecting what the compilation process do to the tree. The + * current implementation do nothing. + */ + virtual void processTreePass(const Expression::Ptr &tree, + const CompilationStage stage); + + virtual void processTemplateRule(const Expression::Ptr &body, + const TemplatePattern::Ptr &pattern, + const QXmlName &mode, + const TemplateCompilationStage stage); + + virtual void processNamedTemplate(const QXmlName &name, + const Expression::Ptr &tree, + const TemplateCompilationStage stage); + + Expression::Ptr createExpression(const Tokenizer::Ptr &tokenizer, + const StaticContext::Ptr &context, + const QXmlQuery::QueryLanguage lang, + const SequenceType::Ptr &requiredType, + const QUrl &queryURI, + const QXmlName &initialTemplateName); + private: + Q_DISABLE_COPY(ExpressionFactory) + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qexpressionsequence.cpp b/src/xmlpatterns/expr/qexpressionsequence.cpp new file mode 100644 index 0000000..a4d1ba6 --- /dev/null +++ b/src/xmlpatterns/expr/qexpressionsequence.cpp @@ -0,0 +1,206 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcardinalityverifier_p.h" +#include "qcommonsequencetypes_p.h" +#include "qemptysequence_p.h" +#include "qsequencemappingiterator_p.h" + +#include "qexpressionsequence_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ExpressionSequence::ExpressionSequence(const Expression::List &ops) : UnlimitedContainer(ops) +{ + Q_ASSERT_X(1 < ops.count(), Q_FUNC_INFO, + "It makes no sense to have an ExpressionSequence containing less than two expressions."); +} + +Item::Iterator::Ptr ExpressionSequence::mapToSequence(const Expression::Ptr &expr, + const DynamicContext::Ptr &context) const +{ + return expr->evaluateSequence(context); +} + +Item::Iterator::Ptr ExpressionSequence::evaluateSequence(const DynamicContext::Ptr &context) const +{ + return makeSequenceMappingIterator<Item>(ConstPtr(this), + makeListIterator(m_operands), + context); +} + +void ExpressionSequence::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + Expression::List::const_iterator it(m_operands.constBegin()); + const Expression::List::const_iterator end(m_operands.constEnd()); + Expression::List result; + + for(; it != end; ++it) + (*it)->evaluateToSequenceReceiver(context); +} + +Expression::Ptr ExpressionSequence::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr me(UnlimitedContainer::compress(context)); + + if(me != this) + return me; + + Expression::List::const_iterator it(m_operands.constBegin()); + const Expression::List::const_iterator end(m_operands.constEnd()); + Expression::List result; + + for(; it != end; ++it) + { + const ID Id = (*it)->id(); + + /* Remove empty sequences. This is rather important because we have some steps in the parser that + * intentionally, unconditionally and for temporary reasons create expressions like (expr, ()). Of course, + * empty sequences also occur as part of optimizations. + * + * User function call sites that are of type empty-sequence() must be avoided since + * they may contain calls to fn:error(), which we would rewrite away otherwise. */ + if(Id != IDUserFunctionCallsite && (*it)->staticType()->cardinality().isEmpty()) + { + /* Rewrite "(1, (), 2)" into "(1, 2)" by not + * adding (*it) to result. */ + continue; + } + else if(Id == IDExpressionSequence) + { + /* Rewrite "(1, (2, 3), 4)" into "(1, 2, 3, 4)" */ + Expression::List::const_iterator seqIt((*it)->operands().constBegin()); + const Expression::List::const_iterator seqEnd((*it)->operands().constEnd()); + + for(; seqIt != seqEnd; ++seqIt) + result.append(*seqIt); + } + else + result.append(*it); + } + + if(result.isEmpty()) + return EmptySequence::create(this, context); + else if(result.count() == 1) + return result.first(); + else + { + m_operands = result; + return me; + } +} + +Expression::Ptr ExpressionSequence::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + Q_ASSERT(reqType); + Expression::List::iterator it(m_operands.begin()); + const Expression::List::iterator end(m_operands.end()); + + /* We treat the cardinality differently here by allowing the empty sequence + * for each individual Expression, since the Cardinality can be conformed to by + * the ExpressionSequence as a whole(which we check for at the end). */ + const SequenceType::Ptr testOnlyIT(makeGenericSequenceType(reqType->itemType(), + Cardinality::empty() | + reqType->cardinality())); + + for(; it != end; ++it) + *it = (*it)->typeCheck(context, testOnlyIT); + + /* The above loop is only guaranteed to find item type errors, but the cardinality + * can still be wrong since the operands were treated individually. */ + return CardinalityVerifier::verifyCardinality(Expression::Ptr(this), reqType->cardinality(), context); +} + +Expression::Properties ExpressionSequence::properties() const +{ + const Expression::List::const_iterator end(m_operands.constEnd()); + Expression::List::const_iterator it; + bool allEvaled = true; + Expression::Properties props(DisableElimination); /* Why do we have this flag? */ + + for(it = m_operands.constBegin(); it != end; ++it) + { + const Expression::Properties newp((*it)->properties()); + props |= newp; + + if((newp & IsEvaluated) != IsEvaluated) + { + allEvaled = false; + break; + } + } + + if(!allEvaled) + props &= ~IsEvaluated; /* Remove IsEvaluated. */ + + /* One of our children might need the focus, but we don't, so + * cut it out. */ + return props & ~RequiresFocus; +} + +SequenceType::Ptr ExpressionSequence::staticType() const +{ + return operandsUnionType<ProductOfCardinality>(); +} + +SequenceType::List ExpressionSequence::expectedOperandTypes() const +{ + SequenceType::List result; + /* ExpressionSequence is a bit strange type wise since it has an + * infinite amount of operands. */ + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +ExpressionVisitorResult::Ptr ExpressionSequence::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID ExpressionSequence::id() const +{ + return IDExpressionSequence; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qexpressionsequence_p.h b/src/xmlpatterns/expr/qexpressionsequence_p.h new file mode 100644 index 0000000..5074489 --- /dev/null +++ b/src/xmlpatterns/expr/qexpressionsequence_p.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** 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_ExpressionSequence_H +#define Patternist_ExpressionSequence_H + +#include "qunlimitedcontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Implements the comma(",") operator, the sequence constructor. + * + * For example, the expression <tt>alpha, beta</tt> evaluates to a sequence + * containing the items the nodetest @c alpha evaluates to, concatenated + * with the items the nodetest @c beta evaluates to. + * + * @see <a href="http://www.w3.org/TR/xpath20/#construct_seq">XML Path Language + * (XPath) 2.0, 3.3.1 Constructing Sequences</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ExpressionSequence : public UnlimitedContainer + { + public: + /** + * Creates an ExpressionSequence with the operands @p operands. @p operands + * must contain two or more Expression instances. + */ + ExpressionSequence(const Expression::List &operands); + + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &) const; + + /** + * Forwards the call to its children. + */ + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + virtual SequenceType::List expectedOperandTypes() const; + virtual SequenceType::Ptr staticType() const; + + /** + * Removes any empty sequences, typically "()", from its list of children. If + * after that rewrite has no children, it rewrites itself to the CommonValues::empty; + * if it has only one, it rewrites to the child. + * + * This optimization is not very usable by itself, but potentially becomes effective after other + * optimizations have rewritten themselves into empty sequences. Thus, + * saving memory consumption and runtime overhead. + */ + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + + inline Item::Iterator::Ptr mapToSequence(const Expression::Ptr &, + const DynamicContext::Ptr &) const; + + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + /** + * @returns Expression::DisableElimination, plus the union + * of all this ExpressionSequence's children's properties. If any child + * does not have IsEvaluated, it is removed from the result. + */ + virtual Expression::Properties properties() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual ID id() const; + private: + typedef QExplicitlySharedDataPointer<const ExpressionSequence> ConstPtr; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qexpressionvariablereference.cpp b/src/xmlpatterns/expr/qexpressionvariablereference.cpp new file mode 100644 index 0000000..3b9ecb1 --- /dev/null +++ b/src/xmlpatterns/expr/qexpressionvariablereference.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + + +#include "qexpressionvariablereference_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ExpressionVariableReference::ExpressionVariableReference(const VariableSlotID slotP, + const VariableDeclaration::Ptr &varDecl) : VariableReference(slotP) + , m_varDecl(varDecl) +{ +} + +bool ExpressionVariableReference::evaluateEBV(const DynamicContext::Ptr &context) const +{ + return context->expressionVariable(slot())->evaluateEBV(context); +} + +Item ExpressionVariableReference::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + return context->expressionVariable(slot())->evaluateSingleton(context); +} + +Item::Iterator::Ptr ExpressionVariableReference::evaluateSequence(const DynamicContext::Ptr &context) const +{ + return context->expressionVariable(slot())->evaluateSequence(context); +} +Expression::Ptr ExpressionVariableReference::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + if(m_varDecl->canSourceRewrite) + return m_varDecl->expression()->typeCheck(context, reqType); + else + return VariableReference::typeCheck(context, reqType); +} + +Expression::ID ExpressionVariableReference::id() const +{ + return IDExpressionVariableReference; +} + +ExpressionVisitorResult::Ptr ExpressionVariableReference::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +SequenceType::Ptr ExpressionVariableReference::staticType() const +{ + return m_varDecl->expression()->staticType(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qexpressionvariablereference_p.h b/src/xmlpatterns/expr/qexpressionvariablereference_p.h new file mode 100644 index 0000000..40c835e --- /dev/null +++ b/src/xmlpatterns/expr/qexpressionvariablereference_p.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** 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_ExpressionVariableReference_H +#define Patternist_ExpressionVariableReference_H + +#include "qvariabledeclaration_p.h" +#include "qvariablereference_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A reference to a variable declared with <tt>declare variable</tt> or @c let. + * + * It's also used by variable bindings in @c case branches of the @c typeswitch + * expression. + * + * This AST node is only used up until the typeCheck() stage. Therefore it + * has no functions for evaluation, such as evaluateSequence(). + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ExpressionVariableReference : public VariableReference + { + public: + ExpressionVariableReference(const VariableSlotID slot, + const VariableDeclaration::Ptr &varDecl); + + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + virtual SequenceType::Ptr staticType() const; + virtual ID id() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + inline const Expression::Ptr &sourceExpression() const; + inline const VariableDeclaration::Ptr &variableDeclaration() const; + private: + const VariableDeclaration::Ptr m_varDecl; + }; + + inline const Expression::Ptr &ExpressionVariableReference::sourceExpression() const + { + return m_varDecl->expression(); + } + + inline const VariableDeclaration::Ptr &ExpressionVariableReference::variableDeclaration() const + { + return m_varDecl; + } + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qexternalvariableloader.cpp b/src/xmlpatterns/expr/qexternalvariableloader.cpp new file mode 100644 index 0000000..2099cb6 --- /dev/null +++ b/src/xmlpatterns/expr/qexternalvariableloader.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qboolean_p.h" +#include "qcommonvalues_p.h" +#include "qdynamiccontext_p.h" + +#include "qexternalvariableloader_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ExternalVariableLoader::~ExternalVariableLoader() +{ +} + + +SequenceType::Ptr ExternalVariableLoader::announceExternalVariable(const QXmlName name, + const SequenceType::Ptr &declaredType) +{ + Q_ASSERT(!name.isNull()); + Q_ASSERT(declaredType); + Q_UNUSED(name); /* Needed when compiling in release mode. */ + Q_UNUSED(declaredType); /* Needed when compiling in release mode. */ + + return SequenceType::Ptr(); +} + +Item::Iterator::Ptr ExternalVariableLoader::evaluateSequence(const QXmlName name, + const DynamicContext::Ptr &context) +{ + Q_ASSERT(!name.isNull()); + const Item item(evaluateSingleton(name, context)); + + if(item) + return makeSingletonIterator(item); + else + return CommonValues::emptyIterator; +} + +Item ExternalVariableLoader::evaluateSingleton(const QXmlName name, + const DynamicContext::Ptr &context) +{ + Q_ASSERT(!name.isNull()); + return Boolean::fromValue(evaluateEBV(name, context)); +} + +bool ExternalVariableLoader::evaluateEBV(const QXmlName name, + const DynamicContext::Ptr &context) +{ + Q_ASSERT(!name.isNull()); + return Boolean::evaluateEBV(evaluateSequence(name, context), context); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qexternalvariableloader_p.h b/src/xmlpatterns/expr/qexternalvariableloader_p.h new file mode 100644 index 0000000..5dc3af5 --- /dev/null +++ b/src/xmlpatterns/expr/qexternalvariableloader_p.h @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** 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_ExternalVariableLoader_H +#define Patternist_ExternalVariableLoader_H + +#include "qitem_p.h" +#include "qsequencetype_p.h" +#include "qxmlname.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + class DynamicContext; + + /** + * @short Responsible for loading and declaring available external variables. + * + * An external variable in XQuery is a global variable that has been declared to receive + * its value from the XQuery implementation, as opposed to an initializing expression. Here + * is an example of a query with an external variable declaration, followed by a ordinary + * global variable: + * + * <tt> declare variable $theName external; + * declare variable $theName := "the value"; + * "And here's the query body(a string literal)"</tt> + * + * An external variable declaration can also specify a sequence type: + * + * <tt>declare variable $theName as xs:integer external;</tt> + * + * This class allows the user to supply the values to external variables. When + * an external variable declaration occur in the query, + * announceExternalVariable() is called. + * + * @ingroup Patternist_xdm + * @author Frans Englich <frans.englich@nokia.com> + */ + class Q_AUTOTEST_EXPORT ExternalVariableLoader : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer<ExternalVariableLoader> Ptr; + inline ExternalVariableLoader() {} + + virtual ~ExternalVariableLoader(); + + /** + * Called when Patternist encounters an external variable in the query. It is guaranteed + * to be called once for each external variable appearing in a query module. + * + * @param name the name of the variable. Quaranteed to never be @c null. + * @param declaredType the type that the user declared the variable to be of. Whether + * this type matches the actual value of the variable or not is irrelevant. Patternist + * will do the necessary error handling based on the sequence type that is returned from + * this function. If the user didn't declare a type, the type is <tt>item()*</tt>(zero or + * more items). Quaranteed to never be @c null. + * @returns the sequence type of the value this ExternalVariableLoader actually supplies. However, + * if the ExternalVariableLoader knows it cannot supply a variable by this name, @c null should be + * returned. + */ + virtual SequenceType::Ptr announceExternalVariable(const QXmlName name, + const SequenceType::Ptr &declaredType); + + /** + * This function is called at runtime when the external variable by name @p name needs + * to be evaluated. It is not defined how many times this function will be called. It + * depends on aspects such as how the query was optimized. + * + * @param name the name of the variable. Quaranteed to never be @c null. + * @param context the DynamicContext. + * @returns the value of the variable. Remember that this value must match the + * sequence type returned from announceExternalVariable() for the same name. + */ + virtual Item::Iterator::Ptr evaluateSequence(const QXmlName name, + const QExplicitlySharedDataPointer<DynamicContext> &context); + + virtual Item evaluateSingleton(const QXmlName name, + const QExplicitlySharedDataPointer<DynamicContext> &context); + virtual bool evaluateEBV(const QXmlName name, + const QExplicitlySharedDataPointer<DynamicContext> &context); + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qexternalvariablereference.cpp b/src/xmlpatterns/expr/qexternalvariablereference.cpp new file mode 100644 index 0000000..8016cc5 --- /dev/null +++ b/src/xmlpatterns/expr/qexternalvariablereference.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + + +#include "qexternalvariablereference_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ExternalVariableReference::ExternalVariableReference(const QXmlName &name, + const SequenceType::Ptr &type) : m_name(name), + m_seqType(type) +{ + Q_ASSERT(!m_name.isNull()); + Q_ASSERT(m_seqType); +} + +Item::Iterator::Ptr ExternalVariableReference::evaluateSequence(const DynamicContext::Ptr &context) const +{ + Q_ASSERT(context->externalVariableLoader()); + return context->externalVariableLoader()->evaluateSequence(m_name, context); +} + +Item ExternalVariableReference::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + return context->externalVariableLoader()->evaluateSingleton(m_name, context); +} + +bool ExternalVariableReference::evaluateEBV(const DynamicContext::Ptr &context) const +{ + return context->externalVariableLoader()->evaluateEBV(m_name, context); +} + +SequenceType::Ptr ExternalVariableReference::staticType() const +{ + return m_seqType; +} + +Expression::Properties ExternalVariableReference::properties() const +{ + return DisableElimination; +} + +ExpressionVisitorResult::Ptr ExternalVariableReference::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qexternalvariablereference_p.h b/src/xmlpatterns/expr/qexternalvariablereference_p.h new file mode 100644 index 0000000..96d0dd2 --- /dev/null +++ b/src/xmlpatterns/expr/qexternalvariablereference_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** 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_ExternalVariableReference_H +#define Patternist_ExternalVariableReference_H + +#include "qemptycontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A reference to an external variable. + * + * ExternalVariableReference does not sub-class VariableReference, because it + * works differently from how sub-classes of VariableReference do. This class + * uses DynamicContext::externalVariableLoader() for retrieving its value, while + * a VariableReference sub-class uses slots in the DynamicContext. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ExternalVariableReference : public EmptyContainer + { + public: + ExternalVariableReference(const QXmlName &name, + const SequenceType::Ptr &type); + + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + + virtual SequenceType::Ptr staticType() const; + + /** + * @returns always DisableElimination + */ + virtual Expression::Properties properties() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + private: + const QXmlName m_name; + const SequenceType::Ptr m_seqType; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qfirstitempredicate.cpp b/src/xmlpatterns/expr/qfirstitempredicate.cpp new file mode 100644 index 0000000..651dff3 --- /dev/null +++ b/src/xmlpatterns/expr/qfirstitempredicate.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qgenericsequencetype_p.h" + +#include "qfirstitempredicate_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +FirstItemPredicate::FirstItemPredicate(const Expression::Ptr &source) : SingleContainer(source) +{ +} + +Item FirstItemPredicate::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + /* If our operand allows the empty sequence, this function can return Item(), otherwise + * it returns the first item. As simple as that. */ + return m_operand->evaluateSequence(context)->next(); +} + +SequenceType::Ptr FirstItemPredicate::staticType() const +{ + const SequenceType::Ptr t(m_operand->staticType()); + return makeGenericSequenceType(t->itemType(), t->cardinality().toWithoutMany()); +} + +Expression::Ptr FirstItemPredicate::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr me(SingleContainer::compress(context)); + if(me != this) + return me; + + if(m_operand->is(IDFirstItemPredicate)) + m_operand = m_operand->operands().first(); + + return me; +} + +SequenceType::List FirstItemPredicate::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +ExpressionVisitorResult::Ptr FirstItemPredicate::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID FirstItemPredicate::id() const +{ + return IDFirstItemPredicate; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qfirstitempredicate_p.h b/src/xmlpatterns/expr/qfirstitempredicate_p.h new file mode 100644 index 0000000..df44195 --- /dev/null +++ b/src/xmlpatterns/expr/qfirstitempredicate_p.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** 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_FirstItemPredicate_H +#define Patternist_FirstItemPredicate_H + +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A predicate that always selects the first item from its sequence. + * + * FirstItemPredicate corresponds exactly to the predicate + * in the expression <tt>input[1]</tt>. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class FirstItemPredicate : public SingleContainer + { + public: + /** + * Creates a FirstItemPredicate that filters @p source. + */ + FirstItemPredicate(const Expression::Ptr &source); + + /** + * @returns the first item, if any, from evaluating the source expression. + */ + virtual Item evaluateSingleton(const DynamicContext::Ptr &) const; + + /** + * @returns a list containing one CommonSequenceTypes::ZeroOrMoreItems instance. + */ + virtual SequenceType::List expectedOperandTypes() const; + + /** + * @returns a SequenceType where the item type is the same as the source expression + * and where the cardinality is either Cardinality::zeroOrOne() or Cardinality::exactlyOne(), + * depending on the source expression. + */ + virtual SequenceType::Ptr staticType() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + /** + * Rewrites <tt>expression[1][1]</tt> into <tt>expression[1]</tt>. + */ + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + + /** + * @returns always IDFirstItemPredicate. + */ + virtual ID id() const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qforclause.cpp b/src/xmlpatterns/expr/qforclause.cpp new file mode 100644 index 0000000..ad9262b --- /dev/null +++ b/src/xmlpatterns/expr/qforclause.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qemptysequence_p.h" +#include "qgenericsequencetype_p.h" +#include "qitemmappingiterator_p.h" +#include "qoptimizationpasses_p.h" +#include "qsequencemappingiterator_p.h" + +#include "qforclause_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ForClause::ForClause(const VariableSlotID varSlot, + const Expression::Ptr &bindingSequence, + const Expression::Ptr &returnExpression, + const VariableSlotID positionSlot) : PairContainer(bindingSequence, returnExpression), + m_varSlot(varSlot), + m_positionSlot(positionSlot), + m_allowsMany(true) +{ + Q_ASSERT(m_positionSlot > -2); +} + +Item ForClause::mapToItem(const Item &item, + const DynamicContext::Ptr &context) const +{ + context->setRangeVariable(m_varSlot, item); + return m_operand2->evaluateSingleton(context); +} + +Item::Iterator::Ptr ForClause::mapToSequence(const Item &item, + const DynamicContext::Ptr &context) const +{ + context->setRangeVariable(m_varSlot, item); + return m_operand2->evaluateSequence(context); +} + +void ForClause::riggPositionalVariable(const DynamicContext::Ptr &context, + const Item::Iterator::Ptr &source) const +{ + if(m_positionSlot > -1) + context->setPositionIterator(m_positionSlot, source); +} + +Item::Iterator::Ptr ForClause::evaluateSequence(const DynamicContext::Ptr &context) const +{ + const Item::Iterator::Ptr source(m_operand1->evaluateSequence(context)); + + riggPositionalVariable(context, source); + + if(m_allowsMany) + { + return makeSequenceMappingIterator<Item>(ConstPtr(this), + source, + context); + } + else + { + return makeItemMappingIterator<Item>(ConstPtr(this), + source, + context); + } +} + +Item ForClause::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + return evaluateSequence(context)->next(); +} + +void ForClause::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + Item::Iterator::Ptr it; + const Item::Iterator::Ptr source(m_operand1->evaluateSequence(context)); + + riggPositionalVariable(context, source); + + Item next(source->next()); + + while(next) + { + context->setRangeVariable(m_varSlot, next); + m_operand2->evaluateToSequenceReceiver(context); + next = source->next(); + } +} + +Expression::Ptr ForClause::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + const Expression::Ptr me(PairContainer::typeCheck(context, reqType)); + const Cardinality card(m_operand1->staticType()->cardinality()); + + /* If our source is empty we will always evaluate to the empty sequence, so rewrite. */ + if(card.isEmpty()) + return EmptySequence::create(this, context); + else + return me; + + /* This breaks because the variable references haven't rewritten themselves, so + * they dangle. When this is fixed, evaluateSingleton can be removed. */ + /* + else if(card->allowsMany()) + return me; + else + return m_operand2; + */ +} + +Expression::Ptr ForClause::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr me(PairContainer::compress(context)); + if(me != this) + return me; + + /* This is done after calling PairContainer::typeCheck(). The advantage of this is that + * m_allowsMany is updated according to what the operand says after it has compressed. However, + * if it was initialized to false(as it once was..), ForClause::evaluateSequence() + * would potentially have been called by PairContainer::compress(), and it would have + * used an unsafe branch. */ + m_allowsMany = m_operand2->staticType()->cardinality().allowsMany(); + + return me; +} + +SequenceType::Ptr ForClause::staticType() const +{ + const SequenceType::Ptr returnType(m_operand2->staticType()); + + return makeGenericSequenceType(returnType->itemType(), + m_operand1->staticType()->cardinality() + * /* multiply operator */ + returnType->cardinality()); +} + +SequenceType::List ForClause::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +ExpressionVisitorResult::Ptr ForClause::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +OptimizationPass::List ForClause::optimizationPasses() const +{ + return OptimizationPasses::forPasses; +} + +Expression::ID ForClause::id() const +{ + return IDForClause; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qforclause_p.h b/src/xmlpatterns/expr/qforclause_p.h new file mode 100644 index 0000000..5799e0d --- /dev/null +++ b/src/xmlpatterns/expr/qforclause_p.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** 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_ForClause_H +#define Patternist_ForClause_H + +#include "qpaircontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short Implements XPath 2.0's @c for expression. + * + * @see <a href="http://www.w3.org/TR/xpath20/#id-for-expressions">XML Path Language + * (XPath) 2.0, 3.7 For Expressions</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ForClause : public PairContainer + { + public: + /** + * If @p positionSlot is -1, no positional variable will be used. + */ + ForClause(const VariableSlotID varSlot, + const Expression::Ptr &bindingSequence, + const Expression::Ptr &returnExpression, + const VariableSlotID positionSlot); + + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + virtual SequenceType::Ptr staticType() const; + virtual SequenceType::List expectedOperandTypes() const; + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual QList<QExplicitlySharedDataPointer<OptimizationPass> > optimizationPasses() const; + + inline Item mapToItem(const Item &item, + const DynamicContext::Ptr &context) const; + virtual ID id() const; + inline Item::Iterator::Ptr mapToSequence(const Item &item, + const DynamicContext::Ptr &context) const; + + /** + * Sets m_allowsMany properly. + */ + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + + private: + inline void riggPositionalVariable(const DynamicContext::Ptr &context, + const Item::Iterator::Ptr &source) const; + typedef QExplicitlySharedDataPointer<const ForClause> ConstPtr; + const VariableSlotID m_varSlot; + const VariableSlotID m_positionSlot; + /** + * Initialized to @c false. This default is always safe. + */ + bool m_allowsMany; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qgeneralcomparison.cpp b/src/xmlpatterns/expr/qgeneralcomparison.cpp new file mode 100644 index 0000000..a6d6399 --- /dev/null +++ b/src/xmlpatterns/expr/qgeneralcomparison.cpp @@ -0,0 +1,297 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qcommonvalues_p.h" +#include "qebvextractor_p.h" +#include "qitem_p.h" +#include "qliteral_p.h" +#include "qoptimizationpasses_p.h" +#include "quntypedatomicconverter_p.h" +#include "qvaluecomparison_p.h" + +#include "qgeneralcomparison_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +GeneralComparison::GeneralComparison(const Expression::Ptr &op1, + const AtomicComparator::Operator op, + const Expression::Ptr &op2, + const bool isBackwardsCompat) : PairContainer(op1, op2) + , m_operator(op) + , m_isBackwardsCompat(isBackwardsCompat) +{ +} + +bool GeneralComparison::generalCompare(const Item &op1, + const Item &op2, + const DynamicContext::Ptr &context) const +{ + Q_ASSERT(op1); + Q_ASSERT(op2); + + if(comparator()) + return compare(op1, op2, comparator(), m_operator); + + Expression::Ptr a1(new Literal(op1)); + Expression::Ptr a2(new Literal(op2)); + + const AtomicComparator::Ptr comp(fetchGeneralComparator(a1, a2, context)); + /* The fetchGeneralComparator call may rewrite a1 and/or a2. */ + Q_ASSERT(a1); + Q_ASSERT(a2); + Q_ASSERT(comp); + + return compare(a1->evaluateSingleton(context), + a2->evaluateSingleton(context), + comp, + m_operator); +} + +bool GeneralComparison::evaluateEBV(const DynamicContext::Ptr &context) const +{ + const Item::Iterator::Ptr it1(m_operand1->evaluateSequence(context)); + Item item1(it1->next()); + + if(!item1) + return false; + + const Item::Iterator::Ptr it2(m_operand2->evaluateSequence(context)); + Item::List cache; + Item item2; + + while(true) + { + item2 = it2->next(); + if(!item2) + break; + + if(generalCompare(item1, item2, context)) + return true; + + cache.append(item2); + } + + while(true) + { + item1 = it1->next(); + + if(!item1) + return false; + + const Item::List::const_iterator end(cache.constEnd()); + Item::List::const_iterator it(cache.constBegin()); + + for(; it != end; ++it) + if(generalCompare(item1, *it, context)) + return true; + } + + Q_ASSERT(false); + return false; +} + +Expression::Ptr GeneralComparison::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr me(PairContainer::compress(context)); + + if(me != this) + return me; + + if(ValueComparison::isCaseInsensitiveCompare(m_operand1, m_operand2)) + useCaseInsensitiveComparator(); + + return me; +} + +Expression::Ptr GeneralComparison::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + + const Expression::Ptr me(PairContainer::typeCheck(context, reqType)); + + const ItemType::Ptr t1(m_operand1->staticType()->itemType()); + const ItemType::Ptr t2(m_operand2->staticType()->itemType()); + + if(*CommonSequenceTypes::Empty == *t1 || + *CommonSequenceTypes::Empty == *t2) + { + return wrapLiteral(CommonValues::BooleanFalse, context, this); + } + + if(*BuiltinTypes::xsAnyAtomicType == *t1 || + *BuiltinTypes::xsAnyAtomicType == *t2) + return me; + + prepareComparison(fetchGeneralComparator(m_operand1, m_operand2, context)); + + if(!m_operand1->staticType()->cardinality().allowsMany() && + !m_operand2->staticType()->cardinality().allowsMany()) + { + /* Rewrite to a ValueComparison whose operands uses typing rules + * as for an general comparison(that's what's done above). */ + return rewrite(Expression::Ptr(new ValueComparison(m_operand1, + m_operator, + m_operand2))->typeCheck(context, reqType), + context); + } + else + return me; +} + +void GeneralComparison::updateType(ItemType::Ptr &type, + const Expression::Ptr &source) +{ + type = source->staticType()->itemType(); +} + +AtomicComparator::Ptr GeneralComparison::fetchGeneralComparator(Expression::Ptr &op1, + Expression::Ptr &op2, + const ReportContext::Ptr &context) const +{ + ItemType::Ptr t1(op1->staticType()->itemType()); + ItemType::Ptr t2(op2->staticType()->itemType()); + + /* a. "If one of the atomic values is an instance of xs:untypedAtomic and + * the other is an instance of a numeric type, then the xs:untypedAtomic + * value is cast to the type xs:double." */ + if(BuiltinTypes::numeric->xdtTypeMatches(t1) && + BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t2)) + { + op2 = Expression::Ptr(new UntypedAtomicConverter(op2, BuiltinTypes::xsDouble)); + + /* The types might have changed, reload. */ + updateType(t2, op2); + } + else if(BuiltinTypes::numeric->xdtTypeMatches(t2) && + BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t1)) + { + op1 = Expression::Ptr(new UntypedAtomicConverter(op1, BuiltinTypes::xsDouble)); + + /* The types might have changed, reload. */ + updateType(t1, op1); + } + /* "If XPath 1.0 compatibility mode is true, a general comparison is + * evaluated by applying the following rules, in order: + * 1. If either operand is a single atomic value that is an instance of + * xs:boolean, then the other operand is converted to xs:boolean by taking + * its effective boolean value." + * + * Notably, it's not conversion to boolean, it is EBV extraction. + */ + else if(m_isBackwardsCompat && BuiltinTypes::xsBoolean->xdtTypeMatches(t1)) + { + op2 = Expression::Ptr(new EBVExtractor(op2)); + updateType(t2, op2); + } + else if(m_isBackwardsCompat && BuiltinTypes::xsBoolean->xdtTypeMatches(t2)) + { + op1 = Expression::Ptr(new EBVExtractor(op1)); + updateType(t1, op1); + } + /* b. "If one of the atomic values is an instance of xs:untypedAtomic and + * the other is an instance of xs:untypedAtomic or xs:string, then the + * xs:untypedAtomic value (or values) is (are) cast to the type xs:string." + * + * c. "If one of the atomic values is an instance of xs:untypedAtomic and the + * other is not an instance of xs:string, xs:untypedAtomic, or any numeric + * type, then the xs:untypedAtomic value is cast to the dynamic type of the + * other value." */ + else if(BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t1) && + !BuiltinTypes::xsString->xdtTypeMatches(t2) && + !BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t2) && + !BuiltinTypes::xsAnyURI->xdtTypeMatches(t2)) + { + op1 = Expression::Ptr(new UntypedAtomicConverter(op1, t2)); + updateType(t1, op1); + } + else if(BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t2) && + !BuiltinTypes::xsString->xdtTypeMatches(t1) && + !BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t1) && + !BuiltinTypes::xsAnyURI->xdtTypeMatches(t1)) + { + op2 = Expression::Ptr(new UntypedAtomicConverter(op2, t1)); + updateType(t2, op2); + } + + /* d. "After performing the conversions described above, the atomic + * values are compared using one of the value comparison operators + * eq, ne, lt, le, gt, or ge, depending on whether the general comparison + * operator was =, !=, <, <=, >, or >=. The values have the required + * magnitude relationship if and only if the result of this value comparison + * is true." */ + + return fetchComparator(t1, t2, context); +} + +OptimizationPass::List GeneralComparison::optimizationPasses() const +{ + Q_ASSERT(!OptimizationPasses::comparisonPasses.isEmpty()); + return OptimizationPasses::comparisonPasses; +} + +SequenceType::List GeneralComparison::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreAtomicTypes); + result.append(CommonSequenceTypes::ZeroOrMoreAtomicTypes); + return result; +} + +SequenceType::Ptr GeneralComparison::staticType() const +{ + return CommonSequenceTypes::ExactlyOneBoolean; +} + +ExpressionVisitorResult::Ptr GeneralComparison::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID GeneralComparison::id() const +{ + return IDGeneralComparison; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qgeneralcomparison_p.h b/src/xmlpatterns/expr/qgeneralcomparison_p.h new file mode 100644 index 0000000..cc83e22 --- /dev/null +++ b/src/xmlpatterns/expr/qgeneralcomparison_p.h @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** 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_GeneralComparison_H +#define Patternist_GeneralComparison_H + +#include "qatomiccomparator_p.h" +#include "qpaircontainer_p.h" +#include "qcomparisonplatform_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short Implements XPath 2.0's general comparions, such as the <tt>=</tt> operator. + * + * ComparisonPlatform is inherited with @c protected scope because ComparisonPlatform + * must access members of GeneralComparison. + * + * @see <a href="http://www.w3.org/TR/xpath20/#id-general-comparisons">XML Path Language + * (XPath) 2.0, 3.5.2 General Comparisons</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class GeneralComparison : public PairContainer, + public ComparisonPlatform<GeneralComparison, + true /* We want to report errors. */, + AtomicComparator::AsGeneralComparison> + { + public: + GeneralComparison(const Expression::Ptr &op1, + const AtomicComparator::Operator op, + const Expression::Ptr &op2, + const bool isBackwardsCompat = false); + + virtual bool evaluateEBV(const DynamicContext::Ptr &) const; + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + + virtual SequenceType::List expectedOperandTypes() const; + virtual SequenceType::Ptr staticType() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + /** + * @returns always IDGeneralComparison + */ + virtual ID id() const; + + virtual QList<QExplicitlySharedDataPointer<OptimizationPass> > optimizationPasses() const; + + /** + * @returns the operator that this GeneralComparison is using. + */ + inline AtomicComparator::Operator operatorID() const + { + return m_operator; + } + + /** + * Overridden to optimize case-insensitive compares. + */ + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + + private: + static inline void updateType(ItemType::Ptr &type, + const Expression::Ptr &source); + AtomicComparator::Ptr fetchGeneralComparator(Expression::Ptr &op1, + Expression::Ptr &op2, + const ReportContext::Ptr &context) const; + bool generalCompare(const Item &op1, + const Item &op2, + const DynamicContext::Ptr &context) const; + + const AtomicComparator::Operator m_operator; + const bool m_isBackwardsCompat; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qgenericpredicate.cpp b/src/xmlpatterns/expr/qgenericpredicate.cpp new file mode 100644 index 0000000..624d17d --- /dev/null +++ b/src/xmlpatterns/expr/qgenericpredicate.cpp @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qabstractfloat_p.h" +#include "qboolean_p.h" +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qemptysequence_p.h" +#include "qfirstitempredicate_p.h" +#include "qgenericsequencetype_p.h" +#include "qitemmappingiterator_p.h" +#include "qliteral_p.h" +#include "qpatternistlocale_p.h" +#include "qtruthpredicate_p.h" + +#include "qgenericpredicate_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +GenericPredicate::GenericPredicate(const Expression::Ptr &sourceExpression, + const Expression::Ptr &predicate) : PairContainer(sourceExpression, + predicate) +{ +} + +Expression::Ptr GenericPredicate::create(const Expression::Ptr &sourceExpression, + const Expression::Ptr &predicateExpression, + const StaticContext::Ptr &context, + const QSourceLocation &location) +{ + Q_ASSERT(sourceExpression); + Q_ASSERT(predicateExpression); + Q_ASSERT(context); + const ItemType::Ptr type(predicateExpression->staticType()->itemType()); + + if(predicateExpression->is(IDIntegerValue) && + predicateExpression->as<Literal>()->item().as<Numeric>()->toInteger() == 1) + { /* Handle [1] */ + return createFirstItem(sourceExpression); + } + else if(BuiltinTypes::numeric->xdtTypeMatches(type)) + { /* A numeric predicate, other than [1]. */ + /* TODO at somepoint we'll return a specialized expr here, NumericPredicate or so. + * Dependency analysis is a bit tricky, since the contained expression can depend on + * some loop component. */ + return Expression::Ptr(new GenericPredicate(sourceExpression, predicateExpression)); + } + else if(*CommonSequenceTypes::Empty == *type) + { + return EmptySequence::create(predicateExpression.data(), context); + } + else if(*BuiltinTypes::item == *type || + *BuiltinTypes::xsAnyAtomicType == *type) + { + /* The type couldn't be narrowed at compile time, so we use + * a generic predicate. This check is before the CommonSequenceTypes::EBV check, + * because the latter matches these types as well. */ + return Expression::Ptr(new GenericPredicate(sourceExpression, predicateExpression)); + } + else if(CommonSequenceTypes::EBV->itemType()->xdtTypeMatches(type)) + { + return Expression::Ptr(new TruthPredicate(sourceExpression, predicateExpression)); + } + else + { + context->error(QtXmlPatterns::tr("A value of type %1 cannot be a " + "predicate. A predicate must have " + "either a numeric type or an " + "Effective Boolean Value type.") + .arg(formatType(context->namePool(), + sourceExpression->staticType())), + ReportContext::FORG0006, location); + return Expression::Ptr(); /* Silence compiler warning. */ + } +} + +Expression::Ptr GenericPredicate::createFirstItem(const Expression::Ptr &sourceExpression) + +{ + return Expression::Ptr(new FirstItemPredicate(sourceExpression)); +} + +Item GenericPredicate::mapToItem(const Item &item, + const DynamicContext::Ptr &context) const +{ + const Item::Iterator::Ptr it(m_operand2->evaluateSequence(context)); + const Item pcateItem(it->next()); + + if(!pcateItem) + return Item(); /* The predicate evaluated to the empty sequence */ + else if(pcateItem.isNode()) + return item; + /* Ok, now it must be an AtomicValue */ + else if(BuiltinTypes::numeric->xdtTypeMatches(pcateItem.type())) + { /* It's a positional predicate. */ + if(it->next()) + { + context->error(QtXmlPatterns::tr("A positional predicate must " + "evaluate to a single numeric " + "value."), + ReportContext::FORG0006, this); + return Item(); + } + + if(Double::isEqual(static_cast<xsDouble>(context->contextPosition()), + pcateItem.as<Numeric>()->toDouble())) + { + return item; + } + else + return Item(); + } + else if(Boolean::evaluateEBV(pcateItem, it, context)) /* It's a truth predicate. */ + return item; + else + return Item(); +} + +Item::Iterator::Ptr GenericPredicate::evaluateSequence(const DynamicContext::Ptr &context) const +{ + const Item::Iterator::Ptr focus(m_operand1->evaluateSequence(context)); + const DynamicContext::Ptr newContext(context->createFocus()); + newContext->setFocusIterator(focus); + + return makeItemMappingIterator<Item>(ConstPtr(this), + focus, + newContext); +} + +Item GenericPredicate::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + const Item::Iterator::Ptr focus(m_operand1->evaluateSequence(context)); + const DynamicContext::Ptr newContext(context->createFocus()); + newContext->setFocusIterator(focus); + return mapToItem(focus->next(), newContext); +} + +SequenceType::List GenericPredicate::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +SequenceType::Ptr GenericPredicate::staticType() const +{ + const SequenceType::Ptr type(m_operand1->staticType()); + return makeGenericSequenceType(type->itemType(), + type->cardinality() | Cardinality::zeroOrOne()); +} + +ExpressionVisitorResult::Ptr GenericPredicate::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +ItemType::Ptr GenericPredicate::newFocusType() const +{ + return m_operand1->staticType()->itemType(); +} + +Expression::Properties GenericPredicate::properties() const +{ + return CreatesFocusForLast; +} + +QString GenericPredicate::description() const +{ + return QLatin1String("predicate"); +} + +Expression::ID GenericPredicate::id() const +{ + return IDGenericPredicate; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qgenericpredicate_p.h b/src/xmlpatterns/expr/qgenericpredicate_p.h new file mode 100644 index 0000000..d48e208 --- /dev/null +++ b/src/xmlpatterns/expr/qgenericpredicate_p.h @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** 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_GenericPredicate_H +#define Patternist_GenericPredicate_H + +#include "qpaircontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A predicate that can handle all kinds of predicates and + * is therefore not very efficient, but can cope with all the tricky scenarios. + * + * @see FirstItemPredicate + * @see TruthPredicate + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class GenericPredicate : public PairContainer + { + public: + + /** + * Creates a predicate expression that filters the items gained + * from evaluating @p sourceExpression through the filter @p predicateExpression. + * + * This function performs type analyzis on the passed expressions, and may + * return more specialized expressions depending on the analyzis. + * + * If @p predicateExpression is an invalid predicate, an error is issued + * via the @p context. + */ + static Expression::Ptr create(const Expression::Ptr &sourceExpression, + const Expression::Ptr &predicateExpression, + const StaticContext::Ptr &context, + const QSourceLocation &location); + + static Expression::Ptr createFirstItem(const Expression::Ptr &sourceExpression); + + /** + * Creates a source iterator which is passed to the ItemMappingIterator + * and the Focus. The ItemMappingIterator modifies it with + * its QAbstractXmlForwardIterator::next() calls, and since the Focus references the same QAbstractXmlForwardIterator, + * the focus is automatically moved. + */ + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + + /** + * Doesn't return the first item from calling evaluateSequence(), but does the mapping + * manually. This avoid allocating an ItemMappingIterator. + */ + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + + inline Item mapToItem(const Item &subject, + const DynamicContext::Ptr &) const; + + virtual SequenceType::List expectedOperandTypes() const; + virtual SequenceType::Ptr staticType() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual ID id() const; + + /** + * @returns always CreatesFocusForLast. + */ + virtual Properties properties() const; + + virtual QString description() const; + + protected: + + /** + * Creates a GenericPredicate which filters the items from the @p sourceExpression + * through @p predicate. + * + * This constructor is protected. The proper way to create predicates is via the static + * create() function. + */ + GenericPredicate(const Expression::Ptr &sourceExpression, + const Expression::Ptr &predicate); + + /** + * @returns the ItemType of the first operand's staticType(). + */ + virtual ItemType::Ptr newFocusType() const; + + private: + typedef QExplicitlySharedDataPointer<const GenericPredicate> ConstPtr; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qifthenclause.cpp b/src/xmlpatterns/expr/qifthenclause.cpp new file mode 100644 index 0000000..cd9cbc3 --- /dev/null +++ b/src/xmlpatterns/expr/qifthenclause.cpp @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qgenericsequencetype_p.h" +#include "qoptimizationpasses_p.h" + +#include "qifthenclause_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +IfThenClause::IfThenClause(const Expression::Ptr &test, + const Expression::Ptr &then, + const Expression::Ptr &el) : TripleContainer(test, then, el) +{ +} + +Item::Iterator::Ptr IfThenClause::evaluateSequence(const DynamicContext::Ptr &context) const +{ + return m_operand1->evaluateEBV(context) + ? m_operand2->evaluateSequence(context) + : m_operand3->evaluateSequence(context); +} + +Item IfThenClause::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + return m_operand1->evaluateEBV(context) + ? m_operand2->evaluateSingleton(context) + : m_operand3->evaluateSingleton(context); +} + +bool IfThenClause::evaluateEBV(const DynamicContext::Ptr &context) const +{ + return m_operand1->evaluateEBV(context) + ? m_operand2->evaluateEBV(context) + : m_operand3->evaluateEBV(context); +} + +void IfThenClause::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + if(m_operand1->evaluateEBV(context)) + m_operand2->evaluateToSequenceReceiver(context); + else + m_operand3->evaluateToSequenceReceiver(context); +} + +Expression::Ptr IfThenClause::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr me(TripleContainer::compress(context)); + + if(me != this) + return me; + + /* All operands mustn't be evaluated in order for const folding to + * be possible. Let's see how far we get. */ + + if(m_operand1->isEvaluated()) + { + if(m_operand1->evaluateEBV(context->dynamicContext())) + return m_operand2; + else + return m_operand3; + } + else + return me; +} + +QList<QExplicitlySharedDataPointer<OptimizationPass> > IfThenClause::optimizationPasses() const +{ + return OptimizationPasses::ifThenPasses; +} + +SequenceType::List IfThenClause::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::EBV); + result.append(CommonSequenceTypes::ZeroOrMoreItems); + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +SequenceType::Ptr IfThenClause::staticType() const +{ + const SequenceType::Ptr t1(m_operand2->staticType()); + const SequenceType::Ptr t2(m_operand3->staticType()); + + return makeGenericSequenceType(t1->itemType() | t2->itemType(), + t1->cardinality() | t2->cardinality()); +} + +ExpressionVisitorResult::Ptr IfThenClause::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID IfThenClause::id() const +{ + return IDIfThenClause; +} + +/* +Expression::Properties IfThenClause::properties() const +{ + return m_operand1->properties() + | m_operand2->properties() + | m_operand3->properties() + & ( Expression::RequiresFocus + | Expression::IsEvaluated + | Expression::DisableElimination); +} +*/ +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qifthenclause_p.h b/src/xmlpatterns/expr/qifthenclause_p.h new file mode 100644 index 0000000..e24d5d0 --- /dev/null +++ b/src/xmlpatterns/expr/qifthenclause_p.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** 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_IfThenClause_H +#define Patternist_IfThenClause_H + +#include "qtriplecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Implements XPath 2.0's conditional expression <tt>if([expr]) then [expr] else [expr]</tt>. + * + * @see <a href="http://www.w3.org/TR/xpath20/#id-conditionals">XML Path Language (XPath) 2.0, + * 3.8 Conditional Expressions</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class IfThenClause : public TripleContainer + { + public: + IfThenClause(const Expression::Ptr &test, + const Expression::Ptr &then, + const Expression::Ptr &el); + + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + virtual SequenceType::List expectedOperandTypes() const; + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + + virtual SequenceType::Ptr staticType() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + /** + * @returns IDIfThenClause + */ + virtual ID id() const; + virtual QList<QExplicitlySharedDataPointer<OptimizationPass> > optimizationPasses() const; + //virtual Properties properties() const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qinstanceof.cpp b/src/xmlpatterns/expr/qinstanceof.cpp new file mode 100644 index 0000000..8e6e5ce --- /dev/null +++ b/src/xmlpatterns/expr/qinstanceof.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qboolean_p.h" +#include "qcommonsequencetypes_p.h" +#include "qcommonvalues_p.h" +#include "qliteral_p.h" + +#include "qinstanceof_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +InstanceOf::InstanceOf(const Expression::Ptr &operand, + const SequenceType::Ptr &tType) : SingleContainer(operand) + , m_targetType(tType) +{ + Q_ASSERT(m_targetType); +} + +bool InstanceOf::evaluateEBV(const DynamicContext::Ptr &context) const +{ + const Item::Iterator::Ptr it(m_operand->evaluateSequence(context)); + Item item(it->next()); + unsigned int count = 1; + + if(!item) + return m_targetType->cardinality().allowsEmpty(); + + do + { + if(!m_targetType->itemType()->itemMatches(item)) + return false; + + if(count == 2 && !m_targetType->cardinality().allowsMany()) + return false; + + item = it->next(); + ++count; + } while(item); + + return true; +} + +Expression::Ptr InstanceOf::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr me(SingleContainer::compress(context)); + + if(me != this || m_operand->has(DisableTypingDeduction)) + return me; + + const SequenceType::Ptr opType(m_operand->staticType()); + const ItemType::Ptr targetType(m_targetType->itemType()); + const ItemType::Ptr operandType(opType->itemType()); + + if(m_targetType->cardinality().isMatch(opType->cardinality())) + { + if(*operandType == *CommonSequenceTypes::Empty || targetType->xdtTypeMatches(operandType)) + return wrapLiteral(CommonValues::BooleanTrue, context, this); + else if(!operandType->xdtTypeMatches(targetType)) + return wrapLiteral(CommonValues::BooleanFalse, context, this); + } + /* Optimization: rule out the case where instance of will always fail. */ + + return me; +} + +SequenceType::Ptr InstanceOf::targetType() const +{ + return m_targetType; +} + +SequenceType::Ptr InstanceOf::staticType() const +{ + return CommonSequenceTypes::ExactlyOneBoolean; +} + +SequenceType::List InstanceOf::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +ExpressionVisitorResult::Ptr InstanceOf::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qinstanceof_p.h b/src/xmlpatterns/expr/qinstanceof_p.h new file mode 100644 index 0000000..d3da026 --- /dev/null +++ b/src/xmlpatterns/expr/qinstanceof_p.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** 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_InstanceOf_H +#define Patternist_InstanceOf_H + +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short Implements XPath 2.0's <tt>instance of</tt> expression. + * + * @see <a href="http://www.w3.org/TR/xpath20/#id-instance-of">XML Path Language (XPath) 2.0, + * 3.10.1 Instance Of</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class Q_AUTOTEST_EXPORT InstanceOf : public SingleContainer + { + public: + + InstanceOf(const Expression::Ptr &operand, + const SequenceType::Ptr &targetType); + + virtual bool evaluateEBV(const DynamicContext::Ptr &) const; + + virtual SequenceType::List expectedOperandTypes() const; + virtual SequenceType::Ptr staticType() const; + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + /** + * @returns the SequenceType that this <tt>instance of</tt> Expression + * is testing its operand against. + */ + SequenceType::Ptr targetType() const; + + private: + const SequenceType::Ptr m_targetType; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qletclause.cpp b/src/xmlpatterns/expr/qletclause.cpp new file mode 100644 index 0000000..d3e939b --- /dev/null +++ b/src/xmlpatterns/expr/qletclause.cpp @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qboolean_p.h" +#include "qcommonsequencetypes_p.h" +#include "qdynamiccontextstore_p.h" +#include "qliteral_p.h" + +#include "qletclause_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +LetClause::LetClause(const Expression::Ptr &operand1, + const Expression::Ptr &operand2, + const VariableDeclaration::Ptr &decl) : PairContainer(operand1, operand2) + , m_varDecl(decl) +{ + Q_ASSERT(m_varDecl); +} + +DynamicContext::Ptr LetClause::bindVariable(const DynamicContext::Ptr &context) const +{ + context->setExpressionVariable(m_varDecl->slot, Expression::Ptr(new DynamicContextStore(m_operand1, context))); + return context; +} + +Item::Iterator::Ptr LetClause::evaluateSequence(const DynamicContext::Ptr &context) const +{ + return m_operand2->evaluateSequence(bindVariable(context)); +} + +Item LetClause::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + return m_operand2->evaluateSingleton(bindVariable(context)); +} + +bool LetClause::evaluateEBV(const DynamicContext::Ptr &context) const +{ + return m_operand2->evaluateEBV(bindVariable(context)); +} + +void LetClause::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + m_operand2->evaluateToSequenceReceiver(bindVariable(context)); +} + +Expression::Ptr LetClause::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + /* Consider the following query: + * + * <tt>let $d := \<child type=""/> + * return $d//\*[let $i := @type + * return $d//\*[$i]]</tt> + * + * The node test <tt>@type</tt> is referenced from two different places, + * where each reference have a different focus. So, in the case of that the source + * uses the focus, we need to use a DynamicContextStore to ensure the variable + * is always evaluated with the correct focus, regardless of where it is referenced + * from. + * + * We miss out a lot of false positives. For instance, the case of where the focus + * is identical for everyone. One reason we cannot check this, is that Expression + * doesn't know about its parent. + */ + m_varDecl->canSourceRewrite = !m_operand1->deepProperties().testFlag(RequiresFocus); + + if(m_varDecl->canSourceRewrite) + return m_operand2->typeCheck(context, reqType); + else + return PairContainer::typeCheck(context, reqType); +} + +Expression::Properties LetClause::properties() const +{ + return m_varDecl->expression()->properties() & (Expression::RequiresFocus | Expression::IsEvaluated | Expression::DisableElimination); +} + +SequenceType::List LetClause::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +SequenceType::Ptr LetClause::staticType() const +{ + return m_operand2->staticType(); +} + +ExpressionVisitorResult::Ptr LetClause::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID LetClause::id() const +{ + return IDLetClause; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qletclause_p.h b/src/xmlpatterns/expr/qletclause_p.h new file mode 100644 index 0000000..24a7bb1 --- /dev/null +++ b/src/xmlpatterns/expr/qletclause_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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_LetClause_H +#define Patternist_LetClause_H + +#include "qpaircontainer_p.h" +#include "qvariabledeclaration_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short Represents a <tt>let</tt>-clause, but is only used at compile + * time. + * + * LetClause is inserted into the AST tree for the single purpose of + * ensuring that the focus is correct for the binding expression. Once + * that is done, LetClause sometimes rewrites itself to its + * <tt>return</tt> expression, and the ExpressionVariableReference will + * handle the evaluation of the variable. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class LetClause : public PairContainer + { + public: + LetClause(const Expression::Ptr &operand1, + const Expression::Ptr &operand2, + const VariableDeclaration::Ptr &decl); + + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + virtual SequenceType::List expectedOperandTypes() const; + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + virtual SequenceType::Ptr staticType() const; + virtual Properties properties() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual ID id() const; + + private: + inline DynamicContext::Ptr bindVariable(const DynamicContext::Ptr &context) const; + + const VariableDeclaration::Ptr m_varDecl; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qliteral.cpp b/src/xmlpatterns/expr/qliteral.cpp new file mode 100644 index 0000000..ac68fe3 --- /dev/null +++ b/src/xmlpatterns/expr/qliteral.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qboolean_p.h" +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qgenericsequencetype_p.h" + +#include "qliteral_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +Literal::Literal(const Item &i) : m_item(i) +{ + Q_ASSERT(m_item); + Q_ASSERT(m_item.isAtomicValue()); +} + +Item Literal::evaluateSingleton(const DynamicContext::Ptr &) const +{ + return m_item; +} + +bool Literal::evaluateEBV(const DynamicContext::Ptr &context) const +{ + return Boolean::evaluateEBV(m_item, context); +} + +void Literal::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + context->outputReceiver()->item(m_item); +} + +SequenceType::Ptr Literal::staticType() const +{ + return makeGenericSequenceType(m_item.type(), Cardinality::exactlyOne()); +} + +ExpressionVisitorResult::Ptr Literal::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID Literal::id() const +{ + Q_ASSERT(m_item); + Q_ASSERT(m_item.isAtomicValue()); + const ItemType::Ptr t(m_item.type()); + + if(BuiltinTypes::xsBoolean->xdtTypeMatches(t)) + return IDBooleanValue; + else if(BuiltinTypes::xsString->xdtTypeMatches(t) || + BuiltinTypes::xsAnyURI->xdtTypeMatches(t) || + BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t)) + { + return IDStringValue; + } + else if(BuiltinTypes::xsInteger->xdtTypeMatches(t)) + return IDIntegerValue; + else + return IDFloat; +} + +Expression::Properties Literal::properties() const +{ + return IsEvaluated; +} + +QString Literal::description() const +{ + return m_item.stringValue(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qliteral_p.h b/src/xmlpatterns/expr/qliteral_p.h new file mode 100644 index 0000000..aec7d53 --- /dev/null +++ b/src/xmlpatterns/expr/qliteral_p.h @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** 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_Literal_H +#define Patternist_Literal_H + +#include "qemptycontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Houses an AtomicValue, making it available as an Expression. + * + * This is not only literals that can be created via the XQuery syntax(strings and numbers), but + * all other atomic values, such as <tt>xs:date</tt> or <tt>xs:time</tt>. + * + * @see <a href="http://www.w3.org/TR/xquery/#id-literals">XQuery 1.0: An XML Query Language, + * 3.1.1 Literals</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class Literal : public EmptyContainer + { + public: + /** + * Creates a Literal that represents @p item. + * + * @param item must be non-null and cannot be a QXmlNodeModelIndex. + */ + Literal(const Item &item); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + virtual SequenceType::Ptr staticType() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual ID id() const; + virtual QString description() const; + + /** + * @returns Expression::DisableElimination and Expression::IsEvaluated + */ + virtual Properties properties() const; + + /** + * Declaring the return value of this function a const reference, leads + * to crashes in patternistview, for a to me unknown reason. + */ + inline Item item() const + { + return m_item; + } + + private: + const Item m_item; + }; + + /** + * @short Creates a Literal that wraps @p item, and returns it. + * + * This simplifies code. Instead of writing: + * + * @code + * Expression::Ptr(new Literal(item)); + * @endcode + * + * One can write: + * + * @code + * wrapLiteral(item); + * @endcode + * + * This function is not declared static, because it breaks the build on + * at least aix-xlc-64. + * + * @relates Literal + */ + inline Expression::Ptr wrapLiteral(const Item &item, + const StaticContext::Ptr &context, + const SourceLocationReflection *const r) + { + Q_ASSERT(item); + + const Expression::Ptr retval(new Literal(item)); + context->addLocation(retval.data(), context->locationFor(r)); + + return retval; + } +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qliteralsequence.cpp b/src/xmlpatterns/expr/qliteralsequence.cpp new file mode 100644 index 0000000..dfd0fd6 --- /dev/null +++ b/src/xmlpatterns/expr/qliteralsequence.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qgenericsequencetype_p.h" + +#include "qliteralsequence_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +LiteralSequence::LiteralSequence(const Item::List &list) : m_list(list) +{ + Q_ASSERT(list.size() >= 2); +} + +Item::Iterator::Ptr LiteralSequence::evaluateSequence(const DynamicContext::Ptr &) const +{ + return makeListIterator(m_list); +} + +SequenceType::Ptr LiteralSequence::staticType() const +{ + const Item::List::const_iterator end(m_list.constEnd()); + Item::List::const_iterator it(m_list.constBegin()); + + /* Load the first item. */ + ItemType::Ptr t((*it).type()); + ++it; + + for(; end != it; ++it) + t |= (*it).type(); + + return makeGenericSequenceType(t, Cardinality::fromCount(m_list.size())); +} + +ExpressionVisitorResult::Ptr LiteralSequence::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID LiteralSequence::id() const +{ + return IDExpressionSequence; +} + +Expression::Properties LiteralSequence::properties() const +{ + return IsEvaluated; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qliteralsequence_p.h b/src/xmlpatterns/expr/qliteralsequence_p.h new file mode 100644 index 0000000..6699ce0 --- /dev/null +++ b/src/xmlpatterns/expr/qliteralsequence_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** 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_LiteralSequence_H +#define Patternist_LiteralSequence_H + +#include "qemptycontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Houses a sequence of atomic values, making it available as an Expression. + * + * This is not only literals that can be created via the XQuery syntax(strings and numbers), but + * all other atomic values, such as <tt>xs:date</tt> or <tt>xs:time</tt>. It is not guaranteed + * that consecutive atomic values are represented in a LiteralSequence. + * + * @see <a href="http://www.w3.org/TR/xquery/#id-literals">XQuery 1.0: An XML Query Language, + * 3.1.1 Literals</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class LiteralSequence : public EmptyContainer + { + public: + /** + * Creates a LiteralSequence that represents @p item. + * + * @param list the list of item. No entry may be @c null. The list + * must at least be two entries large. + */ + LiteralSequence(const Item::List &list); + + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + virtual SequenceType::Ptr staticType() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + virtual ID id() const; + + virtual Properties properties() const; + + private: + const Item::List m_list; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qnamespaceconstructor.cpp b/src/xmlpatterns/expr/qnamespaceconstructor.cpp new file mode 100644 index 0000000..c6838ee --- /dev/null +++ b/src/xmlpatterns/expr/qnamespaceconstructor.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" + +#include "qnamespaceconstructor_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +NamespaceConstructor::NamespaceConstructor(const QXmlName nb) : m_binding(nb) +{ + Q_ASSERT(!m_binding.isNull()); +} + +void NamespaceConstructor::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + context->outputReceiver()->namespaceBinding(m_binding); +} + +SequenceType::Ptr NamespaceConstructor::staticType() const +{ + return CommonSequenceTypes::ExactlyOneAttribute; +} + +SequenceType::List NamespaceConstructor::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ExactlyOneString); + return result; +} + +Expression::Properties NamespaceConstructor::properties() const +{ + return DisableElimination | IsNodeConstructor; +} + +ExpressionVisitorResult::Ptr NamespaceConstructor::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID NamespaceConstructor::id() const +{ + return IDNamespaceConstructor; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qnamespaceconstructor_p.h b/src/xmlpatterns/expr/qnamespaceconstructor_p.h new file mode 100644 index 0000000..5b73d37 --- /dev/null +++ b/src/xmlpatterns/expr/qnamespaceconstructor_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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_NamespaceConstructor_H +#define Patternist_NamespaceConstructor_H + +#include "qemptycontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Constructs a namespace on an element, and naturally only appears + * as a child of ElementConstructor. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class NamespaceConstructor : public EmptyContainer + { + public: + NamespaceConstructor(const QXmlName nb); + + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + /** + * @returns a list containing one CommonSequenceTypes::ExactlyOneString instance. + */ + virtual SequenceType::List expectedOperandTypes() const; + + /** + * The static type is exactly one attribute node. It's unclear what + * affects the static type has, but specifying anything else could lead + * to complications wrt. node order, XQTY0024. Of course, it's not + * conceptually correct, since a namespace node isn't an attribute + * node. + */ + virtual SequenceType::Ptr staticType() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual Expression::Properties properties() const; + + inline const QXmlName &namespaceBinding() const + { + return m_binding; + } + + virtual ID id() const; + private: + const QXmlName m_binding; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qncnameconstructor.cpp b/src/xmlpatterns/expr/qncnameconstructor.cpp new file mode 100644 index 0000000..b1d2739 --- /dev/null +++ b/src/xmlpatterns/expr/qncnameconstructor.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qatomicstring_p.h" + +#include "qncnameconstructor_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +NCNameConstructor::NCNameConstructor(const Expression::Ptr &source) : SingleContainer(source) +{ +} + +Item NCNameConstructor::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + Q_ASSERT(context); + /* Apply the whitespace facet for when casting to xs:NCName. */ + const QString lexNCName(m_operand->evaluateSingleton(context).stringValue().trimmed()); + + validateTargetName<DynamicContext::Ptr, + ReportContext::XQDY0064, + ReportContext::XQDY0041>(lexNCName, + context, + this); + return AtomicString::fromValue(lexNCName); +} + +Expression::Ptr NCNameConstructor::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + if(BuiltinTypes::xsNCName->xdtTypeMatches(m_operand->staticType()->itemType())) + return m_operand->typeCheck(context, reqType); + else + return SingleContainer::typeCheck(context, reqType); +} + +SequenceType::Ptr NCNameConstructor::staticType() const +{ + return CommonSequenceTypes::ExactlyOneString; +} + +SequenceType::List NCNameConstructor::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ExactlyOneString); + return result; +} + +ExpressionVisitorResult::Ptr NCNameConstructor::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qncnameconstructor_p.h b/src/xmlpatterns/expr/qncnameconstructor_p.h new file mode 100644 index 0000000..02163c5 --- /dev/null +++ b/src/xmlpatterns/expr/qncnameconstructor_p.h @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** 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_NCNameConstructor_H +#define Patternist_NCNameConstructor_H + +#include "qsinglecontainer_p.h" +#include "qpatternistlocale_p.h" +#include "private/qxmlutils_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Ensures the lexical space of the string value of the Item returned + * from its child Expression is an NCName. + * + * @note It doesn't actually construct an @c xs:NCName. It only ensures the lexical + * space is an @c NCName. The atomic value can be of any string type, such as @c xs:untypedAtomic + * of @c xs:string. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class NCNameConstructor : public SingleContainer + { + public: + + NCNameConstructor(const Expression::Ptr &source); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &) const; + + virtual SequenceType::List expectedOperandTypes() const; + + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + + virtual SequenceType::Ptr staticType() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + /** + * Validates @p lexicalNCName as a processing instruction's target + * name, and raise an error if it's not an @c NCName. + */ + template<typename TReportContext, + const ReportContext::ErrorCode NameIsXML, + const ReportContext::ErrorCode LexicallyInvalid> + static inline + void validateTargetName(const QString &lexicalNCName, + const TReportContext &context, + const SourceLocationReflection *const r); + private: + + /** + * This translation string is put here in order to avoid duplicate messages and + * hence reduce work for translators and increase consistency. + */ + static + const QString nameIsXML(const QString &lexTarget) + { + return QtXmlPatterns::tr("The target name in a processing instruction " + "cannot be %1 in any combination of upper " + "and lower case. Therefore, %2 is invalid.") + .arg(formatKeyword("xml"), formatKeyword(lexTarget)); + } + }; + + template<typename TReportContext, + const ReportContext::ErrorCode NameIsXML, + const ReportContext::ErrorCode LexicallyInvalid> + inline + void NCNameConstructor::validateTargetName(const QString &lexicalTarget, + const TReportContext &context, + const SourceLocationReflection *const r) + { + Q_ASSERT(context); + + if(QXmlUtils::isNCName(lexicalTarget)) + { + if(QString::compare(QLatin1String("xml"), lexicalTarget, Qt::CaseInsensitive) == 0) + context->error(nameIsXML(lexicalTarget), NameIsXML, r); + } + else + { + context->error(QtXmlPatterns::tr("%1 is not a valid target name in " + "a processing instruction. It " + "must be a %2 value, e.g. %3.") + .arg(formatKeyword(lexicalTarget)) + .arg(formatType(context->namePool(), + BuiltinTypes::xsNCName)) + .arg(formatKeyword("my-name.123")), + LexicallyInvalid, + r); + } + } +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qnodecomparison.cpp b/src/xmlpatterns/expr/qnodecomparison.cpp new file mode 100644 index 0000000..ba262fd --- /dev/null +++ b/src/xmlpatterns/expr/qnodecomparison.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qcommonvalues_p.h" +#include "qemptysequence_p.h" +#include "qinteger_p.h" +#include "qschemanumeric_p.h" +#include "qrangeiterator_p.h" + +#include "qnodecomparison_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +NodeComparison::NodeComparison(const Expression::Ptr &operand1, + const QXmlNodeModelIndex::DocumentOrder op, + const Expression::Ptr &operand2) + : PairContainer(operand1, operand2) + , m_op(op) +{ + Q_ASSERT(op == QXmlNodeModelIndex::Precedes || + op == QXmlNodeModelIndex::Follows || + op == QXmlNodeModelIndex::Is); +} + +Item NodeComparison::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + switch(evaluate(context)) + { + case True: + return CommonValues::BooleanTrue; + case False: + return CommonValues::BooleanFalse; + default: + return Item(); + } +} + +bool NodeComparison::evaluateEBV(const DynamicContext::Ptr &context) const +{ + switch(evaluate(context)) + { + case True: + return true; + default: + /* We include the empty sequence here. */ + return false; + } +} + +NodeComparison::Result NodeComparison::evaluate(const DynamicContext::Ptr &context) const +{ + const Item op1(m_operand1->evaluateSingleton(context)); + if(!op1) + return Empty; + + const Item op2(m_operand2->evaluateSingleton(context)); + if(!op2) + return Empty; + + /* We just returns an arbitrary value, since there's no order defined for nodes from different + * models, except for that the return value must be stable. */ + if(op1.asNode().model() != op2.asNode().model()) + return False; + + switch(m_op) + { + case QXmlNodeModelIndex::Is: + return op1.asNode().is(op2.asNode()) ? True : False; + case QXmlNodeModelIndex::Precedes: + return op1.asNode().compareOrder(op2.asNode()) == QXmlNodeModelIndex::Precedes ? True : False; + default: + { + Q_ASSERT(m_op == QXmlNodeModelIndex::Follows); + return op1.asNode().compareOrder(op2.asNode()) == QXmlNodeModelIndex::Follows ? True : False; + } + } +} + + +SequenceType::List NodeComparison::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrOneNode); + result.append(CommonSequenceTypes::ZeroOrOneNode); + return result; +} + +Expression::Ptr NodeComparison::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr me(PairContainer::compress(context)); + + if(me != this) + /* We're already rewritten. */ + return me; + + if(m_operand1->staticType()->cardinality().isEmpty() || + m_operand2->staticType()->cardinality().isEmpty()) + { + // TODO issue a warning in the @p context saying that one of the operands + // were empty, and that the expression always result in the empty sequence + // (which never is the intent, right?). + return EmptySequence::create(this, context); + } + + return Expression::Ptr(this); +} + +QString NodeComparison::displayName(const QXmlNodeModelIndex::DocumentOrder op) +{ + switch(op) + { + case QXmlNodeModelIndex::Is: + return QLatin1String("is"); + case QXmlNodeModelIndex::Precedes: + return QLatin1String("<<"); + default: + { + Q_ASSERT(op == QXmlNodeModelIndex::Follows); + return QLatin1String(">>"); + } + } +} + +SequenceType::Ptr NodeComparison::staticType() const +{ + if(m_operand1->staticType()->cardinality().allowsEmpty() || + m_operand2->staticType()->cardinality().allowsEmpty()) + return CommonSequenceTypes::ZeroOrOneBoolean; + else + return CommonSequenceTypes::ExactlyOneBoolean; +} + +QXmlNodeModelIndex::DocumentOrder NodeComparison::operatorID() const +{ + return m_op; +} + +ExpressionVisitorResult::Ptr NodeComparison::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qnodecomparison_p.h b/src/xmlpatterns/expr/qnodecomparison_p.h new file mode 100644 index 0000000..86af0f6 --- /dev/null +++ b/src/xmlpatterns/expr/qnodecomparison_p.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** 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_NodeComparison_H +#define Patternist_NodeComparison_H + +#include "qpaircontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short Implements the node comparison operators <tt>\>\></tt>, <tt>\<\<</tt>, and @c is. + * + * @see <a href="http://www.w3.org/TR/xpath20/#id-node-comparisons">XML Path Language + * (XPath) 2.0, 3.5.3 QXmlNodeModelIndex Comparisons</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class Q_AUTOTEST_EXPORT NodeComparison : public PairContainer + { + public: + NodeComparison(const Expression::Ptr &operand1, + const QXmlNodeModelIndex::DocumentOrder op, + const Expression::Ptr &operand2); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &) const; + virtual bool evaluateEBV(const DynamicContext::Ptr &) const; + + virtual SequenceType::List expectedOperandTypes() const; + + virtual QXmlNodeModelIndex::DocumentOrder operatorID() const; + /** + * If any operator is the empty sequence, the NodeComparison rewrites + * into that, since the empty sequence is always the result in that case. + */ + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + + /** + * @returns either CommonSequenceTypes::ZeroOrOneBoolean or + * CommonSequenceTypes::ExactlyOneBoolean depending on the static + * cardinality of its operands. + */ + virtual SequenceType::Ptr staticType() const; + + /** + * Determines the string representation for a node comparison operator. + * + * @returns + * - "<<" if @p op is Precedes + * - ">>" if @p op is Follows + * - "is" if @p op is Is + */ + static QString displayName(const QXmlNodeModelIndex::DocumentOrder op); + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + private: + enum Result + { + Empty, + True, + False + }; + inline Result evaluate(const DynamicContext::Ptr &context) const; + + const QXmlNodeModelIndex::DocumentOrder m_op; + + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qnodesort.cpp b/src/xmlpatterns/expr/qnodesort.cpp new file mode 100644 index 0000000..171fbc0 --- /dev/null +++ b/src/xmlpatterns/expr/qnodesort.cpp @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qdeduplicateiterator_p.h" +#include "qnodesort_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +NodeSortExpression::NodeSortExpression(const Expression::Ptr &op) : SingleContainer(op) +{ +} + +bool NodeSortExpression::lessThanUsingNodeModel(const Item &n1, + const Item &n2) +{ + Q_ASSERT(n1.isNode()); + Q_ASSERT(n2.isNode()); + + if(n1.asNode().model() == n2.asNode().model()) + return n1.asNode().compareOrder(n2.asNode()) == QXmlNodeModelIndex::Precedes; + else + { + /* The two nodes are from different trees. The sort order is implementation + * defined, but it must be stable. + * + * We do this by looking at the pointer difference. The value means nothing, + * but it is stable, and that's what we're looking for. */ + return n1.asNode().model() - n2.asNode().model() < 0; + } +} + +Item::Iterator::Ptr NodeSortExpression::evaluateSequence(const DynamicContext::Ptr &context) const +{ + Q_ASSERT_X(m_operand->staticType()->cardinality().allowsMany(), Q_FUNC_INFO, + "It makes no sense to sort a single node."); + + Item::List nodes(m_operand->evaluateSequence(context)->toList()); + + if(nodes.isEmpty()) + return CommonValues::emptyIterator; + else if(nodes.first().isAtomicValue()) + return makeListIterator(nodes); + else + { + qSort(nodes.begin(), nodes.end(), lessThanUsingNodeModel); + + return Item::Iterator::Ptr(new DeduplicateIterator(nodes)); + } +} + +Expression::Ptr NodeSortExpression::wrapAround(const Expression::Ptr &operand, + const StaticContext::Ptr &context) +{ + Q_ASSERT(operand); + Q_ASSERT(context); + + const Expression::Ptr sort(new NodeSortExpression(operand)); + context->wrapExpressionWith(operand.data(), sort); + return sort; +} + +Expression::Ptr NodeSortExpression::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr me(SingleContainer::compress(context)); + + /* It make no sense to sort & deduplicate a single node. */ + if(m_operand->staticType()->cardinality().allowsMany()) + return me; + else + return m_operand; +} + +SequenceType::Ptr NodeSortExpression::staticType() const +{ + return m_operand->staticType(); +} + +SequenceType::List NodeSortExpression::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +ExpressionVisitorResult::Ptr +NodeSortExpression::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::Properties NodeSortExpression::properties() const +{ + /* The reason we disable elimination is that the assert for sorting a + * single node in evaluateSequence() triggers unless our compress() routine + * has been run. Anyhow, it's not that we would manage to write away anyway, + * since the node source in most(all?) cases prevents it. + */ + return AffectsOrderOnly | DisableElimination; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qnodesort_p.h b/src/xmlpatterns/expr/qnodesort_p.h new file mode 100644 index 0000000..850023b --- /dev/null +++ b/src/xmlpatterns/expr/qnodesort_p.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** 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_NodeSortExpression_H +#define Patternist_NodeSortExpression_H + +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short De-duplicates and sorts in document order the content that its + * operand returns. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class NodeSortExpression : public SingleContainer + { + public: + NodeSortExpression(const Expression::Ptr &operand); + + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + virtual SequenceType::Ptr staticType() const; + virtual SequenceType::List expectedOperandTypes() const; + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual Properties properties() const; + + /** + * Ensures that result delivered from @p operand, is in document order. + */ + static Expression::Ptr wrapAround(const Expression::Ptr &operand, + const StaticContext::Ptr &context); + + private: + static inline bool lessThanUsingNodeModel(const Item &n1, + const Item &n2); + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qoperandsiterator_p.h b/src/xmlpatterns/expr/qoperandsiterator_p.h new file mode 100644 index 0000000..9986ef2 --- /dev/null +++ b/src/xmlpatterns/expr/qoperandsiterator_p.h @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** 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_OperandsIterator_H +#define Patternist_OperandsIterator_H + +#include <QPair> +#include <QStack> + +#include "qexpression_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A helper class that iterates a tree of Expression instances. It + * is not a sub-class of QAbstractXmlForwardIterator. + * + * The OperandsIterator delivers all Expression instances that are children at any + * depth of the Expression passed in the constructor. + * The order is delivered in a defined way, from left to right and depth + * first. + * + * @author Frans Englich <frans.englich@nokia.com> + */ + class OperandsIterator + { + /** + * The second value, the int, is the current position in the first. + */ + typedef QPair<Expression::List, int> Level; + + public: + enum TreatParent + { + ExcludeParent, + IncludeParent + }; + + /** + * if @p treatParent is @c IncludeParent, @p start is excluded. + * + * @p start must be a valid Expression. + */ + inline OperandsIterator(const Expression::Ptr &start, + const TreatParent treatParent) + { + Q_ASSERT(start); + if(treatParent == IncludeParent) + { + Expression::List l; + l.append(start); + m_exprs.push(qMakePair(l, -1)); + } + + m_exprs.push(qMakePair(start->operands(), -1)); + } + + /** + * @short Returns the current Expression and advances the iterator. + * + * If the end has been reached, a default constructed pointer is + * returned. + * + * We intentionally return by reference. + */ + inline Expression::Ptr next() + { + if(m_exprs.isEmpty()) + return Expression::Ptr(); + + Level &lvl = m_exprs.top(); + ++lvl.second; + + if(lvl.second == lvl.first.size()) + { + /* Resume iteration above us. */ + m_exprs.pop(); + + if(m_exprs.isEmpty()) + return Expression::Ptr(); + + while(true) + { + Level &previous = m_exprs.top(); + ++previous.second; + + if(previous.second < previous.first.count()) + { + const Expression::Ptr &op = previous.first.at(previous.second); + m_exprs.push(qMakePair(op->operands(), -1)); + return op; + } + else + { + // We have already reached the end of this level. + m_exprs.pop(); + if(m_exprs.isEmpty()) + return Expression::Ptr(); + } + } + } + else + { + const Expression::Ptr &op = lvl.first.at(lvl.second); + m_exprs.push(qMakePair(op->operands(), -1)); + return op; + } + } + + /** + * Advances this iterator by the current expression and its operands. + */ + Expression::Ptr skipOperands() + { + if(m_exprs.isEmpty()) + return Expression::Ptr(); + + Level &lvl = m_exprs.top(); + ++lvl.second; + + if(lvl.second == lvl.first.size()) + { + /* We've reached the end of this level, at least. */ + m_exprs.pop(); + } + + return next(); + } + + private: + Q_DISABLE_COPY(OperandsIterator) + + QStack<Level> m_exprs; + }; +} + + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qoptimizationpasses.cpp b/src/xmlpatterns/expr/qoptimizationpasses.cpp new file mode 100644 index 0000000..d970483 --- /dev/null +++ b/src/xmlpatterns/expr/qoptimizationpasses.cpp @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qoptimizerblocks_p.h" + +#include "qoptimizationpasses_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +OptimizationPass::List OptimizationPasses::comparisonPasses; +OptimizationPass::List OptimizationPasses::forPasses; +OptimizationPass::List OptimizationPasses::ifThenPasses; +OptimizationPass::List OptimizationPasses::notFN; + +void OptimizationPasses::Coordinator::init() +{ + static bool isInitialized = false; // STATIC DATA + + if(isInitialized) + return; + + isInitialized = true; + + /* Note, below is many of the building blocks re-used in several passes + * in order to reduce memory use. Thus, when changing one building block + * it potentially affects many passes. */ + + /* ****************************************************** */ + /* Rewrite "count(<expr>) ge 1" into "exists(<expr>)" */ + OptimizationPass::ExpressionMarker firstFirstChild; + firstFirstChild.append(0); + firstFirstChild.append(0); + + ExpressionIdentifier::List geOpIDs; + const ExpressionIdentifier::Ptr countFN(new ByIDIdentifier(Expression::IDCountFN)); + geOpIDs.append(countFN); + geOpIDs.append(ExpressionIdentifier::Ptr(new IntegerIdentifier(1))); + + QVector<Expression::ID> geMatcher; + geMatcher.append(Expression::IDValueComparison); + geMatcher.append(Expression::IDGeneralComparison); + + const ExpressionIdentifier::Ptr ge(new ComparisonIdentifier(geMatcher, + AtomicComparator::OperatorGreaterOrEqual)); + + const ExpressionCreator::Ptr existsFN(new ByIDCreator(Expression::IDExistsFN)); + const OptimizationPass::Ptr geToExists(new OptimizationPass(ge, geOpIDs, firstFirstChild, existsFN)); + comparisonPasses.append(geToExists); + /* ****************************************************** */ + + /* ****************************************************** */ + /* Rewrite "count(<expr>) gt 0" into "exists(<expr>)" */ + ExpressionIdentifier::List countAndIntZero; + countAndIntZero.append(countFN); + const ExpressionIdentifier::Ptr zeroInteger(new IntegerIdentifier(0)); + countAndIntZero.append(zeroInteger); + + const ExpressionIdentifier::Ptr gt(new ComparisonIdentifier(geMatcher, + AtomicComparator::OperatorGreaterThan)); + + const OptimizationPass::Ptr gtToExists(new OptimizationPass(gt, countAndIntZero, + firstFirstChild, existsFN)); + comparisonPasses.append(gtToExists); + /* ****************************************************** */ + + /* ****************************************************** */ + /* Rewrite "count(<expr>) ne 0" into "exists(<expr>)" */ + + const ExpressionIdentifier::Ptr ne(new ComparisonIdentifier(geMatcher, + AtomicComparator::OperatorNotEqual)); + const OptimizationPass::Ptr neToExists(new OptimizationPass(ne, countAndIntZero, firstFirstChild, + existsFN, + OptimizationPass::AnyOrder)); + comparisonPasses.append(neToExists); + /* ****************************************************** */ + + /* ****************************************************** */ + /* Rewrite "count(<expr>) eq 0" into "empty(<expr>)" */ + ExpressionIdentifier::List eqOpIDs; + eqOpIDs.append(countFN); + eqOpIDs.append(zeroInteger); + const ExpressionCreator::Ptr emptyFN(new ByIDCreator(Expression::IDEmptyFN)); + const ExpressionIdentifier::Ptr eq(new ComparisonIdentifier(geMatcher, + AtomicComparator::OperatorEqual)); + const OptimizationPass::Ptr eqToEmpty(new OptimizationPass(eq, eqOpIDs, firstFirstChild, + emptyFN, + OptimizationPass::AnyOrder)); + comparisonPasses.append(eqToEmpty); + + /* ****************************************************** */ + + /* ****************************************************** */ + /* Rewrite "for $var in <expr> return $var" into "<expr>" */ + ExpressionIdentifier::List forOps; + OptimizationPass::ExpressionMarker firstChild; + firstChild.append(0); + + forOps.append(ExpressionIdentifier::Ptr()); + forOps.append(ExpressionIdentifier::Ptr(new ByIDIdentifier(Expression::IDRangeVariableReference))); + const OptimizationPass::Ptr simplifyFor(new OptimizationPass(ExpressionIdentifier::Ptr(), forOps, + firstChild, ExpressionCreator::Ptr())); + forPasses.append(simplifyFor); + /* ****************************************************** */ + + /* ****************************************************** */ + /* Rewrite "if(<expr>) then true() else false()" to "<expr>" */ + OptimizationPass::ExpressionMarker marker; + marker.append(0); + + ExpressionIdentifier::List opIDs; + opIDs.append(ExpressionIdentifier::Ptr(new BySequenceTypeIdentifier( + CommonSequenceTypes::ExactlyOneBoolean))); + opIDs.append(ExpressionIdentifier::Ptr(new BooleanIdentifier(true))); + opIDs.append(ExpressionIdentifier::Ptr(new BooleanIdentifier(false))); + + const OptimizationPass::Ptr pass(new OptimizationPass(ExpressionIdentifier::Ptr(), opIDs, marker)); + ifThenPasses.append(pass); + /* ****************************************************** */ + + /* ****************************************************** */ + /* Rewrite "not(exists(X))" into "empty(X)" */ + ExpressionIdentifier::List idExistsFN; + idExistsFN.append(ExpressionIdentifier::Ptr(new ByIDIdentifier(Expression::IDExistsFN))); + + notFN.append(OptimizationPass::Ptr(new OptimizationPass(ExpressionIdentifier::Ptr(), + idExistsFN, + firstFirstChild, + emptyFN))); + + /* Rewrite "not(empty(X))" into "exists(X)" */ + ExpressionIdentifier::List idEmptyFN; + idEmptyFN.append(ExpressionIdentifier::Ptr(new ByIDIdentifier(Expression::IDEmptyFN))); + + notFN.append(OptimizationPass::Ptr(new OptimizationPass(ExpressionIdentifier::Ptr(), + idEmptyFN, + firstFirstChild, + existsFN))); + /* ****************************************************** */ +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qoptimizationpasses_p.h b/src/xmlpatterns/expr/qoptimizationpasses_p.h new file mode 100644 index 0000000..6f10572 --- /dev/null +++ b/src/xmlpatterns/expr/qoptimizationpasses_p.h @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** 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_OptimizationBlocks_H +#define Patternist_OptimizationBlocks_H + +#include "qatomiccomparator_p.h" +#include "qexpression_p.h" +#include "qoptimizerframework_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Contains a set of common OptimizerPass instances. + * + * @author Frans englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + namespace OptimizationPasses + { + /** + * A list of OptimizerPass instances that performs the + * following rewrites: + * + * - <tt>count([expr]) ne 0</tt> into <tt>exists([expr])</tt> + * - <tt>count([expr]) != 0</tt> into <tt>exists([expr])</tt> + * - <tt>0 ne count([expr])</tt> into <tt>exists([expr])</tt> + * - <tt>0 != count([expr])</tt> into <tt>exists([expr])</tt> + * - <tt>count([expr]) eq 0</tt> into <tt>empty([expr])</tt> + * - <tt>count([expr]) = 0</tt> into <tt>empty([expr])</tt> + * - <tt>0 eq count([expr])</tt> into <tt>empty([expr])</tt> + * - <tt>0 = count([expr])</tt> into <tt>empty([expr])</tt> + * - <tt>count([expr]) ge 1</tt> into <tt>exists([expr])</tt> + * - <tt>count([expr]) >= 1</tt> into <tt>exists([expr])</tt> + */ + extern OptimizationPass::List comparisonPasses; + + /** + * A list of OptimizerPass instances that performs the + * following rewrites: + * + * - <tt>for $var in [expr] return $var</tt> into <tt>[expr]</tt> + */ + extern OptimizationPass::List forPasses; + + /** + * A list of OptimizerPass instances that performs the + * following rewrites: + * + * - <tt>if([expr of type xs:boolean]) then true() else false()</tt> + * into <tt>[expr of type xs:boolean]</tt> + */ + extern OptimizationPass::List ifThenPasses; + + /** + * A list of OptimizerPass instances that performs the + * following rewrites: + * + * - <tt>fn:not(fn:exists([expr]))</tt> into <tt>fn:empty([expr])</tt> + * - <tt>fn:not(fn:empty([expr]))</tt> into <tt>fn:exists([expr])</tt> + */ + extern OptimizationPass::List notFN; + + /** + * Initializes the data members in the OptimizationPasses namespace. + * + * This class is not supposed to be instantiated, but to be used via its init() + * function. In fact, this class cannot be instantiated. + * + * @author Frans englich <frans.englich@nokia.com> + */ + class Coordinator + { + public: + /** + * Initializes the members in the OptimizationPasses namespace. + */ + static void init(); + + private: + Q_DISABLE_COPY(Coordinator) + inline Coordinator(); + }; + } +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qoptimizerblocks.cpp b/src/xmlpatterns/expr/qoptimizerblocks.cpp new file mode 100644 index 0000000..511faae --- /dev/null +++ b/src/xmlpatterns/expr/qoptimizerblocks.cpp @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonnamespaces_p.h" + +#include "qcommonsequencetypes_p.h" +#include "qfunctionfactory_p.h" +#include "qgeneralcomparison_p.h" +#include "qliteral_p.h" +#include "qschemanumeric_p.h" +#include "qvaluecomparison_p.h" + +#include "qoptimizerblocks_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ByIDIdentifier::ByIDIdentifier(const Expression::ID id) : m_id(id) +{ +} + +bool ByIDIdentifier::matches(const Expression::Ptr &expr) const +{ + return expr->is(m_id); +} + +ComparisonIdentifier::ComparisonIdentifier(const QVector<Expression::ID> hosts, + const AtomicComparator::Operator op) : m_hosts(hosts), + m_op(op) +{ +} + +bool ComparisonIdentifier::matches(const Expression::Ptr &e) const +{ + const Expression::ID eID = e->id(); + + if(eID == Expression::IDGeneralComparison) + { + if(m_hosts.contains(Expression::IDGeneralComparison)) + return e->as<GeneralComparison>()->operatorID() == m_op; + else + return false; + } + else if(eID == Expression::IDValueComparison) + { + if(m_hosts.contains(Expression::IDValueComparison)) + return e->as<ValueComparison>()->operatorID() == m_op; + else + return false; + } + else + return false; +} + +BySequenceTypeIdentifier::BySequenceTypeIdentifier(const SequenceType::Ptr &seqType) : m_seqType(seqType) +{ + Q_ASSERT(seqType); +} + +bool BySequenceTypeIdentifier::matches(const Expression::Ptr &expr) const +{ + const SequenceType::Ptr t(expr->staticType()); + + return m_seqType->itemType()->xdtTypeMatches(t->itemType()) + && + m_seqType->cardinality().isMatch(t->cardinality()); +} + +IntegerIdentifier::IntegerIdentifier(const xsInteger num) : m_num(num) +{ +} + +bool IntegerIdentifier::matches(const Expression::Ptr &expr) const +{ + return expr->is(Expression::IDIntegerValue) && + expr->as<Literal>()->item().as<Numeric>()->toInteger() == m_num; +} + +BooleanIdentifier::BooleanIdentifier(const bool value) : m_value(value) +{ +} + +bool BooleanIdentifier::matches(const Expression::Ptr &expr) const +{ + return expr->is(Expression::IDBooleanValue) && + expr->evaluateEBV(DynamicContext::Ptr()) == m_value; +} + +ByIDCreator::ByIDCreator(const Expression::ID id) : m_id(id) +{ + Q_ASSERT(id != Expression::IDIgnorableExpression); +} + +Expression::Ptr ByIDCreator::create(const Expression::List &operands, + const StaticContext::Ptr &context, + const SourceLocationReflection *const r) const +{ + return create(m_id, operands, context, r); +} + +Expression::Ptr ByIDCreator::create(const Expression::ID id, + const Expression::List &operands, + const StaticContext::Ptr &context, + const SourceLocationReflection *const r) +{ + Q_ASSERT(context); + + QXmlName::LocalNameCode fnName; + + switch(id) + { + case Expression::IDExistsFN: + { + fnName = StandardLocalNames::exists; + break; + } + case Expression::IDEmptyFN: + { + fnName = StandardLocalNames::empty; + break; + } + default: + { + Q_ASSERT_X(false, Q_FUNC_INFO, + "Cannot create an expression of requested type; m_id is wrong."); + return Expression::Ptr(); + } + } + + /* The reason we don't simply do 'new ExistsFN()' ourselves, is that all FunctionCall + * instances needs their FunctionSignature in order to function, and the FunctionFactories + * sets that. */ + const QXmlName qName(StandardNamespaces::fn, fnName); + + const Expression::Ptr result(context->functionSignatures()->createFunctionCall(qName, operands, context, r)); + context->wrapExpressionWith(r, result); + return result; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qoptimizerblocks_p.h b/src/xmlpatterns/expr/qoptimizerblocks_p.h new file mode 100644 index 0000000..575e07c --- /dev/null +++ b/src/xmlpatterns/expr/qoptimizerblocks_p.h @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** 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_OptimizerBlocks_H +#define Patternist_OptimizerBlocks_H + +#include "qatomiccomparator_p.h" +#include "qexpression_p.h" +#include "qoptimizerframework_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Identifies Expression instances by their Expression::id(). + * + * @author Frans englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ByIDIdentifier : public ExpressionIdentifier + { + public: + ByIDIdentifier(const Expression::ID id); + virtual bool matches(const Expression::Ptr &expr) const; + private: + const Expression::ID m_id; + }; + + /** + * @short Identifies Expression instances based on their static type. + * + * BySequenceTypeIdentifier identifies Expression instances + * if their Expression::staticType() matches the requested one, + * regardless of whether the Expression is a particular one, such + * as AndExpression. + * + * For example, constructing a BySequenceTypeIdentifier while + * passing CommonSequenceTypes::EBV in its constructor will create + * a ExpressionIdentifier that returns @c true for a static type with + * item type <tt>xs:string</tt>, but returns @c false for a static type involving + * <tt>xs:date</tt>. + * + * @author Frans englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class BySequenceTypeIdentifier : public ExpressionIdentifier + { + public: + BySequenceTypeIdentifier(const SequenceType::Ptr &seqType); + + /** + * @returns @c true, if the static type of @p expr is matches + * the SequenceType passed in the BySequenceTypeIdentifier() + * constructor, otherwise @c false. + */ + virtual bool matches(const Expression::Ptr &expr) const; + + private: + const SequenceType::Ptr m_seqType; + }; + + /** + * @short Determines whether an Expression is a value or general comparison or both, + * with a certain operator. + * + * @author Frans englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ComparisonIdentifier : public ExpressionIdentifier + { + public: + + /** + * @param comparatorHosts the possible parent that may have + * the operator. This may be Expression::IDGeneralComparison or + * Expression::IDValueComparison. The two values may also be OR'd, + * meaning any of them will do. + * + * @param op the operator that the comparator host must have. For example, + * if @p op is AtomicComparator::OperatorGreatorOrEqual this ComparisonIdentifier + * will match operator >= in the case of IDGeneralComparison and 'ge' in the + * case of IDValueComparison. + */ + ComparisonIdentifier(const QVector<Expression::ID> comparatorHosts, + const AtomicComparator::Operator op); + + /** + * @returns @c true, if @p expr is a ValueComparison with the operator + * passed in ComparisonIdentifier(). + */ + virtual bool matches(const Expression::Ptr &expr) const; + + private: + const QVector<Expression::ID> m_hosts; + const AtomicComparator::Operator m_op; + }; + + /** + * @short Matches numeric literals that are of type xs:integer and + * has a specific value. + * + * For example IntegerIdentifier(4) would match the former but + * not the latter operand in this expression: "4 + 5". + * + * @author Frans englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class IntegerIdentifier : public ExpressionIdentifier + { + public: + IntegerIdentifier(const xsInteger num); + virtual bool matches(const Expression::Ptr &expr) const; + + private: + const xsInteger m_num; + }; + + /** + * @short Matches boolean literals. + * + * For example BooleanIdentifier(true) would match the former but + * not the latter operand in this expression: "true() + false()". + * + * @author Frans englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class BooleanIdentifier : public ExpressionIdentifier + { + public: + BooleanIdentifier(const bool value); + virtual bool matches(const Expression::Ptr &expr) const; + + private: + const bool m_value; + }; + + /** + * @short Creates a particular Expression instance identified by an Expression::ID. + * + * For example, if ByIDCreator() is passed Expression::IDCountFN, create() + * will return CountFN instances. + * + * @author Frans englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ByIDCreator : public ExpressionCreator + { + public: + /** + * Creates a ByIDCreator that creates expressions + * of the type that @p id identifies. + */ + ByIDCreator(const Expression::ID id); + virtual Expression::Ptr create(const Expression::List &operands, + const StaticContext::Ptr &context, + const SourceLocationReflection *const r) const; + + /** + * Creates an expression by id @p id with the arguments @p operands. + */ + static Expression::Ptr create(const Expression::ID id, + const Expression::List &operands, + const StaticContext::Ptr &context, + const SourceLocationReflection *const r); + + private: + const Expression::ID m_id; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qoptimizerframework.cpp b/src/xmlpatterns/expr/qoptimizerframework.cpp new file mode 100644 index 0000000..c9e1991 --- /dev/null +++ b/src/xmlpatterns/expr/qoptimizerframework.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qoptimizerblocks_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ExpressionIdentifier::~ExpressionIdentifier() +{ +} + +ExpressionCreator::~ExpressionCreator() +{ +} + +OptimizationPass::OptimizationPass(const ExpressionIdentifier::Ptr &startID, + const ExpressionIdentifier::List &opIDs, + const ExpressionMarker &sourceExpr, + const ExpressionCreator::Ptr &resultCtor, + const OperandsMatchMethod mMethod) : startIdentifier(startID), + operandIdentifiers(opIDs), + sourceExpression(sourceExpr), + resultCreator(resultCtor), + operandsMatchMethod(mMethod) +{ + Q_ASSERT_X(resultCtor || !sourceExpr.isEmpty(), Q_FUNC_INFO, + "Either resultCreator or sourceExpression must be set, otherwise there's " + "nothing to rewrite to."); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qoptimizerframework_p.h b/src/xmlpatterns/expr/qoptimizerframework_p.h new file mode 100644 index 0000000..a2c9373 --- /dev/null +++ b/src/xmlpatterns/expr/qoptimizerframework_p.h @@ -0,0 +1,294 @@ +/**************************************************************************** +** +** 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_OptimizerFramework_H +#define Patternist_OptimizerFramework_H + +#include <QSharedData> + +#include "qexpression_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A factory for creating Expression instances. + * + * ExpressionIdentifier is one of the building block of Patternist's + * optimizer framework. An ExpressionIdentifier sub-class has + * the responsibility of creating the Expression that should be + * the result of the optimization. + * + * This class and sub-classes are never used on their own, + * but in cooperation with OptimizationPass. + * + * @author Frans englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ExpressionCreator : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer<ExpressionCreator> Ptr; + + /** + * For some reason this constructor cannot be synthesized. + */ + inline ExpressionCreator() + { + } + + virtual ~ExpressionCreator(); + /** + * Creates an expression that has @p operands as operands. + * + * The Expression that is returned is guaranteed, by the caller, + * to get a treatment identical to if the expression was created + * in an ordinary compilation(via the parser, and so forth). That is, + * Expression::typeCheck() and Expression::compress() stages will be + * carried out on the returned expression. + * + * @returns an Expression::Ptr that never is non @c null, valid pointer + */ + virtual Expression::Ptr create(const Expression::List &operands, + const StaticContext::Ptr &context, + const SourceLocationReflection *const) const = 0; + + private: + Q_DISABLE_COPY(ExpressionCreator) + }; + + /** + * @short Abstract base class for all classes that identify Expressions + * based on some criteria. + * + * ExpressionIdentifier is one of the building block of Patternist's + * optimizer framework. An ExpressionIdentifier sub-class has + * the responsibility of determining whether a particular Expression + * is the one an OptimizationPass should apply for. + * + * This class and sub-classes are never used on their own, + * but in cooperation with OptimizationPass. + * + * @author Frans englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ExpressionIdentifier : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer<ExpressionIdentifier> Ptr; + typedef QList<ExpressionIdentifier::Ptr> List; + + /** + * For some reason this constructor cannot be synthesized. + */ + inline ExpressionIdentifier() + { + } + + virtual ~ExpressionIdentifier(); + /** + * @param expr the Expression to be tested. This is guranteed + * to always be a non @c null, valid pointer. + * + * @returns @c true if @p expr matches as according to this ExpressionIdentifier, + * otherwise @c false. + */ + virtual bool matches(const Expression::Ptr &expr) const = 0; + + private: + Q_DISABLE_COPY(ExpressionIdentifier) + }; + + /** + * @short Describes how a particular optimization pass should be carried out. + * + * OptimizationPass is essentially a declaration, which describes + * how an optimization pass in the form of an AST rewrite should be done, + * by describing what that should be rewritten into what how. + * + * Each OptimizationPass is applied to a "start" Expression. The Expression + * that qualifies as a start Expression for the OptimizationPass in question is + * determined by startIdentifier; if its ExpressionIdentifier::matches() function + * returns @c true, the optimizer continues to apply this OptimizationPass. + * + * After a start Expression has been found, it is verified if the operands matches + * as well by applying the ExpressionIdentifiers in operandIdentifiers to the + * start Expression's operands. Similarly, if the operands matches what + * operandIdentifiers requires, the optimizer continues to apply this OptimizationPass. + * + * At this stage, it has been concluded that the OptimizationPass validly applies, and + * what now remains is to carry out the actual rewrite. The Expression rewritten + * to is the one returned by ExpressionCreator::create(), when invoked via the resultCreator + * variable. + * + * How these components, startIdentifier, operandIdentifiers, sourceExpression, + * and resultCreator interacts with one another is described in more detail + * in the member documentation as well as the classes they are instances of. + * + * @author Frans englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class OptimizationPass : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer<OptimizationPass> Ptr; + typedef QList<OptimizationPass::Ptr> List; + + enum OperandsMatchMethod + { + /** + * All operands must match in the same order the ExpressionMarkers do. + */ + Sequential = 1, + + /** + * Matches if all operands are matched, regardless of their order. This is + * useful when an OptimizationPass is matching an Expression that has two operands + * and that both of them can appear on the left or right hand as long as it is those + * two. + * + * This comparison method only works when two operands + * needs to be matched. + */ + AnyOrder + }; + + /** + * An ExpressionMarker identifies an operand Expression relatively + * the start Expression by that each integer identifies a step + * in a descending AST walk. For example an ExpressionMarker with + * only one entry that is 0(zero), identifies the first operand of the + * start Expression. An ExpressionMarker containing 1, 2 in that order + * identifies the third operand of the second operand of the start Expression. + */ + typedef QList<qint8> ExpressionMarker; + + /** + * Creates an OptimizationPass and sets its public variables + * to the corresponding values passed in this constructor. + */ + OptimizationPass(const ExpressionIdentifier::Ptr &startID, + const ExpressionIdentifier::List &operandIDs, + const ExpressionMarker &sourceExpr, + const ExpressionCreator::Ptr &resultCtor = ExpressionCreator::Ptr(), + const OperandsMatchMethod matchMethod = Sequential); + + /** + * The ExpressionIdentifier that must the Expression this OptimizationPass concerns. + * + * If this variable is @c null, it means that the start Expression does + * not have to match any particular ExpressionIdentifier, but is fine as is. + * + * One might wonder what the purpose of this startIdentifier is, considering + * that what start Expression an OptimizationPass can at all apply to is + * naturally determined by what Expression::optimizationPasses() re-implementation that + * returns this OptimizationPass. The reason is that in some cases an OptimizationPass + * nevertheless doesn't apply. For example, optimizations applying to a ValueComparison + * might depend on what operator that is in use. + * + * May be @c null or point to an ExpressionIdentifier. + */ + const ExpressionIdentifier::Ptr startIdentifier; + + /** + * In order for an OptimizationPass to apply, the start Expression's + * operands must be matched with this list of ExpressionIdentifier instances. + * The first ExpressionIdentifier is applied to the first operand, the second + * ExpressionIdentifier to the second operand, and so forth until all operands + * have been iterated. + * + * Entries in this list may be @c null, and those signals that the corresponding + * operand is not constrained. For example, if the third ExpressionIdentifier in + * the list is @c null, it signals that the third operand may be anykind of expression. + * + * May be empty or contain an arbitrary amount of objects or @c null pointers. + */ + const ExpressionIdentifier::List operandIdentifiers; + + /** + * Identifies the expression that should be part of the new expression + * that this OptimizationPass rewrites to. If this list is empty, it + * means that the result is not derived from the existing tree, and + * that resultCreator will exclusively be used for creating the result + * Expression. + * + * How the ExpressionMarker identifies an Expression is document in + * its documentation. + * + * May be empty. + */ + const ExpressionMarker sourceExpression; + + /** + * This is the ExpressionCreator that will be used to create the + * Expression which is the result. ExpressionCreator::create() + * will be passed as operands the Expression that sourceExpression + * specify, if any. + * + * If this variable is @c null, the result Expression will be the one + * sourceExpression identifies. + */ + const ExpressionCreator::Ptr resultCreator; + + const OperandsMatchMethod operandsMatchMethod; + private: + Q_DISABLE_COPY(OptimizationPass) + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qorderby.cpp b/src/xmlpatterns/expr/qorderby.cpp new file mode 100644 index 0000000..b2fae5a --- /dev/null +++ b/src/xmlpatterns/expr/qorderby.cpp @@ -0,0 +1,261 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include <QtAlgorithms> + +#include "qcommonsequencetypes_p.h" +#include "qnodebuilder_p.h" +#include "qschemanumeric_p.h" +#include "qpatternistlocale_p.h" +#include "qreturnorderby_p.h" +#include "qsorttuple_p.h" +#include "qsequencemappingiterator_p.h" + +#include "qorderby_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +OrderBy::OrderBy(const Stability stability, + const OrderSpec::Vector &aOrderSpecs, + const Expression::Ptr &op, + ReturnOrderBy *const returnOrderBy) : SingleContainer(op) + , m_stability(stability) + , m_orderSpecs(aOrderSpecs) + , m_returnOrderBy(returnOrderBy) +{ + Q_ASSERT(m_returnOrderBy); +} + +void OrderBy::OrderSpec::prepare(const Expression::Ptr &source, + const StaticContext::Ptr &context) +{ + m_expr = source; + const ItemType::Ptr t(source->staticType()->itemType()); + prepareComparison(fetchComparator(t, t, context)); +} + +/** + * @short Functor used by Qt's qSort() and qStableSort(). Used for FLWOR's + * <tt>order by</tt> expression. + * + * This must be in the global namespace, since it is specializing qLess(), which + * is in the global namespace. Hence it can't be in QPatternist. + */ +template<> +class qLess<Item::List> +{ +private: + + static inline bool isNaN(const Item &i) + { + return BuiltinTypes::xsDouble->xdtTypeMatches(i.type()) && + i.as<Numeric>()->isNaN(); + } + +public: + inline qLess(const OrderBy::OrderSpec::Vector &orderspecs, + const DynamicContext::Ptr &context) : m_orderSpecs(orderspecs) + , m_context(context) + { + Q_ASSERT(!m_orderSpecs.isEmpty()); + Q_ASSERT(context); + } + + inline bool operator()(const Item &item1, const Item &item2) const + { + const SortTuple *const s1 = item1.as<SortTuple>(); + const SortTuple *const s2 = item2.as<SortTuple>(); + + const Item::Vector &sortKeys1 = s1->sortKeys(); + const Item::Vector &sortKeys2 = s2->sortKeys(); + const int len = sortKeys1.count(); + Q_ASSERT(sortKeys1.count() == sortKeys2.count()); + + for(int i = 0; i < len; ++i) + { + const Item &i1 = sortKeys1.at(i); + const Item &i2 = sortKeys2.at(i); + const OrderBy::OrderSpec &orderSpec = m_orderSpecs.at(i); + + if(!i1) + { + if(i2 && !isNaN(i2)) + { + /* We got ((), item()). */ + return orderSpec.orderingEmptySequence == StaticContext::Least ? orderSpec.direction == OrderBy::OrderSpec::Ascending + : orderSpec.direction != OrderBy::OrderSpec::Ascending; + } + else + return false; + } + + if(!i2) + { + if(i1 && !isNaN(i1)) + /* We got (item(), ()). */ + return orderSpec.orderingEmptySequence == StaticContext::Greatest ? orderSpec.direction == OrderBy::OrderSpec::Ascending + : orderSpec.direction != OrderBy::OrderSpec::Ascending; + else + return false; + } + + Q_ASSERT(orderSpec.direction == OrderBy::OrderSpec::Ascending || + orderSpec.direction == OrderBy::OrderSpec::Descending); + const AtomicComparator::ComparisonResult result = orderSpec.detailedFlexibleCompare(i1, i2, m_context); + + switch(result) + { + case AtomicComparator::LessThan: + return orderSpec.direction == OrderBy::OrderSpec::Ascending; + case AtomicComparator::GreaterThan: + return orderSpec.direction != OrderBy::OrderSpec::Ascending; + case AtomicComparator::Equal: + continue; + case AtomicComparator::Incomparable: + Q_ASSERT_X(false, Q_FUNC_INFO, "This code path assume values are always comparable."); + } + } + + return false; + } + +private: + /* Yes, we store references here. */ + const OrderBy::OrderSpec::Vector & m_orderSpecs; + const DynamicContext::Ptr & m_context; +}; + +Item::Iterator::Ptr OrderBy::mapToSequence(const Item &i, + const DynamicContext::Ptr &) const +{ + return i.as<SortTuple>()->value(); +} + +Item::Iterator::Ptr OrderBy::evaluateSequence(const DynamicContext::Ptr &context) const +{ + Item::List tuples(m_operand->evaluateSequence(context)->toList()); + + const qLess<Item::List> sorter(m_orderSpecs, context); + + Q_ASSERT(m_stability == StableOrder || m_stability == UnstableOrder); + + /* On one hand we could just disregard stability and always use qStableSort(), but maybe qSort() + * is a bit faster? */ + if(m_stability == StableOrder) + qStableSort(tuples.begin(), tuples.end(), sorter); + else + { + Q_ASSERT(m_stability == UnstableOrder); + qSort(tuples.begin(), tuples.end(), sorter); + } + + return makeSequenceMappingIterator<Item>(ConstPtr(this), + makeListIterator(tuples), + context); +} + +Expression::Ptr OrderBy::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + m_returnOrderBy->setStay(true); + + /* It's important we do the typeCheck() before calling OrderSpec::prepare(), since + * atomizers must first be inserted. */ + const Expression::Ptr me(SingleContainer::typeCheck(context, reqType)); + + const Expression::List ops(m_returnOrderBy->operands()); + const int len = ops.count(); + Q_ASSERT(ops.count() > 1); + Q_ASSERT(m_orderSpecs.count() == ops.count() - 1); + + for(int i = 1; i < len; ++i) + m_orderSpecs[i - 1].prepare(ops.at(i), context); + + return me; + + /* It's not meaningful to sort a single item or less, so rewrite ourselves + * away if that is the case. This is an optimization. */ + /* TODO: How do we remove ReturnOrderBy? + if(Cardinality::zeroOrOne().isMatch(m_operand->staticType()->cardinality())) + return m_operand->typeCheck(context, reqType); + else + return SingleContainer::typeCheck(context, reqType); + */ +} + +Expression::Properties OrderBy::properties() const +{ + return m_operand->properties() & DisableElimination; +} + +Expression::Ptr OrderBy::compress(const StaticContext::Ptr &context) +{ + /* If we only will produce one item, there's no point in sorting. */ + if(m_operand->staticType()->cardinality().allowsMany()) + return SingleContainer::compress(context); + else + { + m_returnOrderBy->setStay(false); + return m_operand->compress(context); + } +} + +SequenceType::Ptr OrderBy::staticType() const +{ + return m_operand->staticType(); +} + +SequenceType::List OrderBy::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +ExpressionVisitorResult::Ptr +OrderBy::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qorderby_p.h b/src/xmlpatterns/expr/qorderby_p.h new file mode 100644 index 0000000..332702b --- /dev/null +++ b/src/xmlpatterns/expr/qorderby_p.h @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** 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_OrderBy_H +#define Patternist_OrderBy_H + +#include "qatomiccomparator_p.h" +#include "qcomparisonplatform_p.h" +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + class ReturnOrderBy; + + /** + * @short Performs the sorting by being a parent to ForClause. + * + * The child of the ForClause is a ReturnOrderBy expression, which collects + * the sort keys and values. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class OrderBy : public SingleContainer + { + public: + enum Stability + { + StableOrder, + UnstableOrder + }; + + /** + * This class is value based. + */ + class OrderSpec : public ComparisonPlatform<OrderBy::OrderSpec, + true, /* Yes, issue errors. */ + AtomicComparator::AsValueComparison> + { + public: + /** + * We want this guy to be public. + */ + using ComparisonPlatform<OrderBy::OrderSpec, true, AtomicComparator::AsValueComparison>::detailedFlexibleCompare; + + typedef QVector<OrderSpec> Vector; + + enum Direction + { + Ascending, + Descending + }; + + /** + * @short Default constructor, which is needed by QVector. + */ + inline OrderSpec() + { + } + + inline OrderSpec(const Direction dir, + const StaticContext::OrderingEmptySequence orderingEmpty) : direction(dir), + orderingEmptySequence(orderingEmpty) + { + } + + void prepare(const Expression::Ptr &source, + const StaticContext::Ptr &context); + + const SourceLocationReflection *actualReflection() const + { + return m_expr.data(); + } + + private: + Expression::Ptr m_expr; + + public: + /** + * We place these afterwards, such that m_expr gets aligned at the + * start of the address. + */ + Direction direction; + + StaticContext::OrderingEmptySequence orderingEmptySequence; + + inline AtomicComparator::Operator operatorID() const + { + return orderingEmptySequence == StaticContext::Least ? AtomicComparator::OperatorLessThanNaNLeast + : AtomicComparator::OperatorLessThanNaNGreatest; + } + + }; + + OrderBy(const Stability stability, + const OrderSpec::Vector &orderSpecs, + const Expression::Ptr &operand, + ReturnOrderBy *const returnOrderBy); + + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + virtual SequenceType::Ptr staticType() const; + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + virtual SequenceType::List expectedOperandTypes() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + inline Item::Iterator::Ptr mapToSequence(const Item &i, + const DynamicContext::Ptr &context) const; + virtual Properties properties() const; + + private: + /** + * Needed when calling makeSequenceMappingIterator(). + */ + typedef QExplicitlySharedDataPointer<const OrderBy> ConstPtr; + + const Stability m_stability; + OrderSpec::Vector m_orderSpecs; + ReturnOrderBy *const m_returnOrderBy; + }; + + /* TODO Q_DECLARE_TYPEINFO(OrderBy::OrderSpec, Q_MOVABLE_TYPE); Breaks, + * probably because it's nested. */ +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qorexpression.cpp b/src/xmlpatterns/expr/qorexpression.cpp new file mode 100644 index 0000000..c2bbe3c --- /dev/null +++ b/src/xmlpatterns/expr/qorexpression.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qboolean_p.h" +#include "qcommonvalues_p.h" +#include "qliteral_p.h" + +#include "qorexpression_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +OrExpression::OrExpression(const Expression::Ptr &operand1, + const Expression::Ptr &operand2) : AndExpression(operand1, operand2) +{ +} + +bool OrExpression::evaluateEBV(const DynamicContext::Ptr &context) const +{ + return m_operand1->evaluateEBV(context) || m_operand2->evaluateEBV(context); +} + +Expression::Ptr OrExpression::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr newMe(PairContainer::compress(context)); + + if(newMe != this) + return newMe; + + /* Both operands mustn't be evaluated in order to be able to compress. */ + if(m_operand1->isEvaluated() && m_operand1->evaluateEBV(context->dynamicContext())) + return wrapLiteral(CommonValues::BooleanTrue, context, this); + else if(m_operand2->isEvaluated() && m_operand2->evaluateEBV(context->dynamicContext())) + return wrapLiteral(CommonValues::BooleanTrue, context, this); + else + return Expression::Ptr(this); +} + +ExpressionVisitorResult::Ptr OrExpression::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qorexpression_p.h b/src/xmlpatterns/expr/qorexpression_p.h new file mode 100644 index 0000000..c86f654 --- /dev/null +++ b/src/xmlpatterns/expr/qorexpression_p.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** 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_OrExpression_H +#define Patternist_OrExpression_H + +#include "qandexpression_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Implements XPath 2.0's logical expression @c or. + * + * @see <a href="http://www.w3.org/TR/xpath20/#id-logical-expressions">XML Path Language + * (XPath) 2.0, 3.6 Logical Expressions</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class OrExpression : public AndExpression + { + public: + OrExpression(const Expression::Ptr &operand1, + const Expression::Ptr &operand2); + + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qpaircontainer.cpp b/src/xmlpatterns/expr/qpaircontainer.cpp new file mode 100644 index 0000000..7ca7b53 --- /dev/null +++ b/src/xmlpatterns/expr/qpaircontainer.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qbuiltintypes_p.h" + +#include "qpaircontainer_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +PairContainer::PairContainer(const Expression::Ptr &operand1, + const Expression::Ptr &operand2) : m_operand1(operand1), + m_operand2(operand2) +{ + Q_ASSERT(m_operand1); + Q_ASSERT(m_operand2); +} + +Expression::List PairContainer::operands() const +{ + Expression::List list; + list.append(m_operand1); + list.append(m_operand2); + return list; +} + +void PairContainer::setOperands(const Expression::List &ops) +{ + Q_ASSERT(ops.count() == 2); + m_operand1 = ops.first(); + m_operand2 = ops.last(); + Q_ASSERT(m_operand1); + Q_ASSERT(m_operand2); +} + +bool PairContainer::compressOperands(const StaticContext::Ptr &context) +{ + Q_ASSERT(m_operand1); + Q_ASSERT(m_operand2); + rewrite(m_operand1, m_operand1->compress(context), context); + rewrite(m_operand2, m_operand2->compress(context), context); + + return m_operand1->isEvaluated() && m_operand2->isEvaluated(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qpaircontainer_p.h b/src/xmlpatterns/expr/qpaircontainer_p.h new file mode 100644 index 0000000..7acf7df --- /dev/null +++ b/src/xmlpatterns/expr/qpaircontainer_p.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** 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_PairContainer_H +#define Patternist_PairContainer_H + +#include "qexpression_p.h" +#include "qatomictype_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Base class for expressions that has exactly two operands. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class PairContainer : public Expression + { + public: + virtual Expression::List operands() const; + virtual void setOperands(const Expression::List &operands); + virtual bool compressOperands(const StaticContext::Ptr &); + + protected: + PairContainer(const Expression::Ptr &operand1, const Expression::Ptr &operand2); + + Expression::Ptr m_operand1; + Expression::Ptr m_operand2; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qparentnodeaxis.cpp b/src/xmlpatterns/expr/qparentnodeaxis.cpp new file mode 100644 index 0000000..b715782 --- /dev/null +++ b/src/xmlpatterns/expr/qparentnodeaxis.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" + +#include "qparentnodeaxis_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +Item ParentNodeAxis::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + return context->contextItem().asNode().iterate(QXmlNodeModelIndex::AxisParent)->next(); +} + +Expression::Properties ParentNodeAxis::properties() const +{ + return DisableElimination | RequiresContextItem; +} + +ExpressionVisitorResult::Ptr ParentNodeAxis::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +ItemType::Ptr ParentNodeAxis::expectedContextItemType() const +{ + return BuiltinTypes::node; +} + +SequenceType::Ptr ParentNodeAxis::staticType() const +{ + // Parentless node exists. + return CommonSequenceTypes::ZeroOrOneNode; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qparentnodeaxis_p.h b/src/xmlpatterns/expr/qparentnodeaxis_p.h new file mode 100644 index 0000000..ee5529f --- /dev/null +++ b/src/xmlpatterns/expr/qparentnodeaxis_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** 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_ParentNodeAxis_H +#define Patternist_ParentNodeAxis_H + +#include "qemptycontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Corresponds to the expression <tt>parent::node()</tt>. + * + * This AST node is now useless, due to refactorings. Prevously we had + * Item QAbstractXmlNodeModel::parent(), which didn't have the overhead of + * allocating an iterator for a single node. However, in order to stream + * line the API it is now gone and hence the node performs exactly the same + * as AxisStep. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ParentNodeAxis : public EmptyContainer + { + public: + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + + /** + * @returns always DisableElimination + */ + virtual Expression::Properties properties() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + /** + * @returns always CommonSequenceTypes::ExactlyOneNode; + */ + virtual SequenceType::Ptr staticType() const; + + /** + * @returns always BuiltinTypes::node; + */ + virtual ItemType::Ptr expectedContextItemType() const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qpath.cpp b/src/xmlpatterns/expr/qpath.cpp new file mode 100644 index 0000000..73cf0d9 --- /dev/null +++ b/src/xmlpatterns/expr/qpath.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qgenericsequencetype_p.h" +#include "qnodesort_p.h" +#include "qpatternistlocale_p.h" +#include "qsequencemappingiterator_p.h" +#include "qtypechecker_p.h" + +#include "qpath_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +Path::Path(const Expression::Ptr &operand1, + const Expression::Ptr &operand2, + const Kind kind) : PairContainer(operand1, operand2) + , m_hasCreatedSorter(kind != RegularPath) + , m_isLast(false) + , m_checkXPTY0018(kind == RegularPath) + , m_kind(kind) +{ +} + +Item::Iterator::Ptr Path::mapToSequence(const Item &item, + const DynamicContext::Ptr &context) const +{ + /* item is the focus here. That is in <e/>/1, item is <e/>. However, + * we don't use it, since the context item is accessed through + * DynamicContext::focusIterator() and friends. */ + Q_ASSERT(item); + Q_UNUSED(item); /* Needed when compiling in release mode. */ + return m_operand2->evaluateSequence(context); +} + +Item::Iterator::Ptr Path::evaluateSequence(const DynamicContext::Ptr &context) const +{ + /* Note, we use the old context for m_operand1. */ + const Item::Iterator::Ptr source(m_operand1->evaluateSequence(context)); + + const DynamicContext::Ptr focus(context->createFocus()); + focus->setFocusIterator(source); + + const Item::Iterator::Ptr result(makeSequenceMappingIterator<Item>(ConstPtr(this), source, focus)); + + if(m_checkXPTY0018) + { + /* This is an expensive code path, but it should happen very rarely. */ + + enum FoundItem + { + FoundNone, + FoundNode, + FoundAtomicValue + } hasFound = FoundNone; + + Item::List whenChecked; + + Item next(result->next()); + + while(next) + { + const FoundItem found = next.isAtomicValue() ? FoundAtomicValue : FoundNode; + + if(hasFound != FoundNone && hasFound != found) + { + /* It's an atomic value and we've already found a node. Mixed content. */ + context->error(QtXmlPatterns::tr("The last step in a path must contain either nodes " + "or atomic values. It cannot be a mixture between the two."), + ReportContext::XPTY0018, this); + } + else + hasFound = found; + + whenChecked.append(next); + next = result->next(); + } + + return makeListIterator(whenChecked); + } + else + return result; +} + +Item Path::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + /* This function is called if both operands' cardinality is exactly-one. Therefore + * we manually go forward in the focus by calling next(). + * + * We don't check for XPTY0018, only in evaluateSequence(), since if we're guaranteed + * to evaluate to one item, we can only evaluate to one node or one atomic value. + */ + + /* Note, we use the old context for m_operand1. */ + const Item::Iterator::Ptr source(m_operand1->evaluateSequence(context)); + + const DynamicContext::Ptr focus(context->createFocus()); + focus->setFocusIterator(source); + + /* This test is needed because if the focus is empty, we don't want to(nor can't) evaluate + * the next step. */ + // TODO Why are we at all invoked then? + if(source->next()) + return m_operand2->evaluateSingleton(focus); + else + return Item(); +} + +void Path::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + /* Note, we use the old context for m_operand1. */ + const Item::Iterator::Ptr source(m_operand1->evaluateSequence(context)); + + const DynamicContext::Ptr focus(context->createFocus()); + focus->setFocusIterator(source); + + while(source->next()) + m_operand2->evaluateToSequenceReceiver(focus); +} + +Expression::Ptr Path::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr me(PairContainer::compress(context)); + + /* "./expr" is by now equal to "expr" since we've done + * focus/type checks, and a node sorter has been inserted. */ + if(m_operand1->is(IDContextItem)) + return m_operand2; + + /* We do this as late as we can, such that we pick up the most recent type + * from the operand. */ + if(m_isLast && m_kind != XSLTForEach && m_operand2->staticType()->itemType() == BuiltinTypes::item) + m_checkXPTY0018 = true; + + return me; +} + +Expression::Ptr Path::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + m_operand2->announceFocusType(newFocusType()); + + /* Here we apply the function conversion first, and with the error code + * that we want -- XPTY0019 instead of XPTY0004. Unfortunately + * PairContainer::typeCheck() will do the type check again, which is + * redundant in the case of when we're not XSLTForEach. + * + * If we're XSLTForEach, it means we're a synthetic "map" expression for + * implementing various XSL-T expressions, and hence don't have the + * constraint of XPTY0019. + * + * It's important that typeCheck() is run for the operands(of course), and the call to + * PairContainer::typeCheck() ensures that below, in the case that we're XSL-T code. + * + * The type we expect, CommonSequenceTypes::ZeroOrMoreNodes() needs to be in sync with + * what we return in expectedOperandTypes(). */ + if(m_kind != XSLTForEach) + { + m_operand1 = TypeChecker::applyFunctionConversion(m_operand1, + CommonSequenceTypes::ZeroOrMoreNodes, + context, + m_kind == ForApplyTemplate ? ReportContext::XTTE0520 + : ReportContext::XPTY0019); + } + + /* If our step ends with atomic values, we cannot sort. + * + * We must smack the NodeSortExpression ontop before calling typeCheck(), since the latter + * may insert an Atomizer, as possibly mandated by reqType. By doing it after, the Atomizer + * will be a parent to NodeSortExpression, as opposed to a child. + */ + if(!m_hasCreatedSorter) + { + m_hasCreatedSorter = true; + + return NodeSortExpression::wrapAround(Expression::Ptr(this), context)->typeCheck(context, reqType); + } + else + return PairContainer::typeCheck(context, reqType); +} + +SequenceType::List Path::expectedOperandTypes() const +{ + SequenceType::List result; + + /* This value needs to be in sync with what we pass to + * applyFunctionConversion() in typeCheck() above. + * + * We don't have the XPTY0019 restriction when we're synthetic XSL-T code. + */ + if(m_kind == XSLTForEach) + result.append(CommonSequenceTypes::ZeroOrMoreItems); + else + result.append(CommonSequenceTypes::ZeroOrMoreNodes); + + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +SequenceType::Ptr Path::staticType() const +{ + const SequenceType::Ptr opType(m_operand2->staticType()); + + /* For each parent step, we evaluate the child step. So multiply the two + * cardinalities. */ + return makeGenericSequenceType(opType->itemType(), + m_operand1->staticType()->cardinality() * opType->cardinality()); +} + +ExpressionVisitorResult::Ptr Path::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::Properties Path::properties() const +{ + return CreatesFocusForLast | ((m_operand1->properties() | m_operand2->properties()) & (RequiresCurrentItem | DisableElimination)); +} + +ItemType::Ptr Path::newFocusType() const +{ + return m_operand1->staticType()->itemType(); +} + +Expression::ID Path::id() const +{ + return IDPath; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qpath_p.h b/src/xmlpatterns/expr/qpath_p.h new file mode 100644 index 0000000..e4dc365 --- /dev/null +++ b/src/xmlpatterns/expr/qpath_p.h @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** 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_Path_H +#define Patternist_Path_H + +#include "qpaircontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short Implements the path expression, containing two steps, such as in <tt>html/body</tt>. + * + * @see <a href="http://www.w3.org/TR/xquery/#id-path-expressions">XQuery 1.0: An + * XML Query Language, 3.2 Path Expressions</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class Path : public PairContainer + { + public: + enum Kind + { + /** + * This Path is a plain old path expression as found in XPath. + * Sorting is performed, and atomics are disallowed as left + * operand. + */ + RegularPath = 1, + + /** + * This Path emulates an @c xsl:for-each instruction. This means no + * sorting of result, and atomics are allowed as left operand. + */ + XSLTForEach, + + /** + * This Path performs the iteration in an @c xsl:apply-templates + * instruction. This means sorting, and atomics are disallowed + * as left operand. + */ + ForApplyTemplate + }; + + Path(const Expression::Ptr &operand1, + const Expression::Ptr &operand2, + const Kind kind = RegularPath); + + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + inline Item::Iterator::Ptr mapToSequence(const Item &item, + const DynamicContext::Ptr &context) const; + + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + + virtual SequenceType::List expectedOperandTypes() const; + + /** + * @returns the static type of the last step where the cardinality is multiplied with + * the cardinality of the first step's cardinality. + */ + virtual SequenceType::Ptr staticType() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + virtual Properties properties() const; + + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + + /** + * @returns the item type of the last step's static type. + */ + virtual ItemType::Ptr newFocusType() const; + + virtual ID id() const; + + inline void setLast(); + + inline Kind kind() const + { + return m_kind; + } + + private: + typedef QExplicitlySharedDataPointer<const Path> ConstPtr; + + /** + * One might think this block exists for preventing multiple + * NodeSortExpressions to be created. However, that is not an issue, + * since NodeSortExpression optimizes this away anyway. + * + * The real reason is to avoid infinite recursion. When our typeCheck() + * forwards on the type check to the just created + * NodeSortExpression, it in turn calls typeCheck() on its child, which + * is this Path. Rince and repeat. + * + * We only create node sorts when we're a regular path expression, and + * not when standing in as a generic map expression. */ + bool m_hasCreatedSorter; + + /** + * Whether this path is the step. For instance, in <tt>a/b/c</tt>, the + * last path has @c c as the right operand. + */ + bool m_isLast; + + bool m_checkXPTY0018; + const Kind m_kind; + }; + + void Path::setLast() + { + m_isLast = true; + } +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qpositionalvariablereference.cpp b/src/xmlpatterns/expr/qpositionalvariablereference.cpp new file mode 100644 index 0000000..0b4f69b --- /dev/null +++ b/src/xmlpatterns/expr/qpositionalvariablereference.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qinteger_p.h" + +#include "qpositionalvariablereference_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +PositionalVariableReference::PositionalVariableReference(const VariableSlotID s) : VariableReference(s) +{ +} + +Item PositionalVariableReference::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + Q_ASSERT(context); + Q_ASSERT(context->positionIterator(slot())); + return Integer::fromValue(context->positionIterator(slot())->position()); +} + +bool PositionalVariableReference::evaluateEBV(const DynamicContext::Ptr &) const +{ + return true; +} + +SequenceType::Ptr PositionalVariableReference::staticType() const +{ + return CommonSequenceTypes::ExactlyOneInteger; +} + +Expression::Properties PositionalVariableReference::properties() const +{ + return DependsOnLocalVariable; +} + +ExpressionVisitorResult::Ptr + +PositionalVariableReference::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qpositionalvariablereference_p.h b/src/xmlpatterns/expr/qpositionalvariablereference_p.h new file mode 100644 index 0000000..9fe3cbd --- /dev/null +++ b/src/xmlpatterns/expr/qpositionalvariablereference_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** 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_PositionVariableReference_H +#define Patternist_PositionVariableReference_H + +#include "qvariablereference_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A reference to an @c at variable, declared with the + * <tt>for</tt>-part in XQuery's FLWOR expression. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class PositionalVariableReference : public VariableReference + { + public: + typedef QExplicitlySharedDataPointer<PositionalVariableReference> Ptr; + PositionalVariableReference(const VariableSlotID slot); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + + /** + * Returns always @c true, since a positional variable is always one or more, and the + * Effective %Boolean Value for that range is always @c true. + * + * @returns always @c true + */ + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + + /** + * @returns always CommonSequenceTypes::ExactlyOneInteger + */ + virtual SequenceType::Ptr staticType() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual Properties properties() const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qprocessinginstructionconstructor.cpp b/src/xmlpatterns/expr/qprocessinginstructionconstructor.cpp new file mode 100644 index 0000000..d933ee0 --- /dev/null +++ b/src/xmlpatterns/expr/qprocessinginstructionconstructor.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qpatternistlocale_p.h" +#include "qnodebuilder_p.h" +#include "qqnamevalue_p.h" + +#include "qprocessinginstructionconstructor_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ProcessingInstructionConstructor:: +ProcessingInstructionConstructor(const Expression::Ptr &op1, + const Expression::Ptr &op2) : PairContainer(op1, op2) +{ +} + +QString ProcessingInstructionConstructor::leftTrimmed(const QString &input) +{ + const int len = input.length(); + + for(int i = 0; i < len; ++i) + { + if(!input.at(i).isSpace()) + return input.mid(i); + } + + return QString(); /* input consists only of whitespace. All was trimmed. */ +} + +QString ProcessingInstructionConstructor::data(const DynamicContext::Ptr &context) const +{ + const Item name(m_operand1->evaluateSingleton(context)); + const Item dataArg(m_operand2->evaluateSingleton(context)); + + if(dataArg) + { + /* Perform trimming before validation, to increase speed. */ + const QString value(leftTrimmed(dataArg.stringValue())); + + if(value.contains(QLatin1String("?>"))) + { + context->error(QtXmlPatterns::tr("The data of a processing instruction cannot contain the string %1").arg(formatData("?>")), + ReportContext::XQDY0026, this); + return QString(); + } + else + return value; + } + else + return QString(); +} + +QXmlName ProcessingInstructionConstructor::evaluateTardata(const DynamicContext::Ptr &context) const +{ + const Item name(m_operand1->evaluateSingleton(context)); + return context->namePool()->allocateQName(QString(), name.stringValue()); +} + +Item ProcessingInstructionConstructor::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + const NodeBuilder::Ptr nodeBuilder(context->nodeBuilder(QUrl())); + + nodeBuilder->processingInstruction(evaluateTardata(context), data(context)); + + const QAbstractXmlNodeModel::Ptr nm(nodeBuilder->builtDocument()); + context->addNodeModel(nm); + + return nm->root(QXmlNodeModelIndex()); +} + +void ProcessingInstructionConstructor::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + QAbstractXmlReceiver *const receiver = context->outputReceiver(); + + receiver->processingInstruction(evaluateTardata(context), data(context)); +} + +SequenceType::Ptr ProcessingInstructionConstructor::staticType() const +{ + return CommonSequenceTypes::ExactlyOneProcessingInstruction; +} + +SequenceType::List ProcessingInstructionConstructor::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ExactlyOneString); + result.append(CommonSequenceTypes::ZeroOrOneString); + return result; +} + +Expression::Properties ProcessingInstructionConstructor::properties() const +{ + return DisableElimination | IsNodeConstructor; +} + +ExpressionVisitorResult::Ptr +ProcessingInstructionConstructor::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qprocessinginstructionconstructor_p.h b/src/xmlpatterns/expr/qprocessinginstructionconstructor_p.h new file mode 100644 index 0000000..950ebc8 --- /dev/null +++ b/src/xmlpatterns/expr/qprocessinginstructionconstructor_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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_ProcessingInstructionConstructor_H +#define Patternist_ProcessingInstructionConstructor_H + +#include "qpaircontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Constructs an element node. This covers both computed and directly constructed + * element nodes. + * + * @see <a href="http://www.w3.org/TR/xquery/#id-constructors">XQuery + * 1.0: An XML Query Language, 3.7 Constructors</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ProcessingInstructionConstructor : public PairContainer + { + public: + ProcessingInstructionConstructor(const Expression::Ptr &operand1, + const Expression::Ptr &operand2); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + virtual SequenceType::Ptr staticType() const; + + /** + * Both arguments must of type @c xs:string. It is assumes that the first argument's + * lexical space is @c xs:NCName. + */ + virtual SequenceType::List expectedOperandTypes() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + virtual Properties properties() const; + private: + inline QXmlName evaluateTardata(const DynamicContext::Ptr &context) const; + /** + * Performs left-trimming only. + * + * @see QString::trimmed() + */ + static inline QString leftTrimmed(const QString &input); + + QString data(const DynamicContext::Ptr &context) const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qqnameconstructor.cpp b/src/xmlpatterns/expr/qqnameconstructor.cpp new file mode 100644 index 0000000..7925e2b --- /dev/null +++ b/src/xmlpatterns/expr/qqnameconstructor.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qpatternistlocale_p.h" +#include "qqnamevalue_p.h" + +#include "qqnameconstructor_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +QNameConstructor::QNameConstructor(const Expression::Ptr &source, + const NamespaceResolver::Ptr &nsResolver) : SingleContainer(source), + m_nsResolver(nsResolver) +{ + Q_ASSERT(m_nsResolver); +} + +Item QNameConstructor::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + Q_ASSERT(context); + const QString lexQName(m_operand->evaluateSingleton(context).stringValue()); + + const QXmlName expQName(expandQName<DynamicContext::Ptr, + ReportContext::XQDY0074, + ReportContext::XQDY0074>(lexQName, + context, + m_nsResolver, + this)); + return toItem(QNameValue::fromValue(context->namePool(), expQName)); +} + +QXmlName::NamespaceCode QNameConstructor::namespaceForPrefix(const QXmlName::PrefixCode prefix, + const StaticContext::Ptr &context, + const SourceLocationReflection *const r) +{ + Q_ASSERT(context); + const QXmlName::NamespaceCode ns(context->namespaceBindings()->lookupNamespaceURI(prefix)); + + if(ns == NamespaceResolver::NoBinding) + { + context->error(QtXmlPatterns::tr("No namespace binding exists for the prefix %1") + .arg(formatKeyword(context->namePool()->stringForPrefix(prefix))), + ReportContext::XPST0081, + r); + return NamespaceResolver::NoBinding; + } + else + return ns; +} + +SequenceType::Ptr QNameConstructor::staticType() const +{ + return CommonSequenceTypes::ExactlyOneQName; +} + +SequenceType::List QNameConstructor::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ExactlyOneString); + return result; +} + +ExpressionVisitorResult::Ptr QNameConstructor::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +const SourceLocationReflection *QNameConstructor::actualReflection() const +{ + return m_operand.data(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qqnameconstructor_p.h b/src/xmlpatterns/expr/qqnameconstructor_p.h new file mode 100644 index 0000000..4011870 --- /dev/null +++ b/src/xmlpatterns/expr/qqnameconstructor_p.h @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** 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_QNameConstructor_H +#define Patternist_QNameConstructor_H + +#include "qsinglecontainer_p.h" +#include "qbuiltintypes_p.h" +#include "qpatternistlocale_p.h" +#include "qxpathhelper_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Creates an @c xs:QName value from a lexical QName using + * statically known namespace bindings. + * + * @see QQNameValue + * @see QXmlUtils + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class QNameConstructor : public SingleContainer + { + public: + + QNameConstructor(const Expression::Ptr &source, + const NamespaceResolver::Ptr &nsResolver); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &) const; + + virtual SequenceType::List expectedOperandTypes() const; + + virtual SequenceType::Ptr staticType() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + /** + * Expands @p lexicalQName, which is a lexical representation of a QName such as "x:body", into + * a QName using @p nsResolver to supply the namespace bindings. + * + * If @p lexicalQName is lexically invalid @p InvalidQName is raised via @p context, or if + * no namespace binding does not exists for a prefix(if any) in @p lexicalQName, @p NoBinding + * is raised via @p context. + * + * If @p asForAttribute is @c true, the name is considered to be for an + * attribute in some way, and @p lexicalQName will not pick up the + * default namespace if it doesn't have a prefix. + * + * @p nsResolver is parameterized meaning the function can be instantiated with either + * DynamicContext or StaticContext. + * + * @see QQNameValue + * @see QXmlUtils + */ + template<typename TReportContext, + const ReportContext::ErrorCode InvalidQName, + const ReportContext::ErrorCode NoBinding> + static + QXmlName expandQName(const QString &lexicalQName, + const TReportContext &context, + const NamespaceResolver::Ptr &nsResolver, + const SourceLocationReflection *const r, + const bool asForAttribute = false); + + /** + * Resolves the namespace prefix @p prefix to its namespace if it exists, or + * raised ReportContext::XPST0081 otherwise. + * + * @returns the namespace URI corresponding to @p prefix + */ + static QXmlName::NamespaceCode namespaceForPrefix(const QXmlName::PrefixCode prefix, + const StaticContext::Ptr &context, + const SourceLocationReflection *const r); + + virtual const SourceLocationReflection *actualReflection() const; + + private: + const NamespaceResolver::Ptr m_nsResolver; + }; + + template<typename TReportContext, + const ReportContext::ErrorCode InvalidQName, + const ReportContext::ErrorCode NoBinding> + QXmlName QNameConstructor::expandQName(const QString &lexicalQName, + const TReportContext &context, + const NamespaceResolver::Ptr &nsResolver, + const SourceLocationReflection *const r, + const bool asForAttribute) + { + Q_ASSERT(nsResolver); + Q_ASSERT(context); + + if(XPathHelper::isQName(lexicalQName)) + { + QString prefix; + QString local; + XPathHelper::splitQName(lexicalQName, prefix, local); + const QXmlName::NamespaceCode nsCode = asForAttribute && prefix.isEmpty() ? QXmlName::NamespaceCode(StandardNamespaces::empty) + : (nsResolver->lookupNamespaceURI(context->namePool()->allocatePrefix(prefix))); + + if(nsCode == NamespaceResolver::NoBinding) + { + context->error(QtXmlPatterns::tr("No namespace binding exists for " + "the prefix %1 in %2").arg(formatKeyword(prefix), + formatKeyword(lexicalQName)), + NoBinding, + r); + return QXmlName(); /* Silence compiler warning. */ + } + else + return context->namePool()->allocateQName(context->namePool()->stringForNamespace(nsCode), local, prefix); + } + else + { + context->error(QtXmlPatterns::tr("%1 is an invalid %2") + .arg(formatData(lexicalQName)) + .arg(formatType(context->namePool(), BuiltinTypes::xsQName)), + InvalidQName, + r); + return QXmlName(); /* Silence compiler warning. */ + } + } +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qquantifiedexpression.cpp b/src/xmlpatterns/expr/qquantifiedexpression.cpp new file mode 100644 index 0000000..a6c4d03 --- /dev/null +++ b/src/xmlpatterns/expr/qquantifiedexpression.cpp @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qgenericsequencetype_p.h" +#include "qitemmappingiterator_p.h" + +#include "qquantifiedexpression_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +QuantifiedExpression::QuantifiedExpression(const VariableSlotID varSlot, + const Operator quantifier, + const Expression::Ptr &inClause, + const Expression::Ptr &testExpression) + : PairContainer(inClause, testExpression), + m_varSlot(varSlot), + m_quantifier(quantifier) +{ + Q_ASSERT(quantifier == Some || quantifier == Every); +} + +Item QuantifiedExpression::mapToItem(const Item &item, + const DynamicContext::Ptr &context) const +{ + context->setRangeVariable(m_varSlot, item); + return item; +} + +bool QuantifiedExpression::evaluateEBV(const DynamicContext::Ptr &context) const +{ + const Item::Iterator::Ptr it(makeItemMappingIterator<Item>(ConstPtr(this), + m_operand1->evaluateSequence(context), + context)); + + Item item(it->next()); + + if(m_quantifier == Some) + { + while(item) + { + if(m_operand2->evaluateEBV(context)) + return true; + else + item = it->next(); + }; + + return false; + } + else + { + Q_ASSERT(m_quantifier == Every); + + while(item) + { + if(m_operand2->evaluateEBV(context)) + item = it->next(); + else + return false; + } + + return true; + } +} + +QString QuantifiedExpression::displayName(const Operator quantifier) +{ + if(quantifier == Some) + return QLatin1String("some"); + else + { + Q_ASSERT(quantifier == Every); + return QLatin1String("every"); + } +} + +SequenceType::Ptr QuantifiedExpression::staticType() const +{ + return CommonSequenceTypes::ExactlyOneBoolean; +} + +SequenceType::List QuantifiedExpression::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + result.append(CommonSequenceTypes::EBV); + return result; +} + +QuantifiedExpression::Operator QuantifiedExpression::operatorID() const +{ + return m_quantifier; +} + +ExpressionVisitorResult::Ptr QuantifiedExpression::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qquantifiedexpression_p.h b/src/xmlpatterns/expr/qquantifiedexpression_p.h new file mode 100644 index 0000000..0c65782 --- /dev/null +++ b/src/xmlpatterns/expr/qquantifiedexpression_p.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** 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_QuantifiedExpression_H +#define Patternist_QuantifiedExpression_H + +#include "qpaircontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Implements XPath 2.0's quantification expressions @c some and @c every. + * + * @see <a href="http://www.w3.org/TR/xpath20/#id-quantified-expressions">XML Path Language + * (XPath) 2.0, 3.9 Quantified Expressions</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class Q_AUTOTEST_EXPORT QuantifiedExpression : public PairContainer + { + public: + enum Operator + { + Some = 1, + Every + }; + + QuantifiedExpression(const VariableSlotID varSlot, + const Operator quantifier, + const Expression::Ptr &inClause, + const Expression::Ptr &testExpression); + + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + virtual SequenceType::Ptr staticType() const; + virtual SequenceType::List expectedOperandTypes() const; + + Operator operatorID() const; + + /** + * Determines the string representation for a quantification operator. + * + * @return "some" if @p quantifier is Some, or "every" if @p quantifier + * is Every + */ + static QString displayName(const Operator quantifier); + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + inline Item mapToItem(const Item &item, const DynamicContext::Ptr &context) const; + + private: + typedef QExplicitlySharedDataPointer<const QuantifiedExpression> ConstPtr; + const VariableSlotID m_varSlot; + const Operator m_quantifier; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qrangeexpression.cpp b/src/xmlpatterns/expr/qrangeexpression.cpp new file mode 100644 index 0000000..b4d7e91 --- /dev/null +++ b/src/xmlpatterns/expr/qrangeexpression.cpp @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qcommonvalues_p.h" +#include "qgenericsequencetype_p.h" +#include "qinteger_p.h" +#include "qliteral_p.h" +#include "qrangeiterator_p.h" + +#include "qrangeexpression_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +RangeExpression::RangeExpression(const Expression::Ptr &operand1, + const Expression::Ptr &operand2) : PairContainer(operand1, operand2) +{ +} + +Item::Iterator::Ptr RangeExpression::evaluateSequence(const DynamicContext::Ptr &context) const +{ + const Item s(m_operand1->evaluateSingleton(context)); + + if(!s) + return CommonValues::emptyIterator; + + const Item e(m_operand2->evaluateSingleton(context)); + if(!e) + return CommonValues::emptyIterator; + + const xsInteger start = s.as<Numeric>()->toInteger(); + const xsInteger end = e.as<Numeric>()->toInteger(); + + if(start > end) + return CommonValues::emptyIterator; + else if(start == end) + return makeSingletonIterator(s); + else + return Item::Iterator::Ptr(new RangeIterator(start, RangeIterator::Forward, end)); +} + +Item RangeExpression::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + return m_operand1->evaluateSingleton(context); +} + +SequenceType::List RangeExpression::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrOneInteger); + result.append(CommonSequenceTypes::ZeroOrOneInteger); + return result; +} + +SequenceType::Ptr RangeExpression::staticType() const +{ + /* This logic makes the Cardinality more specific. */ + Cardinality::Count from; + bool hasFrom; + + if(m_operand1->is(IDIntegerValue)) + { + from = m_operand1->as<Literal>()->item().as<Integer>()->toInteger(); + hasFrom = true; + } + else + { + hasFrom = false; + from = 0; + } + + /* We can't check whether to is -1 since maybe the user wrote -1. Hence + * hasTo is required. */ + bool hasTo; + Cardinality::Count to; + + if(m_operand2->is(IDIntegerValue)) + { + const xsInteger asInt = m_operand2->as<Literal>()->item().as<Integer>()->toInteger(); + to = asInt; + + if(to == asInt) + hasTo = true; + else + { + /* Cardinality::Count is not the same as type xsInteger. We had overflow. */ + to = -1; + hasTo = false; + } + } + else + { + to = -1; + hasTo = false; + } + + if(hasTo && hasFrom) + { + if(from > to) + { + /* The query is incorrectly written, we'll evaluate to the empty sequence. + * Just return what's correct. */ + return CommonSequenceTypes::ZeroOrMoreIntegers; + } + else + { + Cardinality::Count count = (to - from) + 1; /* + 1, since it's inclusive. */ + return makeGenericSequenceType(BuiltinTypes::xsInteger, Cardinality::fromExact(count)); + } + } + else + { + /* We can't do fromExact(from, -1) since the latter can evaluate to a value that actually is + * lower than from, although that unfortunately is very unlikely. */ + return CommonSequenceTypes::ZeroOrMoreIntegers; + } +} + +Expression::Properties RangeExpression::properties() const +{ + return Expression::DisableElimination; +} + +ExpressionVisitorResult::Ptr RangeExpression::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qrangeexpression_p.h b/src/xmlpatterns/expr/qrangeexpression_p.h new file mode 100644 index 0000000..94756d7 --- /dev/null +++ b/src/xmlpatterns/expr/qrangeexpression_p.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** 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_RangeExpression_H +#define Patternist_RangeExpression_H + +#include "qpaircontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short Implements XPath 2.0's @c to expression. + * + * Despite its name, RangeExpression is not related to RangeVariableDeclaration. + * + * @see <a href="http://www.w3.org/TR/xpath20/#construct_seq">XML Path Language + * (XPath) 2.0, 3.3.1 Constructing Sequences</a> + * @see RangeIterator + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class RangeExpression : public PairContainer + { + public: + RangeExpression(const Expression::Ptr &operand1, const Expression::Ptr &operand2); + + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &) const; + /** + * It's likely that this function gets called if staticType() inferred + * the cardinality to an exact number. In that case, we know that the + * first arguments is the same as the second argument. + */ + virtual Item evaluateSingleton(const DynamicContext::Ptr &) const; + + virtual SequenceType::List expectedOperandTypes() const; + + /** + * @returns always CommonSequenceTypes::ZeroOrMoreIntegers + */ + virtual SequenceType::Ptr staticType() const; + + /** + * Disables compression for optimization reasons. For example, the + * expression "1 to 1000" would consume thousand allocated instances + * of Integer, and RangeIterator is well suited for dynamic evaluation. + * + * @returns Expression::DisableElimination + */ + virtual Expression::Properties properties() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qrangevariablereference.cpp b/src/xmlpatterns/expr/qrangevariablereference.cpp new file mode 100644 index 0000000..e4d6c7e --- /dev/null +++ b/src/xmlpatterns/expr/qrangevariablereference.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qboolean_p.h" +#include "qgenericsequencetype_p.h" + +#include "qrangevariablereference_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +RangeVariableReference::RangeVariableReference(const Expression::Ptr &source, + const VariableSlotID slotP) : VariableReference(slotP), + m_sourceExpression(source) +{ + Q_ASSERT(source); +} + +bool RangeVariableReference::evaluateEBV(const DynamicContext::Ptr &context) const +{ + Q_ASSERT_X(context->rangeVariable(slot()), Q_FUNC_INFO, "The range variable must be set."); + return Boolean::evaluateEBV(context->rangeVariable(slot()), context); +} + +Item RangeVariableReference::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + Q_ASSERT_X(context->rangeVariable(slot()), Q_FUNC_INFO, "The range variable must be set."); + return context->rangeVariable(slot()); +} + +SequenceType::Ptr RangeVariableReference::staticType() const +{ + return makeGenericSequenceType(m_sourceExpression->staticType()->itemType(), + Cardinality::exactlyOne()); +} + +Expression::ID RangeVariableReference::id() const +{ + return IDRangeVariableReference; +} + +ExpressionVisitorResult::Ptr +RangeVariableReference::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::Properties RangeVariableReference::properties() const +{ + return DependsOnLocalVariable; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qrangevariablereference_p.h b/src/xmlpatterns/expr/qrangevariablereference_p.h new file mode 100644 index 0000000..1246937 --- /dev/null +++ b/src/xmlpatterns/expr/qrangevariablereference_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** 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_RangeVariableReference_H +#define Patternist_RangeVariableReference_H + +#include "qvariablereference_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A reference to a variable declared with @c for or a quantification + * expression, but not for instance a @c let binding. + * + * A range variable always represents a single item, while an other + * expression provides the binding and iteration. A @c for expression is + * a good example. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class RangeVariableReference : public VariableReference + { + public: + RangeVariableReference(const Expression::Ptr &sourceExpression, + const VariableSlotID slot); + + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual SequenceType::Ptr staticType() const; + + /** + * @returns IDRangeVariableReference + */ + virtual ID id() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual Properties properties() const; + private: + const Expression::Ptr m_sourceExpression; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qreturnorderby.cpp b/src/xmlpatterns/expr/qreturnorderby.cpp new file mode 100644 index 0000000..c530971 --- /dev/null +++ b/src/xmlpatterns/expr/qreturnorderby.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qexpressionsequence_p.h" +#include "qsorttuple_p.h" + +#include "qreturnorderby_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ReturnOrderBy::ReturnOrderBy(const OrderBy::Stability aStability, + const OrderBy::OrderSpec::Vector &oSpecs, + const Expression::List &ops) : UnlimitedContainer(ops) + , m_stability(aStability) + , m_orderSpecs(oSpecs) + , m_flyAway(true) +{ + Q_ASSERT_X(m_operands.size() >= 2, Q_FUNC_INFO, + "ReturnOrderBy must have the return expression, and at least one sort key."); + Q_ASSERT(m_orderSpecs.size() == ops.size() - 1); +} + +Item ReturnOrderBy::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + Q_ASSERT(m_operands.size() > 1); + const Item::Iterator::Ptr value(makeListIterator(m_operands.first()->evaluateSequence(context)->toList())); + Item::Vector sortKeys; + + /* We're skipping the first operand. */ + const int len = m_operands.size() - 1; + sortKeys.resize(len); + + for(int i = 1; i <= len; ++i) + sortKeys[i - 1] = m_operands.at(i)->evaluateSingleton(context); + + return Item(new SortTuple(value, sortKeys)); +} + +bool ReturnOrderBy::evaluateEBV(const DynamicContext::Ptr &context) const +{ + // TODO This is temporary code. + return m_operands.first()->evaluateEBV(context); +} + +Expression::Ptr ReturnOrderBy::compress(const StaticContext::Ptr &context) +{ + /* We first did this in typeCheck(), but that broke due to that type checks were + * missed, which other pieces relied on. */ + if(m_flyAway) + { + /* We only want the return expression, not the sort keys. */ + return m_operands.first()->compress(context); + } + else + { + /* We don't need the members, so don't keep a reference to them. */ + m_orderSpecs.clear(); + + return UnlimitedContainer::compress(context); + } +} + +Expression::Properties ReturnOrderBy::properties() const +{ + /* For some unknown reason this is necessary for XQTS test case orderBy18. */ + return DisableElimination; +} + +ExpressionVisitorResult::Ptr ReturnOrderBy::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +SequenceType::Ptr ReturnOrderBy::staticType() const +{ + return m_operands.first()->staticType(); +} + +SequenceType::List ReturnOrderBy::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + result.append(CommonSequenceTypes::ZeroOrOneAtomicType); + return result; +} + +Expression::ID ReturnOrderBy::id() const +{ + return IDReturnOrderBy; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qreturnorderby_p.h b/src/xmlpatterns/expr/qreturnorderby_p.h new file mode 100644 index 0000000..6a51717 --- /dev/null +++ b/src/xmlpatterns/expr/qreturnorderby_p.h @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** 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_ReturnOrderBy_H +#define Patternist_ReturnOrderBy_H + +#include "qorderby_p.h" +#include "qunlimitedcontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Together with OrderBy, it implements XQuery 1.0's <tt>order by</tt> expression. + * + * ReturnOrderBy evaluates the sort keys and values, and hands it over to + * OrderBy, which is an AST ancestor, using SortTuples. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ReturnOrderBy : public UnlimitedContainer + { + public: + /** + * In @p operands the first item is the return expression, and the + * rest, which is at least one, are the sort keys. + */ + ReturnOrderBy(const OrderBy::Stability stability, + const OrderBy::OrderSpec::Vector &oSpecs, + const Expression::List &operands); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + virtual SequenceType::Ptr staticType() const; + virtual SequenceType::List expectedOperandTypes() const; + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual ID id() const; + + inline OrderBy::OrderSpec::Vector orderSpecs() const + { + return m_orderSpecs; + } + + inline OrderBy::Stability stability() const + { + return m_stability; + } + + /** + * In the case of that we don't have a for-expression beloning us, but + * only a let clause, this ReturnOrderBy breaks if it stays in the AST. + * So, by default we assume that we should write ourselves away, unless + * this function is called. The associated ForClause will call it + * during typeCheck(), if it exists. + */ + inline void setStay(const bool a) + { + m_flyAway = !a; + } + + virtual Properties properties() const; + private: + /** + * This variable is unfortunately only used at compile time. However, + * it's tricky to get rid of it due to how QueryTransformParser would + * have to be adapted. + */ + const OrderBy::Stability m_stability; + + OrderBy::OrderSpec::Vector m_orderSpecs; + + /** + * @see stay() + */ + bool m_flyAway; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qsimplecontentconstructor.cpp b/src/xmlpatterns/expr/qsimplecontentconstructor.cpp new file mode 100644 index 0000000..e98d988 --- /dev/null +++ b/src/xmlpatterns/expr/qsimplecontentconstructor.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qatomicstring_p.h" + +#include "qsimplecontentconstructor_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +SimpleContentConstructor::SimpleContentConstructor(const Expression::Ptr &operand) : SingleContainer(operand) +{ +} + +Item SimpleContentConstructor::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + const Item::Iterator::Ptr it(m_operand->evaluateSequence(context)); + Item next(it->next()); + QString result; + + if(next) + { + result = next.stringValue(); + next = it->next(); + } + else + return Item(); + + while(next) + { + result += QLatin1Char(' '); + result += next.stringValue(); + next = it->next(); + } + + return AtomicString::fromValue(result); +} + +Expression::Ptr SimpleContentConstructor::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr me(SingleContainer::compress(context)); + + if(me.data() == this) + { + /* Optimization: if we will evaluate to a single string, we're not + * necessary. */ + if(CommonSequenceTypes::ExactlyOneString->matches(m_operand->staticType())) + return m_operand; + } + + return me; +} + +SequenceType::List SimpleContentConstructor::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreAtomicTypes); + return result; +} + +SequenceType::Ptr SimpleContentConstructor::staticType() const +{ + if(m_operand->staticType()->cardinality().allowsEmpty()) + return CommonSequenceTypes::ZeroOrOneString; + else + return CommonSequenceTypes::ExactlyOneString; +} + +ExpressionVisitorResult::Ptr SimpleContentConstructor::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qsimplecontentconstructor_p.h b/src/xmlpatterns/expr/qsimplecontentconstructor_p.h new file mode 100644 index 0000000..bb80b4a --- /dev/null +++ b/src/xmlpatterns/expr/qsimplecontentconstructor_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** 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_SimpleContentConstructor_H +#define Patternist_SimpleContentConstructor_H + +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short Constructs simple content as specified for attributes in direct + * element constructors in XQuery. + * + * @note Sometimes you want XSLTSimpleContentConstructor. + * + * @see XSLTSimpleContentConstructor + * @see <a href="http://www.w3.org/TR/xquery/#id-attributes">XQuery 1.0: + * An XML Query Language, 3.7.1.1 Attributes</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class SimpleContentConstructor : public SingleContainer + { + public: + SimpleContentConstructor(const Expression::Ptr &operand); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + + virtual SequenceType::List expectedOperandTypes() const; + virtual SequenceType::Ptr staticType() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qsinglecontainer.cpp b/src/xmlpatterns/expr/qsinglecontainer.cpp new file mode 100644 index 0000000..cd280f3 --- /dev/null +++ b/src/xmlpatterns/expr/qsinglecontainer.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include <QList> + + +#include "qsinglecontainer_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +SingleContainer::SingleContainer(const Expression::Ptr &operand) : m_operand(operand) +{ + Q_ASSERT(operand); +} + +Expression::List SingleContainer::operands() const +{ + Expression::List list; + list.append(m_operand); + return list; +} + +void SingleContainer::setOperands(const Expression::List &ops) +{ + Q_ASSERT(ops.count() == 1); + m_operand = ops.first(); +} + +bool SingleContainer::compressOperands(const StaticContext::Ptr &context) +{ + rewrite(m_operand, m_operand->compress(context), context); + + return m_operand->isEvaluated(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qsinglecontainer_p.h b/src/xmlpatterns/expr/qsinglecontainer_p.h new file mode 100644 index 0000000..a55e891 --- /dev/null +++ b/src/xmlpatterns/expr/qsinglecontainer_p.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** 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_SingleContainer_H +#define Patternist_SingleContainer_H + +#include "qexpression_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Base class for expressions that has exactly one operand. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class SingleContainer : public Expression + { + public: + virtual Expression::List operands() const; + + virtual void setOperands(const Expression::List &operands); + virtual bool compressOperands(const StaticContext::Ptr &); + + protected: + SingleContainer(const Expression::Ptr &operand); + + Expression::Ptr m_operand; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qsourcelocationreflection.cpp b/src/xmlpatterns/expr/qsourcelocationreflection.cpp new file mode 100644 index 0000000..d24b030 --- /dev/null +++ b/src/xmlpatterns/expr/qsourcelocationreflection.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qsourcelocation.h" + +#include "qsourcelocationreflection_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +QSourceLocation SourceLocationReflection::sourceLocation() const +{ + return QSourceLocation(); +} + +const SourceLocationReflection *DelegatingSourceLocationReflection::actualReflection() const +{ + return m_r->actualReflection(); +} + +QString DelegatingSourceLocationReflection::description() const +{ + return m_r->description(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qsourcelocationreflection_p.h b/src/xmlpatterns/expr/qsourcelocationreflection_p.h new file mode 100644 index 0000000..d85c10c --- /dev/null +++ b/src/xmlpatterns/expr/qsourcelocationreflection_p.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** 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_SourceLocationReflection_H +#define Patternist_SourceLocationReflection_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QString; + +namespace QPatternist +{ + /** + * @short Base class for all instances that represents something + * at a certain location. + * + * SourceLocationReflection does not provide the source location itself, + * the address to an instance is the mark for it, that in turn can be used + * for looking up the source location where that mapping is provided. + * + * However, this SourceLocationReflection is not itself the mark. The real + * mark is retrieved by calling actualReflection(). This mechanism + * allows a SourceLocationReflection sub-class to delegate, or be an alias, + * for another source location mark. + * + * If sourceLocation() returns a non-null object, it will be used instead + * of looking up via actualReflection(). + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class Q_AUTOTEST_EXPORT SourceLocationReflection + { + public: + inline SourceLocationReflection() + { + } + + virtual ~SourceLocationReflection() + { + } + + virtual const SourceLocationReflection *actualReflection() const = 0; + + /** + * A description of what represents the source code location, for + * human consumption. Must be translated, as appropriate. + */ + virtual QString description() const + { + return QString(); + } + + virtual QSourceLocation sourceLocation() const; + + private: + Q_DISABLE_COPY(SourceLocationReflection) + }; + + class DelegatingSourceLocationReflection : public SourceLocationReflection + { + public: + inline DelegatingSourceLocationReflection(const SourceLocationReflection *const r) : m_r(r) + { + Q_ASSERT(r); + } + + virtual const SourceLocationReflection *actualReflection() const; + virtual QString description() const; + + private: + const SourceLocationReflection *const m_r; + }; + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qstaticbaseuristore.cpp b/src/xmlpatterns/expr/qstaticbaseuristore.cpp new file mode 100644 index 0000000..41b2d02 --- /dev/null +++ b/src/xmlpatterns/expr/qstaticbaseuristore.cpp @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qstaticbaseuricontext_p.h" + +#include "qstaticbaseuristore_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +StaticBaseURIStore::StaticBaseURIStore(const QUrl &baseURI, + const Expression::Ptr &operand) : SingleContainer(operand) + , m_baseURI(baseURI) +{ +} + +Expression::Ptr StaticBaseURIStore::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + const StaticContext::Ptr newContext(new StaticBaseURIContext(context->baseURI().resolved(m_baseURI), + context)); + return m_operand->typeCheck(newContext, reqType); +} + +SequenceType::Ptr StaticBaseURIStore::staticType() const +{ + return m_operand->staticType(); +} + +SequenceType::List StaticBaseURIStore::expectedOperandTypes() const +{ + SequenceType::List ops; + ops.append(CommonSequenceTypes::ZeroOrMoreItems); + return ops; +} + +ExpressionVisitorResult::Ptr StaticBaseURIStore::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qstaticbaseuristore_p.h b/src/xmlpatterns/expr/qstaticbaseuristore_p.h new file mode 100644 index 0000000..1347eab --- /dev/null +++ b/src/xmlpatterns/expr/qstaticbaseuristore_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** 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_StaticBaseURIStore_H +#define Patternist_StaticBaseURIStore_H + +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A compile time only AST node that changes the static base URI, + * used when @c xml:base attributes appears. + * + * @see StaticBaseURIContext + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + * @since 4.5 + */ + class StaticBaseURIStore : public SingleContainer + { + public: + /** + * @p baseURI must be valid, not empty, and either relative or + * absolute. + */ + StaticBaseURIStore(const QUrl &baseURI, + const Expression::Ptr &operand); + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + virtual SequenceType::Ptr staticType() const; + virtual SequenceType::List expectedOperandTypes() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + private: + const QUrl m_baseURI; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qstaticcompatibilitystore.cpp b/src/xmlpatterns/expr/qstaticcompatibilitystore.cpp new file mode 100644 index 0000000..1131955 --- /dev/null +++ b/src/xmlpatterns/expr/qstaticcompatibilitystore.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qstaticcompatibilitycontext_p.h" + +#include "qstaticcompatibilitystore_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +StaticCompatibilityStore::StaticCompatibilityStore(const Expression::Ptr &operand) : SingleContainer(operand) +{ +} + +Expression::Ptr StaticCompatibilityStore::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + const StaticContext::Ptr newContext(new StaticCompatibilityContext(context)); + return m_operand->typeCheck(newContext, reqType); +} + +SequenceType::Ptr StaticCompatibilityStore::staticType() const +{ + return m_operand->staticType(); +} + +SequenceType::List StaticCompatibilityStore::expectedOperandTypes() const +{ + SequenceType::List ops; + ops.append(CommonSequenceTypes::ZeroOrMoreItems); + return ops; +} + +ExpressionVisitorResult::Ptr StaticCompatibilityStore::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qstaticcompatibilitystore_p.h b/src/xmlpatterns/expr/qstaticcompatibilitystore_p.h new file mode 100644 index 0000000..981a177 --- /dev/null +++ b/src/xmlpatterns/expr/qstaticcompatibilitystore_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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_StaticCompatibilityStore_H +#define Patternist_StaticCompatibilityStore_H + +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A compile time only AST node that changes the backwareds compatibility mode. + * Used for XSL-T 2.0's backwards compatibility mode. + * + * @see StaticCompatibilityContext + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + * @since 4.5 + */ + class StaticCompatibilityStore : public SingleContainer + { + public: + /** + * @p baseURI must be valid, not empty, and either relative or + * absolute. + */ + StaticCompatibilityStore(const Expression::Ptr &operand); + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + virtual SequenceType::Ptr staticType() const; + virtual SequenceType::List expectedOperandTypes() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qtemplate.cpp b/src/xmlpatterns/expr/qtemplate.cpp new file mode 100644 index 0000000..79afab6 --- /dev/null +++ b/src/xmlpatterns/expr/qtemplate.cpp @@ -0,0 +1,232 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qdynamiccontextstore_p.h" +#include "qpatternistlocale_p.h" + +#include "qtemplate_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +const SourceLocationReflection* Template::actualReflection() const +{ + return this; +} + +DynamicContext::TemplateParameterHash Template::parametersAsHash() const +{ + DynamicContext::TemplateParameterHash retval; + const int len = templateParameters.count(); + + for(int i = 0; i < len; ++i) + { + const VariableDeclaration::Ptr &at = templateParameters.at(i); + retval.insert(at->name, at->expression()); + } + + return retval; +} + +void Template::raiseXTSE0680(const ReportContext::Ptr &context, + const QXmlName &name, + const SourceLocationReflection *const reflection) +{ + context->error(QtXmlPatterns::tr("The parameter %1 is passed, but no corresponding %2 exists.") + .arg(formatKeyword(context->namePool(), name), + formatKeyword(QLatin1String("xsl:param"))), + ReportContext::XTSE0680, + reflection); +} + +DynamicContext::Ptr Template::createContext(const TemplateInvoker *const invoker, + const DynamicContext::Ptr &context, + const bool isCallTemplate) const +{ + Q_ASSERT(invoker); + Q_ASSERT(context); + + /* We have: + * - xsl:params in the target template (if any) which may provide + * default values. + * - xsl:with-params in the caller (if any) which provides values. + * + * We need to, for each parameter: + * - If the called template provides no default value and the caller + * has no value, it's an error + * - If the called template has a default value and the caller provides + * none, it should be used + * - In any case the caller provides a value, it needs to be used. + * + * Problems to look out for: + * + * - Each xsl:param is in scope for the subsequent xsl:params. Hence, + * the evaluation of one xsl:param can depend on another xsl:param, + * and so on + * - The focus for xsl:params is different from the focus for + * the xsl:with-params + * - The xsl:with-params are not in scope for the xsl:params. + */ + + WithParam::Hash withParams(invoker->withParams()); + + /** + * Parameters or not, we must in any case create a new stack frame + * for the template invocation since otherwise we will trash our existing + * variables. Hence it's as with calling user functions. + * + * This is especially reproducible with recursive functions. + */ + DynamicContext::Ptr newStack(context->createStack()); + + /* We have no parameters, and we have no further error checking to + * do in the case of not being xsl:apply-templates, so we need to do nothing. */ + if(templateParameters.isEmpty() && (!isCallTemplate || withParams.isEmpty())) + return newStack; + + const DynamicContext::TemplateParameterHash hashedParams(parametersAsHash()); + DynamicContext::TemplateParameterHash sewnTogether(hashedParams); + + const DynamicContext::TemplateParameterHash::iterator end(sewnTogether.end()); + + for(DynamicContext::TemplateParameterHash::iterator it(sewnTogether.begin()); + it != end; + ++it) + { + Expression::Ptr ¶m = it.value(); + + WithParam::Ptr &withParam = withParams[it.key()]; + + if(withParam) + param = Expression::Ptr(new DynamicContextStore(withParam->sourceExpression(), context)); + else if(!param) + { + /* Ops, no xsl:with-param and no default value to cover up for it. + */ + context->error(QtXmlPatterns::tr("The parameter %1 is required, but no corresponding %2 is supplied.") + .arg(formatKeyword(context->namePool(), it.key()), + formatKeyword(QLatin1String("xsl:with-param"))), + ReportContext::XTSE0690, + this); + } + } + + if(isCallTemplate) + { + /* Find xsl:with-param that has no corresponding xsl:param. */ + /* Optimization: candidate for threading? */ + + const WithParam::Hash::const_iterator end(withParams.constEnd()); + + for(WithParam::Hash::const_iterator it(withParams.constBegin()); it != end; ++it) + { + if(!hashedParams.contains(it.key())) + raiseXTSE0680(context, it.key(), this); + } + + } + + newStack->templateParameterStore() = sewnTogether; + return newStack; +} + +void Template::compileParameters(const StaticContext::Ptr &context) +{ + Q_ASSERT(context); + + const int len = templateParameters.count(); + + for(int i = 0; i < len; ++i) + { + const VariableDeclaration::Ptr &at = templateParameters.at(i); + + /* If our value is required, we don't have a default value. */ + if(at->expression()) + { + // TODO why do we pass in its own type here? + at->setExpression(at->expression()->typeCheck(context, at->expression()->staticType())); + + at->setExpression(at->expression()->compress(context)); + } + } +} + +Expression::Properties Template::properties() const +{ + return Expression::DisableElimination; /* We're having issues with recursion detection, so this path currently loops infintely. */ + + Expression::Properties collect(body->properties()); + + VariableDeclaration::List::const_iterator end(templateParameters.constEnd()); + + for(VariableDeclaration::List::const_iterator it(templateParameters.constBegin()); + it != end; + ++it) + { + if((*it)->expression()) + collect |= (*it)->expression()->properties(); + } + + // TODO simplify. + return collect & (Expression::RequiresFocus | Expression::IsEvaluated | Expression::DisableElimination); +} + +Expression::Properties Template::dependencies() const +{ + return Expression::DisableElimination; /* We're having issues with recursion detection, so this path currently loops infintely. */ + + Expression::Properties collect(body->dependencies()); + + VariableDeclaration::List::const_iterator end(templateParameters.constEnd()); + + for(VariableDeclaration::List::const_iterator it(templateParameters.constBegin()); + it != end; + ++it) + { + if((*it)->expression()) + collect |= (*it)->expression()->dependencies(); + } + + return collect & (Expression::RequiresFocus | Expression::IsEvaluated | Expression::DisableElimination); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qtemplate_p.h b/src/xmlpatterns/expr/qtemplate_p.h new file mode 100644 index 0000000..cf00850 --- /dev/null +++ b/src/xmlpatterns/expr/qtemplate_p.h @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** 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_Template_H +#define Patternist_Template_H + +#include <QSharedData> +#include <QVector> + +#include "qdynamiccontext_p.h" +#include "qexpression_p.h" +#include "qsourcelocationreflection_p.h" +#include "qtemplateinvoker_p.h" +#include "qvariabledeclaration_p.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Contains data related to a template. + * + * A Template is associated with a mode, by being housed + * inside a TemplateMode instance. + * + * Template has role very similar to UserFunction. + * + * @see TemplateMode + * @see TemplatePattern + * @see UserFunction + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + * @since 4.5 + */ + class Template : public QSharedData + , public SourceLocationReflection + + { + public: + typedef QExplicitlySharedDataPointer<Template> Ptr; + typedef QVector<Template::Ptr> Vector; + + inline Template(const ImportPrecedence ip, + const SequenceType::Ptr &reqType) : importPrecedence(ip) + , m_reqType(reqType) + { + } + + Expression::Ptr body; + + /** + * Returns @c this. + */ + virtual const SourceLocationReflection* actualReflection() const; + + const ImportPrecedence importPrecedence; + + VariableDeclaration::List templateParameters; + + /** + * If @p isCallTemplate, the caller is @c xsl:call-template, as opposed + * to for instance @c xsl:apply-templates. This affects error + * reporting. + */ + DynamicContext::Ptr createContext(const TemplateInvoker *const invoker, + const DynamicContext::Ptr &context, + const bool isCallTemplate) const; + + /** + * Since we have our template parameters in templateParameters, we need + * this separate step to do the regular phases: + * Expression::typeCheck(), and Expression::compress(). + */ + void compileParameters(const StaticContext::Ptr &context); + + /** + * A value which takes into account the body and its template + * parameters. + */ + Expression::Properties properties() const; + + Expression::Properties dependencies() const; + + static void raiseXTSE0680(const ReportContext::Ptr &context, + const QXmlName &name, + const SourceLocationReflection *const reflection); + + private: + DynamicContext::TemplateParameterHash parametersAsHash() const; + const SequenceType::Ptr m_reqType; + }; +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qtemplateinvoker.cpp b/src/xmlpatterns/expr/qtemplateinvoker.cpp new file mode 100644 index 0000000..7de8e01 --- /dev/null +++ b/src/xmlpatterns/expr/qtemplateinvoker.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qtemplateinvoker_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +TemplateInvoker::TemplateInvoker(const WithParam::Hash &withParams, + const QXmlName &name) : CallSite(name) + , m_withParams(withParams) +{ + const WithParam::Hash::const_iterator end(m_withParams.constEnd()); + + for(WithParam::Hash::const_iterator it(m_withParams.constBegin()); it != end; ++it) + { + /* In the case of for instance: + * <xsl:with-param name="empty_seq" as="item()"/> + * + * we have no default expression. */ + Q_ASSERT(it.value()->sourceExpression()); + m_operands.append(it.value()->sourceExpression()); + } +} + +Expression::Ptr TemplateInvoker::compress(const StaticContext::Ptr &context) +{ + /* CallSite::compress() may have changed our children, so update + * our m_withParams. */ + const Expression::Ptr me(CallSite::compress(context)); + const WithParam::Hash::const_iterator end(m_withParams.constEnd()); + int exprIndex = -1; + + for(WithParam::Hash::const_iterator it(m_withParams.constBegin()); it != end; ++it) + { + if(it.value()->sourceExpression()) + { + ++exprIndex; + it.value()->setSourceExpression(m_operands.at(exprIndex)); + } + } + + return me; +} + +SequenceType::List TemplateInvoker::expectedOperandTypes() const +{ + SequenceType::List result; + + /* We don't return the type of the m_template->templateParameters(), we + * return the type of the @c xsl:with-param first. @em After that, we + * manually apply the parameter types in typeCheck(). */ + const WithParam::Hash::const_iterator end(m_withParams.constEnd()); + + for(WithParam::Hash::const_iterator it(m_withParams.constBegin()); it != end; ++it) + { + /* We're not guaranteed to have a with-param, we may be using the + * default value of the xsl:param. Tunnel parameters may also play + * in. */ + result.append(it.value()->type()); + } + + return result; +} + +QT_END_NAMESPACE + diff --git a/src/xmlpatterns/expr/qtemplateinvoker_p.h b/src/xmlpatterns/expr/qtemplateinvoker_p.h new file mode 100644 index 0000000..caf0253 --- /dev/null +++ b/src/xmlpatterns/expr/qtemplateinvoker_p.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** 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_TemplateInvoker_H +#define Patternist_TemplateInvoker_H + +#include "qcallsite_p.h" +#include "qwithparam_p.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Base class for classes that invokes @em templates, such as + * CallTemplate and ApplyTemplate. + * + * TemplateInvoker has the member m_withParams, which is the @c + * xsl:with-param instructions of the caller. The definite source for the + * expressions is m_withParams, not Expression::operands(). However, the + * order of operands() is defined, while m_withParams is not since it's a + * hash. Therefore operands() is definite on order. + * + * TemplateInvoker is intended to be sub-classed. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + * @since 4.5 + */ + class TemplateInvoker : public CallSite + { + public: + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + + inline const WithParam::Hash &withParams() const; + WithParam::Hash m_withParams; + + /** + * This is a bit complicated by that we have two required types, one + * specified by @c xsl:param in the template declaration, and one on @c + * xsl:with-param. + * + * @see UserFunctionCallsite::expectedOperandTypes() + * @see <a href="http://www.w3.org/TR/xslt20/#with-param">XSL + * Transformations (XSLT) Version 2.0, 10.1.1 Passing Parameters to Templates</a> + */ + virtual SequenceType::List expectedOperandTypes() const; + protected: + /** + * @p withParams may be empty. + */ + TemplateInvoker(const WithParam::Hash &withParams, + const QXmlName &name = QXmlName()); + + private: + Q_DISABLE_COPY(TemplateInvoker) + }; + + const WithParam::Hash &TemplateInvoker::withParams() const + { + return m_withParams; + } + +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif + diff --git a/src/xmlpatterns/expr/qtemplatemode.cpp b/src/xmlpatterns/expr/qtemplatemode.cpp new file mode 100644 index 0000000..976cefd --- /dev/null +++ b/src/xmlpatterns/expr/qtemplatemode.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qtemplatemode_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +bool TemplateMode::lessThanByPriority(const TemplatePattern::Ptr &t1, + const TemplatePattern::Ptr &t2) +{ + return t1->priority() > t2->priority(); +} + +void TemplateMode::finalize() +{ + qSort(templatePatterns.begin(), templatePatterns.end(), lessThanByPriority); + + /* Now we have a list of patterns sorted by priority. */ +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qtemplatemode_p.h b/src/xmlpatterns/expr/qtemplatemode_p.h new file mode 100644 index 0000000..044b405 --- /dev/null +++ b/src/xmlpatterns/expr/qtemplatemode_p.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** 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_TemplateMode_H +#define Patternist_TemplateMode_H + +#include <QtCore/QSharedData> +#include <QXmlName> + +#include "qtemplatepattern_p.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Houses the data specific to the templates for a certain mode. + * + * @see Template + * @see TemplatePattern + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + * @since 4.5 + */ + class Q_AUTOTEST_EXPORT TemplateMode : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer<TemplateMode> Ptr; + + inline TemplateMode(const QXmlName &modeName) : m_modeName(modeName) + { + } + + TemplatePattern::Vector templatePatterns; + + /** + * Adds the templates in @p mode to this TemplateMode. + * + * The existing name remains. + */ + inline void addMode(const TemplateMode::Ptr &mode); + + inline const QXmlName &name() const; + + /** + * Orders its templates by priority such that the first lookup always + * returns the template with highest priority, and removes templates + * shadowed by import precedence. + */ + void finalize(); + + private: + const QXmlName m_modeName; + Q_DISABLE_COPY(TemplateMode) + + /** + * Operator for qSort(). + */ + static inline bool lessThanByPriority(const TemplatePattern::Ptr &t1, + const TemplatePattern::Ptr &t2); + }; + + const QXmlName &TemplateMode::name() const + { + return m_modeName; + } + + void TemplateMode::addMode(const TemplateMode::Ptr &mode) + { + templatePatterns += mode->templatePatterns; + } + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qtemplateparameterreference.cpp b/src/xmlpatterns/expr/qtemplateparameterreference.cpp new file mode 100644 index 0000000..550e39f --- /dev/null +++ b/src/xmlpatterns/expr/qtemplateparameterreference.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" + +#include "qtemplateparameterreference_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +TemplateParameterReference::TemplateParameterReference(const VariableDeclaration::Ptr &varDecl) : m_varDecl(varDecl) +{ +} + +bool TemplateParameterReference::evaluateEBV(const DynamicContext::Ptr &context) const +{ + return context->templateParameterStore()[m_varDecl->name]->evaluateEBV(context); +} + +Item TemplateParameterReference::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + return context->templateParameterStore()[m_varDecl->name]->evaluateSingleton(context); +} + +Item::Iterator::Ptr TemplateParameterReference::evaluateSequence(const DynamicContext::Ptr &context) const +{ + Q_ASSERT(!m_varDecl->name.isNull()); + Q_ASSERT(context->templateParameterStore()[m_varDecl->name]); + return context->templateParameterStore()[m_varDecl->name]->evaluateSequence(context); +} + +ExpressionVisitorResult::Ptr TemplateParameterReference::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::Properties TemplateParameterReference::properties() const +{ + return DisableElimination; +} + +SequenceType::Ptr TemplateParameterReference::staticType() const +{ + /* We can't use m_varDecl->expression()'s static type here, because + * it's the default argument. */ + if(!m_varDecl->sequenceType) + return CommonSequenceTypes::ZeroOrMoreItems; + else + return m_varDecl->sequenceType; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qtemplateparameterreference_p.h b/src/xmlpatterns/expr/qtemplateparameterreference_p.h new file mode 100644 index 0000000..7eb9562 --- /dev/null +++ b/src/xmlpatterns/expr/qtemplateparameterreference_p.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** 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_TemplateParameterReference_H +#define Patternist_TemplateParameterReference_H + +#include "qvariabledeclaration_p.h" +#include "qemptycontainer_p.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A reference to a template parameter declared with @c xsl:param. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + * @since 4.5 + */ + class TemplateParameterReference : public EmptyContainer + { + public: + TemplateParameterReference(const VariableDeclaration::Ptr &varDecl); + + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + + virtual SequenceType::Ptr staticType() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual Properties properties() const; + + inline const Expression::Ptr &sourceExpression() const; + inline const VariableDeclaration::Ptr &variableDeclaration() const; + + private: + const VariableDeclaration::Ptr m_varDecl; + }; + + inline const Expression::Ptr &TemplateParameterReference::sourceExpression() const + { + return m_varDecl->expression(); + } + + inline const VariableDeclaration::Ptr &TemplateParameterReference::variableDeclaration() const + { + return m_varDecl; + } + +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qtemplatepattern_p.h b/src/xmlpatterns/expr/qtemplatepattern_p.h new file mode 100644 index 0000000..1ac1c56 --- /dev/null +++ b/src/xmlpatterns/expr/qtemplatepattern_p.h @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** 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_TemplatePattern_H +#define Patternist_TemplatePattern_H + +#include "qtemplate_p.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Houses the data necessary for a template pattern. + * + * A template pattern is the match pattern, but have had each operand to @c + * | separated out into a separate TemplatePattern. For instance, the + * pattern <tt>a | b | c</tt>, becomes three separate TemplatePattern + * instances. + * + * @see TemplateMode + * @see Template + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + * @since 4.5 + */ + class TemplatePattern : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer<TemplatePattern> Ptr; + typedef QVector<Ptr> Vector; + typedef int ID; + + inline TemplatePattern(const Expression::Ptr &matchPattern, + const PatternPriority pri, + const ID id, + const Template::Ptr templ); + + inline PatternPriority priority() const; + inline const Expression::Ptr &matchPattern() const; + inline void setMatchPattern(const Expression::Ptr &pattern); + inline const Template::Ptr &templateTarget() const; + inline ID id() const; + + /** + * This ID is used to ensure that, as 6.4 Conflict Resolution for + * Template Rules reads: + * + * "If the pattern contains multiple alternatives separated by |, then + * the template rule is treated equivalently to a set of template + * rules, one for each alternative. However, it is not an error if a + * node matches more than one of the alternatives." + * + * For patterns separated by @c |, we have one Template instance for + * each alternative, but they all have the same ID, hence if several + * alternatives match, we don't flag it as an error if they have the + * same ID. + */ + private: + Expression::Ptr m_matchPattern; + PatternPriority m_priority; + ID m_id; + Template::Ptr m_templateTarget; + Q_DISABLE_COPY(TemplatePattern) + }; + + TemplatePattern::TemplatePattern(const Expression::Ptr &matchPattern, + const PatternPriority pri, + const ID id, + const Template::Ptr templ) : m_matchPattern(matchPattern) + , m_priority(pri) + , m_id(id) + , m_templateTarget(templ) + + { + Q_ASSERT(m_matchPattern); + Q_ASSERT(m_templateTarget); + } + + const Expression::Ptr &TemplatePattern::matchPattern() const + { + return m_matchPattern; + } + + void TemplatePattern::setMatchPattern(const Expression::Ptr &pattern) + { + m_matchPattern = pattern; + } + + PatternPriority TemplatePattern::priority() const + { + return m_priority; + } + + TemplatePattern::ID TemplatePattern::id() const + { + return m_id; + } + + const Template::Ptr &TemplatePattern::templateTarget() const + { + return m_templateTarget; + } + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif + diff --git a/src/xmlpatterns/expr/qtextnodeconstructor.cpp b/src/xmlpatterns/expr/qtextnodeconstructor.cpp new file mode 100644 index 0000000..bb74079 --- /dev/null +++ b/src/xmlpatterns/expr/qtextnodeconstructor.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include <QUrl> + +#include "qcommonsequencetypes_p.h" +#include "qnodebuilder_p.h" + +#include "qtextnodeconstructor_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +TextNodeConstructor::TextNodeConstructor(const Expression::Ptr &op) : SingleContainer(op) +{ +} + +Item TextNodeConstructor::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + const Item chars(m_operand->evaluateSingleton(context)); + + if(!chars) + return Item(); + + const NodeBuilder::Ptr nodeBuilder(context->nodeBuilder(QUrl())); + const QString &v = chars.stringValue(); + nodeBuilder->characters(QStringRef(&v)); + + const QAbstractXmlNodeModel::Ptr nm(nodeBuilder->builtDocument()); + context->addNodeModel(nm); + + return nm->root(QXmlNodeModelIndex()); +} + +void TextNodeConstructor::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + const Item item(m_operand->evaluateSingleton(context)); + + QAbstractXmlReceiver *const receiver = context->outputReceiver(); + + if(item) + { + const QString &v = item.stringValue(); + receiver->characters(QStringRef(&v)); + } + else + receiver->characters(QStringRef()); +} + +SequenceType::Ptr TextNodeConstructor::staticType() const +{ + if(m_operand->staticType()->cardinality().allowsEmpty()) + return CommonSequenceTypes::ZeroOrOneTextNode; + else + return CommonSequenceTypes::ExactlyOneTextNode; +} + +SequenceType::List TextNodeConstructor::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrOneString); + return result; +} + +Expression::Properties TextNodeConstructor::properties() const +{ + return DisableElimination | IsNodeConstructor; +} + +ExpressionVisitorResult::Ptr +TextNodeConstructor::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qtextnodeconstructor_p.h b/src/xmlpatterns/expr/qtextnodeconstructor_p.h new file mode 100644 index 0000000..ac20cc7 --- /dev/null +++ b/src/xmlpatterns/expr/qtextnodeconstructor_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** 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_TextNodeConstructor_H +#define Patternist_TextNodeConstructor_H + +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Constructs a text node. This covers both computed and directly constructed + * text nodes. + * + * @see <a href="http://www.w3.org/TR/xquery/#id-constructors">XQuery + * 1.0: An XML Query Language, 3.7 Constructors</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class TextNodeConstructor : public SingleContainer + { + public: + TextNodeConstructor(const Expression::Ptr &operand); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + virtual SequenceType::Ptr staticType() const; + + /** + * The first operand must be exactly one @c xs:string. + */ + virtual SequenceType::List expectedOperandTypes() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + virtual Properties properties() const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qtreatas.cpp b/src/xmlpatterns/expr/qtreatas.cpp new file mode 100644 index 0000000..8ccfb12 --- /dev/null +++ b/src/xmlpatterns/expr/qtreatas.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qtypechecker_p.h" + +#include "qtreatas_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +TreatAs::TreatAs(const Expression::Ptr &operand, + const SequenceType::Ptr &reqType) : SingleContainer(operand), + m_reqType(reqType) +{ + Q_ASSERT(reqType); +} + +Expression::Ptr TreatAs::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + Q_ASSERT(context); + Q_ASSERT(reqType); + + /* Apply function conversion with the special error code XPDY0050. After that, we + * let the regular typeCheck() function be invoked on the operand before we rewrite + * to it. Hence is applyFunctionConversion() called twice, which doesn't break anything, + * but indeed is redundant. */ + const Expression::Ptr treated(TypeChecker::applyFunctionConversion(m_operand, + m_reqType, + context, + ReportContext::XPDY0050)); + return treated->typeCheck(context, reqType); +} + +ExpressionVisitorResult::Ptr TreatAs::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +SequenceType::Ptr TreatAs::staticType() const +{ + return m_reqType; +} + +SequenceType::List TreatAs::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qtreatas_p.h b/src/xmlpatterns/expr/qtreatas_p.h new file mode 100644 index 0000000..cf8599c --- /dev/null +++ b/src/xmlpatterns/expr/qtreatas_p.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** 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_TreatAs_H +#define Patternist_TreatAs_H + +#include "qsinglecontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Implements XPath 2.0's <tt>treat as</tt> expression. + * + * TreatAs is always a compile-time class only, and is always deallocated + * by re-writing to CardinalityVerifier or ItemVerifier or both, by calling + * TypeChecker::applyFunctionConversion(). + * + * + * One approach could be to skip instantiating TreatAs and simply let the + * return value of TypeChecker::applyFunctionConversion() be inserted into + * the AST, but that wouldn't handle type checking the context item + * properly, which depends on that the StaticContext have been set by the + * parent Expression. + * + * @see <a href="http://www.w3.org/TR/xpath20/#id-treat">XML Path Language + * (XPath) 2.0, 3.10.5 Treat</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class TreatAs : public SingleContainer + { + public: + /** + * Creats a TreatAs where it is checked that the expression @p operand conforms + * to the type @p reqType. + */ + TreatAs(const Expression::Ptr &operand, + const SequenceType::Ptr &reqType); + + /** + * This function rewrites always. First the type that this TreatAs expression tests for + * is verified. Then, the type the <tt>treat as</tt> expression itself must match, @p reqType, + * is verified. + */ + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + + /** + * @returns always the SequenceType passed in the constructor to this class. That is, the + * SequenceType that the operand must conform to. + */ + virtual SequenceType::Ptr staticType() const; + + /** + * @returns a list containing one CommonSequenceTypes::ZeroOrMoreItems + */ + virtual SequenceType::List expectedOperandTypes() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + private: + const SequenceType::Ptr m_reqType; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qtriplecontainer.cpp b/src/xmlpatterns/expr/qtriplecontainer.cpp new file mode 100644 index 0000000..8ffff85 --- /dev/null +++ b/src/xmlpatterns/expr/qtriplecontainer.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include <QList> + +#include "qtriplecontainer_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +TripleContainer::TripleContainer(const Expression::Ptr &operand1, + const Expression::Ptr &operand2, + const Expression::Ptr &operand3) : m_operand1(operand1), + m_operand2(operand2), + m_operand3(operand3) +{ + Q_ASSERT(operand1); + Q_ASSERT(operand2); + Q_ASSERT(operand3); +} + +Expression::List TripleContainer::operands() const +{ + Expression::List result; + result.append(m_operand1); + result.append(m_operand2); + result.append(m_operand3); + return result; +} + +void TripleContainer::setOperands(const Expression::List &ops) +{ + Q_ASSERT(ops.count() == 3); + m_operand1 = ops.first(); + m_operand2 = ops.at(1); + m_operand3 = ops.at(2); +} + +bool TripleContainer::compressOperands(const StaticContext::Ptr &context) +{ + rewrite(m_operand1, m_operand1->compress(context), context); + rewrite(m_operand2, m_operand2->compress(context), context); + rewrite(m_operand3, m_operand3->compress(context), context); + + return m_operand1->isEvaluated() && m_operand2->isEvaluated() && m_operand3->isEvaluated(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qtriplecontainer_p.h b/src/xmlpatterns/expr/qtriplecontainer_p.h new file mode 100644 index 0000000..e9cd249 --- /dev/null +++ b/src/xmlpatterns/expr/qtriplecontainer_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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_TripleContainer_H +#define Patternist_TripleContainer_H + +#include "qexpression_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Base class for expressions that has exactly three operands. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class TripleContainer : public Expression + { + public: + virtual Expression::List operands() const; + virtual void setOperands(const Expression::List &operands); + + virtual bool compressOperands(const StaticContext::Ptr &); + + protected: + TripleContainer(const Expression::Ptr &operand1, + const Expression::Ptr &operand2, + const Expression::Ptr &operand3); + + Expression::Ptr m_operand1; + Expression::Ptr m_operand2; + Expression::Ptr m_operand3; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qtruthpredicate.cpp b/src/xmlpatterns/expr/qtruthpredicate.cpp new file mode 100644 index 0000000..0c967d2 --- /dev/null +++ b/src/xmlpatterns/expr/qtruthpredicate.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qcommonvalues_p.h" +#include "qgenericsequencetype_p.h" + +#include "qtruthpredicate_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +TruthPredicate::TruthPredicate(const Expression::Ptr &sourceExpression, + const Expression::Ptr &predicate) : GenericPredicate(sourceExpression, + predicate) +{ +} + +SequenceType::List TruthPredicate::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + result.append(CommonSequenceTypes::EBV); + return result; +} + +ExpressionVisitorResult::Ptr TruthPredicate::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qtruthpredicate_p.h b/src/xmlpatterns/expr/qtruthpredicate_p.h new file mode 100644 index 0000000..1a395bd --- /dev/null +++ b/src/xmlpatterns/expr/qtruthpredicate_p.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** 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_TruthPredicate_H +#define Patternist_TruthPredicate_H + +#include "qgenericpredicate_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A predicate which is optimized for filter expressions that + * are of type @c xs:boolean. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class TruthPredicate : public GenericPredicate + { + public: + /** + * Creates a TruthPredicate which filters the items from the @p sourceExpression + * through @p predicate. + * + * This constructor is protected. The proper way to create predicates is via the static + * create() function. + */ + TruthPredicate(const Expression::Ptr &sourceExpression, + const Expression::Ptr &predicate); + + inline Item mapToItem(const Item &item, const DynamicContext::Ptr &context) const + { + Q_ASSERT_X(false, Q_FUNC_INFO, "This is practically dead code because it never gets called in GenericPredicate, " + "which binds to its own mapToItem for completely legitime reasons."); + if(m_operand2->evaluateEBV(context)) + return item; + else + return Item(); + } + + inline Item::Iterator::Ptr map(const Item &item, + const DynamicContext::Ptr &context) const + { + Q_ASSERT_X(false, Q_FUNC_INFO, "I don't expect this function to be called, for the same reasons as above."); + if(m_operand2->evaluateEBV(context)) + return makeSingletonIterator(item); + else + return CommonValues::emptyIterator; + } + + virtual SequenceType::List expectedOperandTypes() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qunaryexpression.cpp b/src/xmlpatterns/expr/qunaryexpression.cpp new file mode 100644 index 0000000..88419ce --- /dev/null +++ b/src/xmlpatterns/expr/qunaryexpression.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qarithmeticexpression_p.h" +#include "qcommonvalues_p.h" +#include "qliteral_p.h" +#include "qschemanumeric_p.h" + +#include "qunaryexpression_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +UnaryExpression::UnaryExpression(const AtomicMathematician::Operator op, + const Expression::Ptr &operand, + const StaticContext::Ptr &context) : ArithmeticExpression(wrapLiteral(CommonValues::IntegerZero, context, operand.data()), + op, + operand) +{ + Q_ASSERT(op == AtomicMathematician::Substract || + op == AtomicMathematician::Add); + Q_ASSERT(context); +} + +Item UnaryExpression::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + if(operatorID() == AtomicMathematician::Substract) + { + const Item item(m_operand2->evaluateSingleton(context)); + + if(item) + return item.as<Numeric>()->toNegated(); + else + return Item(); + } + else + return m_operand2->evaluateSingleton(context); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qunaryexpression_p.h b/src/xmlpatterns/expr/qunaryexpression_p.h new file mode 100644 index 0000000..abc17cb --- /dev/null +++ b/src/xmlpatterns/expr/qunaryexpression_p.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** 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_UnaryExpression_H +#define Patternist_UnaryExpression_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#include "qarithmeticexpression_p.h" + +namespace QPatternist +{ + /** + * @short Implements XPath 2.0 unary expression, <tt>(-|+)ValueExpr</tt>. + * + * UnaryExpression is implemented by rewriting the expression <tt>operator [expr]</tt> + * to the ArithmeticExpression <tt>0 operator [expr]</tt>. For example, the expression + * <tt>+3</tt> becomes <tt>0 + 3</tt>, and <tt>-nodetest</tt> becomes <tt>0 - nodetest</tt>. + * + * On top of that expression ArithmeticExpression does the usual type + * checking conversion. The only thing this class do, is to overide + * evaluateSingleton() and calls Numeric::toNegated(). The reason this + * UnaryExpression is needed at all and that <tt>0 - [expr]</tt> is + * insufficent is that <tt>0 - xs:double(0)</tt> needs to return -0, + * instead of 0. I know no other difference. + * + * In most cases the constant propagation optimization rewrites UnaryExpression into + * a value, an instance of a sub-class of the Numeric class, wrapped with + * Literal. + * + * Beyond the mathematical implication the unary expression have, it also + * have the significant effect that it may invoke type promotion or that an expression + * may contain a type error. For example, the expression "+'a string'" contains a type error, since + * no unary operator is defined for @c xs:string. This is the reason why the '+' unary + * operator isn't ignored. + * + * @see <a href="http://www.w3.org/TR/xpath20/#id-arithmetic">XML Path Language + * (XPath) 2.0, 3.4 Arithmetic Expressions</a> + * @see <a href="http://www.w3.org/TR/xpath-functions/#func-numeric-unary-plus">XQuery 1.0 and XPath + * 2.0 Functions and Operators, 6.2.7 op:numeric-unary-plus</a> + * @see <a href="http://www.w3.org/TR/xpath-functions/#func-numeric-unary-minus">XQuery 1.0 and XPath + * 2.0 Functions and Operators, 6.2.8 op:numeric-unary-minus</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class UnaryExpression : public ArithmeticExpression + { + public: + UnaryExpression(const AtomicMathematician::Operator op, + const Expression::Ptr &operand, + const StaticContext::Ptr &context); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + + private: + Q_DISABLE_COPY(UnaryExpression) + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qunlimitedcontainer.cpp b/src/xmlpatterns/expr/qunlimitedcontainer.cpp new file mode 100644 index 0000000..d1f4638 --- /dev/null +++ b/src/xmlpatterns/expr/qunlimitedcontainer.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qunlimitedcontainer_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +UnlimitedContainer::UnlimitedContainer(const Expression::List &ops) : m_operands(ops) +{ +} + +void UnlimitedContainer::setOperands(const Expression::List &list) +{ + m_operands = list; +} + +Expression::List UnlimitedContainer::operands() const +{ + return m_operands; +} + +bool UnlimitedContainer::compressOperands(const StaticContext::Ptr &context) +{ + const Expression::List::iterator end(m_operands.end()); + Expression::List::iterator it(m_operands.begin()); + int evaled = 0; + + for(; it != end; ++it) + { + Q_ASSERT((*it)); + rewrite((*it), (*it)->compress(context), context); + if((*it)->isEvaluated()) + ++evaled; + } + + return evaled == m_operands.count(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qunlimitedcontainer_p.h b/src/xmlpatterns/expr/qunlimitedcontainer_p.h new file mode 100644 index 0000000..1c032f0 --- /dev/null +++ b/src/xmlpatterns/expr/qunlimitedcontainer_p.h @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** 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_UnlimitedContainer_H +#define Patternist_UnlimitedContainer_H + +#include <QList> +#include "qexpression_p.h" +#include "qgenericsequencetype_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Base class for expressions that has any amount of operands. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class UnlimitedContainer : public Expression + { + public: + /** + * Creates an UnlimitedContainer containing the operands @p operands. @p operands + * may be empty. + */ + UnlimitedContainer(const Expression::List &operands = Expression::List()); + + virtual void setOperands(const Expression::List &list); + + virtual Expression::List operands() const; + + /** + * @note This function cannot be called before setOperands is called. + */ + virtual bool compressOperands(const StaticContext::Ptr &); + + /** + * Tells how operandsUnionType() should compute the cardinality of + * its children. + * + * This type is public because of a bug in the HP-UX aCC compiler. + */ + enum CardinalityComputation + { + ProductOfCardinality, + UnionOfCardinality + }; + + protected: + /** + * Computes and returns the union type of all the Expression instances + * in this Expression's operands. + * + * This implementation is placed inside because CardinalityComputation + * can't be referenced from the outside(in conforming compilers). + */ + template<CardinalityComputation suppliedCard> + inline + SequenceType::Ptr operandsUnionType() const + { + Q_ASSERT(suppliedCard == ProductOfCardinality || suppliedCard == UnionOfCardinality); + const Expression::List::const_iterator end(m_operands.constEnd()); + Expression::List::const_iterator it(m_operands.constBegin()); + + /* Load the first one, and jump over it in the loop. */ + SequenceType::Ptr t(m_operands.first()->staticType()); + ItemType::Ptr type(t->itemType()); + Cardinality card(t->cardinality()); + ++it; + + for(; it != end; ++it) + { + t = (*it)->staticType(); + type |= t->itemType(); + + /* Since this function is a template function, it doesn't + * hurt performance that this test is inside the loop. */ + if(suppliedCard == ProductOfCardinality) + card += t->cardinality(); + else + card |= t->cardinality(); + } + + return makeGenericSequenceType(type, card); + } + + Expression::List m_operands; + }; + + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qunresolvedvariablereference.cpp b/src/xmlpatterns/expr/qunresolvedvariablereference.cpp new file mode 100644 index 0000000..68c974e --- /dev/null +++ b/src/xmlpatterns/expr/qunresolvedvariablereference.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" + +#include "qunresolvedvariablereference_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +UnresolvedVariableReference::UnresolvedVariableReference(const QXmlName &name) : m_name(name) +{ + Q_ASSERT(!m_name.isNull()); +} + +Expression::Ptr UnresolvedVariableReference::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + /* We may be called before m_replacement is called, when we're part of a + * function body whose type checking is performed for. See + * UserFunctionCallsite::typeCheck(). */ + if(m_replacement) + return m_replacement->typeCheck(context, reqType); + else + return EmptyContainer::typeCheck(context, reqType); +} + +SequenceType::Ptr UnresolvedVariableReference::staticType() const +{ + /* We may be called by xmlpatternsview before the typeCheck() stage. */ + if(m_replacement) + return m_replacement->staticType(); + else + return CommonSequenceTypes::ZeroOrMoreItems; +} + +SequenceType::List UnresolvedVariableReference::expectedOperandTypes() const +{ + return SequenceType::List(); +} + +ExpressionVisitorResult::Ptr UnresolvedVariableReference::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID UnresolvedVariableReference::id() const +{ + return IDUnresolvedVariableReference; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qunresolvedvariablereference_p.h b/src/xmlpatterns/expr/qunresolvedvariablereference_p.h new file mode 100644 index 0000000..d32fb0a --- /dev/null +++ b/src/xmlpatterns/expr/qunresolvedvariablereference_p.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** 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_UnresolvedVariableReference_H +#define Patternist_UnresolvedVariableReference_H + +#include "qemptycontainer_p.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short Compile time only AST-node which is a marker for variable + * references whose declaration has not yet appeared in the source code. + * + * This can not appear in XQuery, but can in XSL-T. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + * @since 4.5 + */ + class Q_AUTOTEST_EXPORT UnresolvedVariableReference : public EmptyContainer + { + public: + UnresolvedVariableReference(const QXmlName &name); + + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + virtual SequenceType::List expectedOperandTypes() const; + virtual SequenceType::Ptr staticType() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual ID id() const; + + inline void bindTo(const Expression::Ptr &body); + + inline Expression::Ptr replacement() const; + + private: + const QXmlName m_name; + Expression::Ptr m_replacement; + }; + + void UnresolvedVariableReference::bindTo(const Expression::Ptr &body) + { + Q_ASSERT(body); + m_replacement = body; + } + + Expression::Ptr UnresolvedVariableReference::replacement() const + { + Q_ASSERT(m_replacement); + return m_replacement; + } + +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/quserfunction.cpp b/src/xmlpatterns/expr/quserfunction.cpp new file mode 100644 index 0000000..f440b61 --- /dev/null +++ b/src/xmlpatterns/expr/quserfunction.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + + +#include "quserfunction_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +UserFunction::UserFunction(const FunctionSignature::Ptr &sign, + const Expression::Ptr &b, + const VariableSlotID slotOffset, + const VariableDeclaration::List &varDecls) : m_signature(sign), + m_body(b), + m_slotOffset(slotOffset), + m_argumentDeclarations(varDecls) +{ + Q_ASSERT(m_signature); + Q_ASSERT(m_body); + Q_ASSERT(m_slotOffset > -2); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/quserfunction_p.h b/src/xmlpatterns/expr/quserfunction_p.h new file mode 100644 index 0000000..938a1d9 --- /dev/null +++ b/src/xmlpatterns/expr/quserfunction_p.h @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** 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_UserFunction_H +#define Patternist_UserFunction_H + +template<typename T> class QList; + +#include <QSharedData> + +#include "qexpression_p.h" +#include "qfunctionsignature_p.h" +#include "qvariabledeclaration_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A function created with XQuery's <tt>declare function</tt> declaration. + * + * @see UserFunctionCall + * @see ArgumentReference + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class UserFunction : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer<UserFunction> Ptr; + typedef QList<UserFunction::Ptr> List; + + /** + * If @p slotOffset is -1, it means this function has no arguments. + */ + UserFunction(const FunctionSignature::Ptr &signature, + const Expression::Ptr &body, + const VariableSlotID slotOffset, + const VariableDeclaration::List &varDecls); + + inline const Expression::Ptr &body() const; + inline void setBody(const Expression::Ptr &newBody); + inline FunctionSignature::Ptr signature() const; + inline VariableSlotID expressionSlotOffset() const; + inline VariableDeclaration::List argumentDeclarations() const; + + private: + const FunctionSignature::Ptr m_signature; + Expression::Ptr m_body; + const VariableSlotID m_slotOffset; + const VariableDeclaration::List m_argumentDeclarations; + }; + + inline const Expression::Ptr &UserFunction::body() const + { + return m_body; + } + + inline FunctionSignature::Ptr UserFunction::signature() const + { + return m_signature; + } + + inline VariableSlotID UserFunction::expressionSlotOffset() const + { + return m_slotOffset; + } + + inline VariableDeclaration::List UserFunction::argumentDeclarations() const + { + return m_argumentDeclarations; + } + + void UserFunction::setBody(const Expression::Ptr &newBody) + { + m_body = newBody; + } + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/quserfunctioncallsite.cpp b/src/xmlpatterns/expr/quserfunctioncallsite.cpp new file mode 100644 index 0000000..4e81484 --- /dev/null +++ b/src/xmlpatterns/expr/quserfunctioncallsite.cpp @@ -0,0 +1,245 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qcommonsequencetypes_p.h" +#include "qdynamiccontextstore_p.h" +#include "qevaluationcache_p.h" + +#include "quserfunctioncallsite_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +UserFunctionCallsite::UserFunctionCallsite(const QXmlName nameP, + const FunctionSignature::Arity ar) : CallSite(nameP) + , m_arity(ar) + , m_expressionSlotOffset(-2) + +{ +} + +Item::Iterator::Ptr UserFunctionCallsite::evaluateSequence(const DynamicContext::Ptr &context) const +{ + return m_body->evaluateSequence(bindVariables(context)); +} + +Item UserFunctionCallsite::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + return m_body->evaluateSingleton(bindVariables(context)); +} + +bool UserFunctionCallsite::evaluateEBV(const DynamicContext::Ptr &context) const +{ + return m_body->evaluateEBV(bindVariables(context)); +} + +void UserFunctionCallsite::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const +{ + m_body->evaluateToSequenceReceiver(bindVariables(context)); +} + +DynamicContext::Ptr UserFunctionCallsite::bindVariables(const DynamicContext::Ptr &context) const +{ + const DynamicContext::Ptr stackContext(context->createStack()); + Q_ASSERT(stackContext); + + const Expression::List::const_iterator end(m_operands.constEnd()); + Expression::List::const_iterator it(m_operands.constBegin()); + + VariableSlotID slot = m_expressionSlotOffset; + + for(; it != end; ++it) + { + stackContext->setExpressionVariable(slot, + Expression::Ptr(new DynamicContextStore(*it, context))); + ++slot; + } + + return stackContext; +} + +SequenceType::List UserFunctionCallsite::expectedOperandTypes() const +{ + SequenceType::List result; + + if(m_functionDeclaration) + { + const FunctionArgument::List args(m_functionDeclaration->signature()->arguments()); + const FunctionArgument::List::const_iterator end(args.constEnd()); + FunctionArgument::List::const_iterator it(args.constBegin()); + + for(; it != end; ++it) + result.append((*it)->type()); + } + else + result.append(CommonSequenceTypes::ZeroOrMoreItems); + + return result; +} + +Expression::Ptr UserFunctionCallsite::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + /* The parser calls TypeChecker::applyFunctionConversion() on user function + * bodies, possibly indirectly, before all function call sites have been + * resolved. Hence it's possible that we're called before before the usual + * typeCheck() pass, and hence before we have been resolved/checked and + * subsequently m_functionDeclaration set. Therefore, encounter for that below. + * + * UnresolvedVariableReference::typeCheck() has the same dilemma. + */ + + /* Ensure that the return value of the function is properly + * converted/does match from where it is called(which is here). */ + if(isRecursive() || !m_functionDeclaration) + return CallSite::typeCheck(context, reqType); + else + { + /* Update, such that we use a recent version of the body that has typeCheck() + * and compress() rewrites included. */ + m_body = m_functionDeclaration->body(); + + /* Note, we can't assign to m_functionDeclaration->body() because UserFunction can apply + * to several different callsites. Hence we need our own version. */ + m_body = m_body->typeCheck(context, reqType); + + /* We just act as a pipe for m_body, so we don't have to typecheck ourselves. However, + * the arguments must match the function declaration. */ + typeCheckOperands(context); + return Expression::Ptr(this); + } +} + +Expression::Ptr UserFunctionCallsite::compress(const StaticContext::Ptr &context) +{ + if(!isRecursive()) + rewrite(m_body, m_body->compress(context), context); + + return CallSite::compress(context); +} + +Expression::Properties UserFunctionCallsite::properties() const +{ + return DisableElimination; +} + +SequenceType::Ptr UserFunctionCallsite::staticType() const +{ + /* Our return type, is the static type of the function body. We could have also used + * m_functionDeclaration->signature()->returnType(), but it doesn't get updated + * when function conversion is applied. + * We can't use m_body's type if we're recursive, because m_body computes its type + * from its children, and we're at least one of the children. Hence, we would + * recurse infinitely if we did. + * + * m_body can be null here if we're called before setSource(). + */ + if(isRecursive() || !m_body) + return CommonSequenceTypes::ZeroOrMoreItems; // TODO use the declaration, it can have a type explicitly. + else + return m_body->staticType(); +} + +ExpressionVisitorResult::Ptr UserFunctionCallsite::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID UserFunctionCallsite::id() const +{ + return IDUserFunctionCallsite; +} + +bool UserFunctionCallsite::isSignatureValid(const FunctionSignature::Ptr &sign) const +{ + Q_ASSERT(sign); + + return sign->name() == name() + && + sign->isArityValid(m_arity); +} + +bool UserFunctionCallsite::configureRecursion(const CallTargetDescription::Ptr &sign) +{ + Q_ASSERT(sign); + + setIsRecursive(isSignatureValid(sign)); + return isRecursive(); +} + +void UserFunctionCallsite::setSource(const UserFunction::Ptr &userFunction, + const VariableSlotID cacheSlotOffset) +{ + m_functionDeclaration = userFunction; + m_body = userFunction->body(); + m_expressionSlotOffset = userFunction->expressionSlotOffset(); + + const int len = m_operands.size(); + + const VariableDeclaration::List varDecls(userFunction->argumentDeclarations()); + + for(int i = 0; i < len; ++i) + { + /* We don't want evaluation caches for range variables, it's not necessary since + * the item is already cached in DynamicContext::rangeVariable(). */ + if(m_operands.at(i)->is(IDRangeVariableReference)) + continue; + + /* Note that we pass in cacheSlotOffset + i here instead of varDecls.at(i)->slot since + * we want independent caches for each callsite. */ + m_operands[i] = Expression::Ptr(new EvaluationCache<false>(m_operands.at(i), + varDecls.at(i), + cacheSlotOffset + i)); + } +} + +FunctionSignature::Arity UserFunctionCallsite::arity() const +{ + return m_arity; +} + +CallTargetDescription::Ptr UserFunctionCallsite::callTargetDescription() const +{ + return m_functionDeclaration->signature(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/quserfunctioncallsite_p.h b/src/xmlpatterns/expr/quserfunctioncallsite_p.h new file mode 100644 index 0000000..db6a661 --- /dev/null +++ b/src/xmlpatterns/expr/quserfunctioncallsite_p.h @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** 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_UserFunctionCallsite_H +#define Patternist_UserFunctionCallsite_H + +#include "qcallsite_p.h" +#include "qfunctionsignature_p.h" +#include "qunlimitedcontainer_p.h" +#include "quserfunction_p.h" +#include "qvariabledeclaration_p.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Performs a call to a UserFunction. + * + * UserFunctionCallsite is the call site to a function that has been + * declared in the query using <tt>declare function</tt>. That is, it is + * never used for builtin functions such as <tt>fn:count()</tt>. + * + * @see UserFunction + * @see ArgumentReference + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class UserFunctionCallsite : public CallSite + { + public: + typedef QExplicitlySharedDataPointer<UserFunctionCallsite> Ptr; + typedef QList<UserFunctionCallsite::Ptr> List; + + UserFunctionCallsite(const QXmlName name, + const FunctionSignature::Arity arity); + + virtual bool evaluateEBV(const DynamicContext::Ptr &context) const; + virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const; + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const; + + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + + /** + * We call compress on our body. + */ + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + + virtual Expression::Properties properties() const; + + /** + * @short Returns the types declared in the function declaration. + * + * @see CallTemplate::expectedOperandTypes() + */ + virtual SequenceType::List expectedOperandTypes() const; + + virtual SequenceType::Ptr staticType() const; + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + + /** + * @returns always IDUserFunctionCallsite. + */ + virtual ID id() const; + + /** + * If @p slotOffset is -1, it means this function has no arguments. + */ + void setSource(const UserFunction::Ptr &userFunction, + const VariableSlotID cacheSlotOffset); + + /** + * @returns @c true, if a function definition with signature @p sign + * would be valid to call from this callsite, otherwise @c false. + */ + bool isSignatureValid(const FunctionSignature::Ptr &sign) const; + + FunctionSignature::Arity arity() const; + + inline Expression::Ptr body() const + { + return m_body; + } + + virtual bool configureRecursion(const CallTargetDescription::Ptr &sign); + virtual CallTargetDescription::Ptr callTargetDescription() const; + + private: + /** + * Creates a new context sets the arguments, and returns it. + */ + DynamicContext::Ptr bindVariables(const DynamicContext::Ptr &context) const; + + const FunctionSignature::Arity m_arity; + /** + * The reason this variable, as well as others, aren't const, is that + * the binding to the actual function, is resolved after this + * UserFunctionCallsite has been created. + */ + VariableSlotID m_expressionSlotOffset; + + /** + * @note This may be different from m_functionDeclaration->body(). It + * may differ on a per-callsite basis. + */ + Expression::Ptr m_body; + UserFunction::Ptr m_functionDeclaration; + }; + + /** + * @short Formats UserFunctionCallsite. + * + * @relates UserFunctionCallsite + */ + static inline QString formatFunction(const UserFunctionCallsite::Ptr &func) + { + Q_UNUSED(func); + // TODO TODO TODO + // TODO Make UserFunctionCallsite always use a FunctionSignature + return QLatin1String("<span class='XQuery-function'>") + + QString() + + //escape(func->name()->toString()) + + QLatin1String("</span>"); + } +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qvalidate.cpp b/src/xmlpatterns/expr/qvalidate.cpp new file mode 100644 index 0000000..8071b32 --- /dev/null +++ b/src/xmlpatterns/expr/qvalidate.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qbuiltintypes_p.h" +#include "qgenericsequencetype_p.h" +#include "qmultiitemtype_p.h" +#include "qtypechecker_p.h" + +#include "qvalidate_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +Expression::Ptr Validate::create(const Expression::Ptr &operandNode, + const Mode validationMode, + const StaticContext::Ptr &context) +{ + Q_ASSERT(operandNode); + Q_ASSERT(validationMode == Lax || validationMode == Strict); + Q_ASSERT(context); + Q_UNUSED(validationMode); + Q_UNUSED(context); + + ItemType::List tList; + tList.append(BuiltinTypes::element); + tList.append(BuiltinTypes::document); + + const SequenceType::Ptr elementOrDocument(makeGenericSequenceType(ItemType::Ptr(new MultiItemType(tList)), + Cardinality::exactlyOne())); + + + return TypeChecker::applyFunctionConversion(operandNode, + elementOrDocument, + context, + ReportContext::XQTY0030); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qvalidate_p.h b/src/xmlpatterns/expr/qvalidate_p.h new file mode 100644 index 0000000..10910cd --- /dev/null +++ b/src/xmlpatterns/expr/qvalidate_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** 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_Validate_H +#define Patternist_Validate_H + +#include "qexpression_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Handles XQuery 1.0's <tt>validate</tt> expression. + * + * This class is currently not used. The Schema Validation Feature is not supported. + * + * @see <a href="http://www.w3.org/TR/xquery/#id-validate">XQuery 1.0: An XML + * Query Language, 3.13 Validate Expressions</a> + * @see <a href="http://www.w3.org/TR/xquery/#id-schema-validation-feature">XQuery 1.0: An + * XML Query Language, 5.2.2 Schema Validation Feature</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class Validate + { + public: + + /** + * Represents the validation mode. + */ + enum Mode + { + Lax = 1, + Strict + }; + + /** + * Creates the necessary Expression instances + * that validates the operand node @p operandNode in mode @p validationMode, + * and returns it. + */ + static Expression::Ptr create(const Expression::Ptr &operandNode, + const Mode validationMode, + const StaticContext::Ptr &context); + private: + Validate(); + Q_DISABLE_COPY(Validate) + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qvaluecomparison.cpp b/src/xmlpatterns/expr/qvaluecomparison.cpp new file mode 100644 index 0000000..fd0e51b --- /dev/null +++ b/src/xmlpatterns/expr/qvaluecomparison.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qitem_p.h" +#include "qboolean_p.h" +#include "qbuiltintypes_p.h" +#include "qcommonsequencetypes_p.h" +#include "qemptysequence_p.h" +#include "qoptimizationpasses_p.h" + +#include "qvaluecomparison_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +ValueComparison::ValueComparison(const Expression::Ptr &op1, + const AtomicComparator::Operator op, + const Expression::Ptr &op2) : PairContainer(op1, op2), + m_operator(op) +{ +} + +Item ValueComparison::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + const Item it1(m_operand1->evaluateSingleton(context)); + if(!it1) + return Item(); + + const Item it2(m_operand2->evaluateSingleton(context)); + if(!it2) + return Item(); + + return Boolean::fromValue(flexibleCompare(it1, it2, context)); +} + +Expression::Ptr ValueComparison::typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType) +{ + const Expression::Ptr me(PairContainer::typeCheck(context, reqType)); + const ItemType::Ptr t1(m_operand1->staticType()->itemType()); + const ItemType::Ptr t2(m_operand2->staticType()->itemType()); + Q_ASSERT(t1); + Q_ASSERT(t2); + + if(*CommonSequenceTypes::Empty == *t1 || + *CommonSequenceTypes::Empty == *t2) + { + return EmptySequence::create(this, context); + } + else + { + prepareComparison(fetchComparator(t1, t2, context)); + + return me; + } +} + +Expression::Ptr ValueComparison::compress(const StaticContext::Ptr &context) +{ + const Expression::Ptr me(PairContainer::compress(context)); + + if(me != this) + return me; + + if(isCaseInsensitiveCompare(m_operand1, m_operand2)) + useCaseInsensitiveComparator(); + + return me; +} + +bool ValueComparison::isCaseInsensitiveCompare(Expression::Ptr &op1, Expression::Ptr &op2) +{ + Q_ASSERT(op1); + Q_ASSERT(op2); + + const ID iD = op1->id(); + + if((iD == IDLowerCaseFN || iD == IDUpperCaseFN) && iD == op2->id()) + { + /* Both are either fn:lower-case() or fn:upper-case(). */ + + /* Replace the calls to the functions with its operands. */ + op1 = op1->operands().first(); + op2 = op2->operands().first(); + + return true; + } + else + return false; +} + +OptimizationPass::List ValueComparison::optimizationPasses() const +{ + return OptimizationPasses::comparisonPasses; +} + +SequenceType::List ValueComparison::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrOneAtomicType); + result.append(CommonSequenceTypes::ZeroOrOneAtomicType); + return result; +} + +SequenceType::Ptr ValueComparison::staticType() const +{ + if(m_operand1->staticType()->cardinality().allowsEmpty() || + m_operand2->staticType()->cardinality().allowsEmpty()) + return CommonSequenceTypes::ZeroOrOneBoolean; + else + return CommonSequenceTypes::ExactlyOneBoolean; +} + +ExpressionVisitorResult::Ptr ValueComparison::accept(const ExpressionVisitor::Ptr &visitor) const +{ + return visitor->visit(this); +} + +Expression::ID ValueComparison::id() const +{ + return IDValueComparison; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qvaluecomparison_p.h b/src/xmlpatterns/expr/qvaluecomparison_p.h new file mode 100644 index 0000000..3aa9f5f --- /dev/null +++ b/src/xmlpatterns/expr/qvaluecomparison_p.h @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** 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_ValueComparison_H +#define Patternist_ValueComparison_H + +#include "qatomiccomparator_p.h" +#include "qpaircontainer_p.h" +#include "qcomparisonplatform_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short Implements XPath 2.0 value comparions, such as the <tt>eq</tt> operator. + * + * ComparisonPlatform is inherited with @c protected scope because ComparisonPlatform + * must access members of ValueComparison. + * + * @see <a href="http://www.w3.org/TR/xpath20/#id-value-comparisons">XML Path Language + * (XPath) 2.0, 3.5.1 Value Comparisons</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class ValueComparison : public PairContainer, + public ComparisonPlatform<ValueComparison, true> + { + public: + ValueComparison(const Expression::Ptr &op1, + const AtomicComparator::Operator op, + const Expression::Ptr &op2); + + virtual Item evaluateSingleton(const DynamicContext::Ptr &) const; + + virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, + const SequenceType::Ptr &reqType); + + /** + * @returns always CommonSequenceTypes::ExactlyOneBoolean + */ + virtual SequenceType::Ptr staticType() const; + + virtual SequenceType::List expectedOperandTypes() const; + + /** + * @returns IDValueComparison + */ + virtual ID id() const; + + virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const; + virtual QList<QExplicitlySharedDataPointer<OptimizationPass> > optimizationPasses() const; + + /** + * Overridden to optimize case-insensitive compares. + */ + virtual Expression::Ptr compress(const StaticContext::Ptr &context); + + /** + * @returns the operator that this ValueComparison is using. + */ + inline AtomicComparator::Operator operatorID() const + { + return m_operator; + } + + /** + * It is considered that the string value from @p op1 will be compared against @p op2. This + * function determines whether the user intends the comparison to be case insensitive. If + * that is the case @c true is returned, and the operands are re-written appropriately. + * + * This is a helper function for Expression classes that compares strings. + * + * @see ComparisonPlatform::useCaseInsensitiveComparator() + */ + static bool isCaseInsensitiveCompare(Expression::Ptr &op1, Expression::Ptr &op2); + + private: + const AtomicComparator::Operator m_operator; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qvariabledeclaration.cpp b/src/xmlpatterns/expr/qvariabledeclaration.cpp new file mode 100644 index 0000000..2f5a72e --- /dev/null +++ b/src/xmlpatterns/expr/qvariabledeclaration.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qvariabledeclaration_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +bool VariableDeclaration::contains(const VariableDeclaration::List &list, + const QXmlName &lookup) +{ + VariableDeclaration::List::const_iterator it(list.constBegin()); + const VariableDeclaration::List::const_iterator end(list.constEnd()); + + for(; it != end; ++it) + { + if((*it)->name == lookup) + return true; + } + + return false; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qvariabledeclaration_p.h b/src/xmlpatterns/expr/qvariabledeclaration_p.h new file mode 100644 index 0000000..a2430a8 --- /dev/null +++ b/src/xmlpatterns/expr/qvariabledeclaration_p.h @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** 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_VariableDeclaration_H +#define Patternist_VariableDeclaration_H + +#include <QSharedData> + +#include "qexpression_p.h" +#include "qpatternistlocale_p.h" +#include "qvariablereference_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +template<typename T> class QStack; + +namespace QPatternist +{ + /** + * @short Represents a declared variable. Only used at + * the compilation stage. + * + * @see FunctionArgument + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class VariableDeclaration : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer<VariableDeclaration> Ptr; + typedef QStack<VariableDeclaration::Ptr> Stack; + typedef QList<VariableDeclaration::Ptr> List; + + /** + * @short The key is the variable name. + */ + typedef QHash<QXmlName, VariableDeclaration::Ptr> Hash; + + enum Type + { + RangeVariable, + ExpressionVariable, + FunctionArgument, + PositionalVariable, + TemplateParameter, + + /** + * A global variable is always an external variable, but it is + * cached differently. + * + * @see DynamicContext::globalItemCacheCell() + */ + GlobalVariable, + + /** + * External variables doesn't use slots, that's a big difference + * compared to the other types. + */ + ExternalVariable + }; + + /** + * Creates a VariableDeclaration. + * + * @p sourceExpr and @p seqType may be @c null. + */ + VariableDeclaration(const QXmlName n, + const VariableSlotID varSlot, + const Type t, + const SequenceType::Ptr &seqType) : name(n) + , slot(varSlot) + , type(t) + , sequenceType(seqType) + , canSourceRewrite(true) + { + Q_ASSERT(!name.isNull()); + Q_ASSERT(t == ExternalVariable || t == TemplateParameter || varSlot > -1); + } + + inline bool isUsed() const + { + return !references.isEmpty(); + } + + inline const Expression::Ptr &expression() const + { + return m_expression; + } + + inline void setExpression(const Expression::Ptr &expr) + { + m_expression = expr; + } + + /** + * @short Returns how many times this variable is used. + */ + inline bool usedByMany() const + { + return references.count() > 1; + } + + /** + * @short Returns @c true if @p list contains @p lookup. + */ + static bool contains(const VariableDeclaration::List &list, + const QXmlName &lookup); + + const QXmlName name; + const VariableSlotID slot; + const Type type; + + /** + * The declared type of the variable. What the value might be, depends + * on the context which VariableDeclaration is used in. Note that + * sequenceType is hence not in anyway obligated to the type of + * expression(). + */ + const SequenceType::Ptr sequenceType; + VariableReference::List references; + + /** + * @short Whether a reference can rewrite itself to expression(). + * + * The default value is @c true. + */ + bool canSourceRewrite; + + private: + Expression::Ptr m_expression; + Q_DISABLE_COPY(VariableDeclaration) + }; + + /** + * @short Formats @p var appropriately for display. + * + * @relates VariableDeclaration + */ + static inline QString formatKeyword(const VariableDeclaration::Ptr &var, + const NamePool::Ptr &np) + { + Q_ASSERT(var); + Q_ASSERT(np); + return formatKeyword(np->displayName(var->name)); + } + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qvariablereference.cpp b/src/xmlpatterns/expr/qvariablereference.cpp new file mode 100644 index 0000000..5281820 --- /dev/null +++ b/src/xmlpatterns/expr/qvariablereference.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qvariablereference_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +VariableReference::VariableReference(const VariableSlotID slotP) : m_varSlot(slotP) +{ + Q_ASSERT(m_varSlot > -1); +} + +Expression::Properties VariableReference::properties() const +{ + return DisableElimination; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qvariablereference_p.h b/src/xmlpatterns/expr/qvariablereference_p.h new file mode 100644 index 0000000..fca6fdd --- /dev/null +++ b/src/xmlpatterns/expr/qvariablereference_p.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** 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_VariableReference_H +#define Patternist_VariableReference_H + +#include "qemptycontainer_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +template<typename T> class QList; + +namespace QPatternist +{ + /** + * @short Baseclass for classes being references to variables. + * + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class VariableReference : public EmptyContainer + { + public: + typedef QExplicitlySharedDataPointer<VariableReference> Ptr; + typedef QList<VariableReference::Ptr> List; + + /** + * Creates a VariableReference. + * + * @param slot must be a valid slot. That is, zero or larger. + */ + VariableReference(const VariableSlotID slot); + + /** + * @returns the slot that this reference communicates through. + * + * This is a slot in the DynamicContext. Which one, depends on the + * type, which this VariableReference does not have information about. + * For instance, it could DynamicContext::expressionVariable() or + * DynamicContext::rangeVariable(). + */ + inline VariableSlotID slot() const; + + /** + * @returns DisableElimination + */ + virtual Properties properties() const; + + private: + /** + * The slot. Same as returned by slot(). + * + * This variable is not called m_slot, because that creates a weird + * compiler error on hpuxi-acc. See the preprocessor output. EvaluationCache::m_varSlot + * is a similar workaround. + */ + const VariableSlotID m_varSlot; + }; + + inline VariableSlotID VariableReference::slot() const + { + return m_varSlot; + } + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qwithparam_p.h b/src/xmlpatterns/expr/qwithparam_p.h new file mode 100644 index 0000000..7f8b542 --- /dev/null +++ b/src/xmlpatterns/expr/qwithparam_p.h @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** 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_TemplateParam_H +#define Patternist_TemplateParam_H + +#include "qfunctionargument_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Carries meta data for @c xsl:with-param as encountered in + * template callsites such as @c xsl:call-template and @c + * xsl:apply-templates. + * + * WithParam is similar to FunctionArgument, but has in addition a default + * value in the form of an Expression. + * + * @since 4.5 + * @ingroup Patternist_expressions + * @author Frans Englich <frans.englich@nokia.com> + */ + class WithParam : public FunctionArgument + { + public: + typedef QExplicitlySharedDataPointer<WithParam> Ptr; + typedef QHash<QXmlName, Ptr> Hash; + + /** + * @p sourceExpression can not be @c null. + */ + inline WithParam(const QXmlName name, + const SequenceType::Ptr &type, + const Expression::Ptr &sourceExpression); + + inline void setSourceExpression(const Expression::Ptr &expr) + { + Q_ASSERT(expr); + m_sourceExpression = expr; + } + + /** + * @short Returns the expression which is the source the value for this + * parameter. + * + * Guaranteed to never be @c null. + */ + inline Expression::Ptr sourceExpression() const + { + return m_sourceExpression; + } + + private: + Expression::Ptr m_sourceExpression; + }; + + WithParam::WithParam(const QXmlName name, + const SequenceType::Ptr &type, + const Expression::Ptr &sourceExpression) : FunctionArgument(name, type) + , m_sourceExpression(sourceExpression) + { + Q_ASSERT(m_sourceExpression); + } + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/expr/qxsltsimplecontentconstructor.cpp b/src/xmlpatterns/expr/qxsltsimplecontentconstructor.cpp new file mode 100644 index 0000000..e69dc5d --- /dev/null +++ b/src/xmlpatterns/expr/qxsltsimplecontentconstructor.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qatomicstring_p.h" +#include "qcommonsequencetypes_p.h" + +#include "qxsltsimplecontentconstructor_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XSLTSimpleContentConstructor::XSLTSimpleContentConstructor(const Expression::Ptr &source) : SimpleContentConstructor(source) +{ +} + +QString XSLTSimpleContentConstructor::processItem(const Item &item, + bool &discard, + bool &isText) +{ + if(item.isNode()) + { + isText = (item.asNode().kind() == QXmlNodeModelIndex::Text); + + if(isText) + { + const QString value(item.stringValue()); + + /* "1. Zero-length text nodes in the sequence are discarded." */ + discard = value.isEmpty(); + return value; + } + else + { + Item::Iterator::Ptr it(item.sequencedTypedValue()); /* Atomic values. */ + Item next(it->next()); + QString result; + + if(next) + result = next.stringValue(); + + next = it->next(); + + while(next) + { + result += next.stringValue(); + result += QLatin1Char(' '); + next = it->next(); + } + + return result; + } + } + else + { + discard = false; + isText = false; + return item.stringValue(); + } +} + +Item XSLTSimpleContentConstructor::evaluateSingleton(const DynamicContext::Ptr &context) const +{ + const Item::Iterator::Ptr it(m_operand->evaluateSequence(context)); + + Item next(it->next()); + QString result; + + bool previousIsText = false; + bool discard = false; + + if(next) + { + const QString unit(processItem(next, discard, previousIsText)); + + if(!discard) + result = unit; + + next = it->next(); + } + else + return Item(); + + while(next) + { + bool currentIsText = false; + const QString unit(processItem(next, discard, currentIsText)); + + if(!discard) + { + /* "Adjacent text nodes in the sequence are merged into a single text + * node." */ + if(previousIsText && currentIsText) + ; + else + result += QLatin1Char(' '); + + result += unit; + } + + next = it->next(); + previousIsText = currentIsText; + } + + return AtomicString::fromValue(result); +} + +SequenceType::List XSLTSimpleContentConstructor::expectedOperandTypes() const +{ + SequenceType::List result; + result.append(CommonSequenceTypes::ZeroOrMoreItems); + return result; +} + +SequenceType::Ptr XSLTSimpleContentConstructor::staticType() const +{ + return CommonSequenceTypes::ZeroOrOneString; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/expr/qxsltsimplecontentconstructor_p.h b/src/xmlpatterns/expr/qxsltsimplecontentconstructor_p.h new file mode 100644 index 0000000..853a38b --- /dev/null +++ b/src/xmlpatterns/expr/qxsltsimplecontentconstructor_p.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** 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_XSLTSimpleContentConstructor_H +#define Patternist_XSLTSimpleContentConstructor_H + +#include "qsimplecontentconstructor_p.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Implements XSL-T's construction of simple content, which is + * different from XQuery's approach. + * + * @see <a href="http://www.w3.org/TR/xslt20/#constructing-simple-content">XSL + * Transformations (XSLT) Version 2.0, 5.7.2 Constructing Simple Content</a> + * @author Frans Englich <frans.englich@nokia.com> + * @ingroup Patternist_expressions + */ + class XSLTSimpleContentConstructor : public SimpleContentConstructor + { + public: + XSLTSimpleContentConstructor(const Expression::Ptr &source); + virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const; + + virtual SequenceType::List expectedOperandTypes() const; + virtual SequenceType::Ptr staticType() const; + private: + static inline QString processItem(const Item &item, + bool &discard, + bool &isText); + }; +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif |