Search in sources :

Example 11 with SequenceType

use of org.exist.xquery.value.SequenceType in project exist by eXist-db.

the class PartialFunctionApplication method createPartial.

private FunctionReference createPartial(Sequence contextSequence, Item contextItem, FunctionCall staticCall) throws XPathException {
    final FunctionSignature signature = staticCall.getSignature();
    final SequenceType[] paramTypes = signature.getArgumentTypes();
    // the parameters of the newly created inline function:
    // old params except the fixed ones
    final List<SequenceType> newParamTypes = new ArrayList<>();
    // the arguments to pass to the inner call
    final List<Expression> callArgs = new ArrayList<>();
    // parameter variables of the new inline function
    final List<QName> variables = new ArrayList<>();
    // the inline function
    final int argCount = staticCall.getArgumentCount();
    for (int i = 0; i < argCount; i++) {
        final Expression param = staticCall.getArgument(i);
        if (param instanceof Function.Placeholder) {
            // overloaded functions like concat may have an arbitrary number of arguments
            if (i < paramTypes.length) {
                newParamTypes.add(paramTypes[i]);
            } else // overloaded function: add last sequence type
            {
                newParamTypes.add(paramTypes[paramTypes.length - 1]);
            }
            // create local parameter variables
            final QName varName = new QName("vp" + i, XMLConstants.NULL_NS_URI);
            variables.add(varName);
            // the argument to the inner call is a variable ref
            final VariableReference ref = new VariableReference(context, varName);
            callArgs.add(ref);
        } else {
            // fixed argument: just compute the argument value
            try {
                param.analyze(cachedContextInfo);
                final Sequence seq = param.eval(contextSequence, contextItem);
                callArgs.add(new PrecomputedValue(context, seq));
            } catch (final XPathException e) {
                if (e.getLine() <= 0) {
                    e.setLocation(line, column, getSource());
                }
                // append location of the function call to the exception message:
                e.addFunctionCall(function.functionDef, this);
                throw e;
            }
        }
    }
    final SequenceType[] newParamArray = newParamTypes.toArray(new SequenceType[0]);
    final QName name = new QName(PARTIAL_FUN_PREFIX + hashCode(), XMLConstants.NULL_NS_URI);
    final FunctionSignature newSignature = new FunctionSignature(name, newParamArray, signature.getReturnType());
    final UserDefinedFunction func = new UserDefinedFunction(context, newSignature);
    func.setLocation(staticCall.getLine(), staticCall.getColumn());
    // add the created parameter variables to the function
    for (final QName varName : variables) {
        func.addVariable(varName);
    }
    final FunctionCall innerCall = new FunctionCall(staticCall);
    innerCall.setArguments(callArgs);
    func.setFunctionBody(innerCall);
    final FunctionCall newCall = new FunctionCall(context, func);
    newCall.setLocation(staticCall.getLine(), staticCall.getColumn());
    return new FunctionReference(newCall);
}
Also used : QName(org.exist.dom.QName) ArrayList(java.util.ArrayList) SequenceType(org.exist.xquery.value.SequenceType) Sequence(org.exist.xquery.value.Sequence) FunctionReference(org.exist.xquery.value.FunctionReference)

Aggregations

SequenceType (org.exist.xquery.value.SequenceType)11 FunctionParameterSequenceType (org.exist.xquery.value.FunctionParameterSequenceType)6 FunctionReturnSequenceType (org.exist.xquery.value.FunctionReturnSequenceType)5 ArrayList (java.util.ArrayList)3 QName (org.exist.dom.QName)3 Sequence (org.exist.xquery.value.Sequence)3 AttributesImpl (org.xml.sax.helpers.AttributesImpl)3 Map (java.util.Map)2 HashMap (java.util.HashMap)1 org.exist.xquery (org.exist.xquery)1 FunctionReference (org.exist.xquery.value.FunctionReference)1 Item (org.exist.xquery.value.Item)1 ValueSequence (org.exist.xquery.value.ValueSequence)1 Sequence (org.exquery.xquery.Sequence)1 TypedArgumentValue (org.exquery.xquery.TypedArgumentValue)1 Test (org.junit.Test)1