net.sf.saxon.expr.instruct.Fork Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Saxon-HE Show documentation
Show all versions of Saxon-HE Show documentation
The XSLT and XQuery Processor
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2018-2023 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.expr.instruct;
import net.sf.saxon.expr.Expression;
import net.sf.saxon.expr.Operand;
import net.sf.saxon.expr.OperandRole;
import net.sf.saxon.expr.elab.Elaborator;
import net.sf.saxon.expr.elab.PushElaborator;
import net.sf.saxon.expr.elab.PushEvaluator;
import net.sf.saxon.expr.parser.ExpressionTool;
import net.sf.saxon.expr.parser.RebindingMap;
import net.sf.saxon.om.StandardNames;
import net.sf.saxon.trace.ExpressionPresenter;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.type.AnyItemType;
import net.sf.saxon.type.ErrorType;
import net.sf.saxon.type.ItemType;
import net.sf.saxon.type.Type;
import java.util.Arrays;
/**
* This class implements an xsl:fork expression.
*/
public class Fork extends Instruction {
Operand[] operanda;
/**
* Create a Fork instruction
* @param prongs the children of the xsl:fork instructions.
*/
public Fork(Operand[] prongs) {
operanda = new Operand[prongs.length];
for (int i=0; i operands() {
return Arrays.asList(operanda);
}
/**
* Get the namecode of the instruction for use in diagnostics
*
* @return a code identifying the instruction: typically but not always
* the fingerprint of a name in the XSLT namespace
*/
@Override
public int getInstructionNameCode() {
return StandardNames.XSL_FORK;
}
/**
* Get the number of prongs in the fork
* @return the number of xsl:sequence children
*/
public int getSize() {
return operanda.length;
}
/**
* Get the n'th child expression of the xsl:fork (zero-based)
* @param i the index of the required subexpression
* @return the i'th subexpression if it exists
* @throws IllegalArgumentException if i is out of range
*/
public Expression getProng(int i) {
return operanda[i].getChildExpression();
}
/**
* Determine the item type of the value returned by the function
*/
/*@NotNull*/
@Override
public ItemType getItemType() {
if (getSize() == 0) {
return ErrorType.getInstance();
}
ItemType t1 = null;
for (Operand o : operands()) {
ItemType t2 = o.getChildExpression().getItemType();
t1 = t1 == null ? t2 : Type.getCommonSuperType(t1, t2);
if (t1 instanceof AnyItemType) {
return t1; // no point going any further
}
}
return t1;
}
/**
* Get the (partial) name of a class that supports streaming of this kind of expression
*
* @return the partial name of a class that can be instantiated to provide streaming support in Saxon-EE,
* or null if there is no such class
*/
@Override
public String getStreamerName() {
return "Fork";
}
/**
* Copy an expression. This makes a deep copy.
*
* @return the copy of the original expression
* @param rebindings the rebinding map
*/
/*@NotNull*/
@Override
public Expression copy(RebindingMap rebindings) {
Expression[] e2 = new Expression[getSize()];
int i=0;
for (Operand o : operands()) {
e2[i++] = o.getChildExpression().copy(rebindings);
}
Fork f2 = new Fork(e2);
ExpressionTool.copyLocationInfo(this, f2);
return f2;
}
/**
* Diagnostic print of expression structure. The abstract expression tree
* is written to the supplied output destination.
*
* @param out the expression presenter used to display the structure
*/
@Override
public void export(ExpressionPresenter out) throws XPathException {
out.startElement("fork", this);
for (Operand o : operands()) {
o.getChildExpression().export(out);
}
out.endElement();
}
@Override
public Elaborator getElaborator() {
return new ForkElaborator();
}
private static class ForkElaborator extends PushElaborator {
@Override
public PushEvaluator elaborateForPush() {
Fork expr = (Fork)getExpression();
PushEvaluator[] prongs = new PushEvaluator[expr.getSize()];
for (int i=0; i {
// non-streamed evaluation
for (PushEvaluator prong : prongs) {
dispatchTailCall(prong.processLeavingTail(output, context));
}
return null;
};
}
}
}