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. */ }
Expression::Ptr PatternPlatform::compress(const StaticContext::Ptr &context) { const Expression::Ptr me(FunctionCall::compress(context)); if(me != this) return me; if(m_operands.at(1)->is(IDStringValue)) { const DynamicContext::Ptr dynContext(context->dynamicContext()); m_pattern = parsePattern(m_operands.at(1)->evaluateSingleton(dynContext).stringValue(), dynContext); m_compiledParts |= PatternPrecompiled; } const Expression::Ptr flagOperand(m_operands.value(m_flagsPosition)); if(!flagOperand) { m_flags = NoFlags; m_compiledParts |= FlagsPrecompiled; } else if(flagOperand->is(IDStringValue)) { const DynamicContext::Ptr dynContext(context->dynamicContext()); m_flags = parseFlags(flagOperand->evaluateSingleton(dynContext).stringValue(), dynContext); m_compiledParts |= FlagsPrecompiled; } if(m_compiledParts == FlagsAndPattern) applyFlags(m_flags, m_pattern); return me; }
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. */ } }
bool ByIDIdentifier::matches(const Expression::Ptr &expr) const { return expr->is(m_id); }
bool BooleanIdentifier::matches(const Expression::Ptr &expr) const { return expr->is(Expression::IDBooleanValue) && expr->evaluateEBV(DynamicContext::Ptr()) == m_value; }
bool IntegerIdentifier::matches(const Expression::Ptr &expr) const { return expr->is(Expression::IDIntegerValue) && expr->as<Literal>()->item().as<Numeric>()->toInteger() == m_num; }