/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtXmlPatterns module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $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() ge 1" into "exists()" */ 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 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() gt 0" into "exists()" */ 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() ne 0" into "exists()" */ 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() eq 0" into "empty()" */ 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 return $var" into "" */ 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() then true() else false()" to "" */ 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