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);
}
Expression::Ptr ElementConstructor::typeCheck(const StaticContext::Ptr &context,
                                              const SequenceType::Ptr &reqType)
{
    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);
}
Пример #3
0
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);
     */
}
Пример #4
0
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);
}