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

net.sf.saxon.style.XSLFunction Maven / Gradle / Ivy

There is a newer version: 10.5
Show newest version
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2013 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.style;

import net.sf.saxon.Configuration;
import net.sf.saxon.expr.*;
import net.sf.saxon.expr.instruct.*;
import net.sf.saxon.expr.parser.*;
import net.sf.saxon.lib.NamespaceConstant;
import net.sf.saxon.om.*;
import net.sf.saxon.trans.SaxonErrorCode;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.tree.iter.AxisIterator;
import net.sf.saxon.tree.util.FastStringBuffer;
import net.sf.saxon.value.SequenceType;
import net.sf.saxon.value.Whitespace;

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

/**
* Handler for xsl:function elements in stylesheet (XSLT 2.0). 
* Attributes:
* name gives the name of the function * saxon:memo-function=yes|no indicates whether it acts as a memo function. */ public class XSLFunction extends StyleElement implements StylesheetProcedure { /*@Nullable*/ private String nameAtt = null; private String asAtt = null; private String overrideAtt = null; private SequenceType resultType; private String functionName; private SlotManager stackFrameMap; private boolean memoFunction = false; private boolean override = true; private int numberOfArguments = -1; // -1 means not yet known private UserFunction compiledFunction; // List of UserFunctionCall objects that reference this XSLFunction List references = new ArrayList(10); /** * Method called by UserFunctionCall to register the function call for * subsequent fixup. * @param ref the UserFunctionCall to be registered */ public void registerReference(UserFunctionReference ref) { references.add(ref); } /** * Ask whether this node is a declaration, that is, a permitted child of xsl:stylesheet * (including xsl:include and xsl:import). * @return true for this element */ @Override public boolean isDeclaration() { return true; } public void prepareAttributes() throws XPathException { AttributeCollection atts = getAttributeList(); overrideAtt = "yes"; for (int a=0; a 0, tailCalls > 1); compiledFunction.setBody(new TailCallLoop(compiledFunction)); } // Generate byte code if appropriate if (getConfiguration().isGenerateByteCode(Configuration.XSLT)) { try { Expression cbody = opt.compileToByteCode(compiledFunction.getBody(), nameAtt, Expression.PROCESS_METHOD | Expression.ITERATE_METHOD); if (cbody != null) { compiledFunction.setBody(cbody); } } catch (Exception e) { System.err.println("Failed while compiling function " + nameAtt); e.printStackTrace(); throw new XPathException(e); } } compiledFunction.computeEvaluationMode(); if (isExplaining()) { exp2.explain(getConfiguration().getStandardErrorOutput()); } } /** * Fixup all function references. * @param compiledFunction the Instruction representing this function in the compiled code * @throws XPathException if an error occurs. */ private void fixupInstruction(UserFunction compiledFunction) throws XPathException { ExpressionVisitor visitor = makeExpressionVisitor(); try { for (UserFunctionReference reference : references) { reference.setFunction(compiledFunction); if (reference instanceof UserFunctionCall) { UserFunctionCall call = (UserFunctionCall)reference; call.checkFunctionCall(compiledFunction, visitor); call.computeArgumentEvaluationModes(); } } } catch (XPathException err) { compileError(err); } } /** * Get associated Procedure (for details of stack frame). * @return the associated Procedure object */ public SlotManager getSlotManager() { return stackFrameMap; } /** * Get the type of value returned by this function * @return the declared result type, or the inferred result type * if this is more precise */ public SequenceType getResultType() { if (resultType == null) { // may be handling a forwards reference - see hof-038 String asAtt = getAttributeValue("", "as"); if (asAtt != null) { try { resultType = makeSequenceType(asAtt); } catch (XPathException err) { // the error will be reported when we get round to processing the function declaration } } } return resultType == null ? SequenceType.ANY_SEQUENCE : resultType; } /** * Get the number of arguments declared by this function (that is, its arity). * @return the arity of the function */ public int getNumberOfArguments() { if (numberOfArguments == -1) { numberOfArguments = 0; AxisIterator kids = iterateAxis(AxisInfo.CHILD); while (true) { Item child = kids.next(); if (child instanceof XSLLocalParam) { numberOfArguments++; } else { return numberOfArguments; } } } return numberOfArguments; } /** * Set the definitions of the parameters in the compiled function, as an array. * @param fn the compiled object representing the user-written function */ public void setParameterDefinitions(UserFunction fn) { UserFunctionParameter[] params = new UserFunctionParameter[getNumberOfArguments()]; fn.setParameterDefinitions(params); int count = 0; AxisIterator kids = iterateAxis(AxisInfo.CHILD); while (true) { NodeInfo node = kids.next(); if (node == null) { return; } if (node instanceof XSLLocalParam) { UserFunctionParameter param = new UserFunctionParameter(); params[count++] = param; param.setRequiredType(((XSLLocalParam)node).getRequiredType()); param.setVariableQName(((XSLLocalParam)node).getVariableQName()); param.setSlotNumber(((XSLLocalParam)node).getSlotNumber()); ((XSLLocalParam)node).getSourceBinding().fixupBinding(param); int refs = ExpressionTool.getReferenceCount(fn.getBody(), param, false); param.setReferenceCount(refs); } } } /** * Get the argument types * @return the declared types of the arguments */ public SequenceType[] getArgumentTypes() { SequenceType[] types = new SequenceType[getNumberOfArguments()]; int count = 0; AxisIterator kids = iterateAxis(AxisInfo.CHILD); while (true) { NodeInfo node = kids.next(); if (node == null) { return types; } if (node instanceof XSLLocalParam) { types[count++] = (((XSLLocalParam)node).getRequiredType()); } } } /** * Get the compiled function * @return the object representing the compiled user-written function */ public UserFunction getCompiledFunction() { return compiledFunction; } /** * Get the type of construct. This will be a constant in * class {@link net.sf.saxon.trace.Location}. This method is part of the * {@link net.sf.saxon.trace.InstructionInfo} interface */ public int getConstructType() { return StandardNames.XSL_FUNCTION; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy