All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.saxon.functions.hof.PartialApply Maven / Gradle / Ivy

There is a newer version: 12.5
Show newest version
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2020 Saxonica Limited
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

package net.sf.saxon.functions.hof;

import net.sf.saxon.expr.*;
import net.sf.saxon.expr.parser.*;
import net.sf.saxon.om.Function;
import net.sf.saxon.om.Sequence;
import net.sf.saxon.om.SequenceTool;
import net.sf.saxon.trace.ExpressionPresenter;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.transpile.CSharpSuppressWarnings;
import net.sf.saxon.type.AnyFunctionType;
import net.sf.saxon.type.ItemType;
import net.sf.saxon.type.SpecificFunctionType;
import net.sf.saxon.value.SequenceType;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * This expression class implements the operation of currying (or performing partial application) of a function.
 * That is, it takes a function and a set of argument bindings as input, and produces a new function as output.
 */

public class PartialApply extends Expression {

    private final Operand baseOp;
    private final Operand[] boundArgumentsOp; // contains null where the question marks appear

    /**
     * Create a partial function application expression
     *
     * @param base           the expression that returns the function to be called
     * @param boundArguments an array in which each element is either an expression to be bound to the corresponding
     *                       argument, or null to represent a placeholder ("?" in the source syntax)
     */

    public PartialApply(Expression base, Expression[] boundArguments) {
        baseOp = new Operand(this, base, OperandRole.INSPECT);
        adoptChildExpression(base);
        boundArgumentsOp = new Operand[boundArguments.length];
        for (int i=0; i operands() {
        List operanda = new ArrayList(boundArgumentsOp.length + 1);
        operanda.add(baseOp);
        for (Operand o : boundArgumentsOp) {
            if (o != null) {
                operanda.add(o);
            }
        }
        return operanda;
    }

    public int getNumberOfArguments() {
        return boundArgumentsOp.length;
    }

    public Expression getArgument(int n) {
        Operand o = boundArgumentsOp[n];
        return o==null ? null : o.getChildExpression();
    }

    @Override
    public int getImplementationMethod() {
        return EVALUATE_METHOD;
    }

    /**
     * Is this expression the same as another expression?
     *
     * @param other the expression to be compared with this one
     * @return true if the two expressions are statically equivalent
     */
    @Override
    public boolean equals(Object other) {
        if (!(other instanceof PartialApply)) {
            return false;
        } else {
            PartialApply pa2 = (PartialApply)other;
            if (!getBaseExpression().isEqual(pa2.getBaseExpression())) {
                return false;
            }
            if (boundArgumentsOp.length != pa2.boundArgumentsOp.length) {
                return false;
            }
            for (int i=0; iThe toString() method for an expression attempts to give a representation of the expression
     * in an XPath-like form.

*

For subclasses of Expression that represent XPath expressions, the result should always be a string that * parses as an XPath 3.0 expression. The expression produced should be equivalent to the original making certain * assumptions about the static context. In general the expansion will make no assumptions about namespace bindings, * except that (a) the prefix "xs" is used to refer to the XML Schema namespace, and (b) the default funcion namespace * is assumed to be the "fn" namespace.

*

In the case of XSLT instructions and XQuery expressions, the toString() method gives an abstracted view of the syntax * that is not designed in general to be parseable.

* * @return a representation of the expression as a string */ @Override @CSharpSuppressWarnings("UnsafeIteratorConversion") public String toString() { StringBuilder buff = new StringBuilder(64); boolean par = getBaseExpression().operands().iterator().hasNext(); if (par) { buff.append("(" + getBaseExpression().toString() + ")"); } else { buff.append(getBaseExpression().toString()); } buff.append("("); for (int i = 0; i < boundArgumentsOp.length; i++) { if (boundArgumentsOp[i] == null) { buff.append("?"); } else { buff.append(boundArgumentsOp[i].getChildExpression().toString()); } if (i != boundArgumentsOp.length - 1) { buff.append(", "); } } buff.append(")"); return buff.toString(); } /** * Evaluate this expression at run-time * * @param context The XPath dynamic evaluation context * @return the result of the function, or null to represent an empty sequence * @throws net.sf.saxon.trans.XPathException * if a dynamic error occurs during evaluation of the function. */ @Override public Function evaluateItem(XPathContext context) throws XPathException { Function f = (Function) getBaseExpression().evaluateItem(context); assert f != null; Sequence[] values = new Sequence[boundArgumentsOp.length]; for (int i = 0; i < boundArgumentsOp.length; i++) { if (boundArgumentsOp[i] == null) { values[i] = null; } else { values[i] = SequenceTool.toGroundedValue(boundArgumentsOp[i].getChildExpression().iterate(context)); } } return new CurriedFunction(f, values); } /** * Get a name identifying the kind of expression, in terms meaningful to a user. * * @return a name identifying the kind of expression, in terms meaningful to a user. * The name will always be in the form of a lexical XML QName, and should match the name used * in export() output displaying the expression. */ @Override public String getExpressionName() { return "partialApply"; } } // Copyright (c) 2011-2022 Saxonica Limited




© 2015 - 2024 Weber Informatics LLC | Privacy Policy