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

net.sf.saxon.expr.instruct.LocalParamSetter 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.expr.instruct;



import net.sf.saxon.expr.Expression;
import net.sf.saxon.expr.StaticProperty;
import net.sf.saxon.expr.XPathContext;
import net.sf.saxon.expr.parser.ExpressionTool;
import net.sf.saxon.expr.parser.ExpressionVisitor;
import net.sf.saxon.om.StandardNames;
import net.sf.saxon.trace.ExpressionPresenter;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.type.ErrorType;
import net.sf.saxon.type.ItemType;
import net.sf.saxon.type.TypeHierarchy;

import java.util.Iterator;

/**
 * The compiled form of an xsl:param element within a template in an XSLT stylesheet. An xsl:param
 * element used as a template parameter is compiled into two objects: a LocalParam which represents the
 * parameter definition and the Binding for the value, and a LocalParamSetter which is an Instruction
 * to set a default value for the parameter if none has been supplied.
 *
 * 

The xsl:param element in XSLT has mandatory attribute name and optional attribute select. It can also * be specified as required="yes" or required="no".

* *

This is used only for parameters to XSLT templates. For function calls, the caller of the function * places supplied arguments onto the callee's stackframe and the callee does not need to do anything. * Global parameters (XQuery external variables) are handled using {@link net.sf.saxon.expr.instruct.GlobalParam}.

* *

The LocalParam class is also used to represent parameters with the saxon:iterate instruction

*/ public final class LocalParamSetter extends Instruction { /*@NotNull*/ private LocalParam binding; public LocalParamSetter(/*@NotNull*/ LocalParam binding) { this.binding = binding; } /** * Get the LocalParam element representing the binding for this parameter * @return the binding element */ /*@NotNull*/ public LocalParam getBinding() { return binding; } /** * Get the item type of the items returned by evaluating this instruction * * @param th the type hierarchy cache * @return the static item type of the instruction */ /*@NotNull*/ @Override public ItemType getItemType(TypeHierarchy th) { return ErrorType.getInstance(); } /** * Get the cardinality of the sequence returned by evaluating this instruction * * @return the static cardinality */ @Override public int computeCardinality() { return StaticProperty.ALLOWS_ZERO_OR_MORE; } /** * Get the static properties of this expression (other than its type). The result is * bit-signficant. These properties are used for optimizations. In general, if * property bit is set, it is true, but if it is unset, the value is unknown. * * @return a set of flags indicating static properties of this expression */ @Override public int computeSpecialProperties() { return 0; } /** * Determine whether this instruction creates new nodes. * This implementation returns a default value of false * * @return true if the instruction creates new nodes (or if it can't be proved that it doesn't) */ @Override public boolean createsNewNodes() { return false; } /** * Simplify an expression. This performs any static optimization (by rewriting the expression * as a different expression). The default implementation does nothing. * * @param visitor an expression visitor * @return the simplified expression * @throws net.sf.saxon.trans.XPathException * if an error is discovered during expression * rewriting */ /*@NotNull*/ @Override public Expression simplify(ExpressionVisitor visitor) throws XPathException { Expression select = binding.getSelectExpression(); if (select != null) { binding.setSelectExpression(visitor.simplify(select)); adoptChildExpression(select); } return this; } /** * Perform type checking of an expression and its subexpressions. This is the second phase of * static optimization. *

*

This checks statically that the operands of the expression have * the correct type; if necessary it generates code to do run-time type checking or type * conversion. A static type error is reported only if execution cannot possibly succeed, that * is, if a run-time type error is inevitable. The call may return a modified form of the expression.

*

*

This method is called after all references to functions and variables have been resolved * to the declaration of the function or variable. However, the types of such functions and * variables may not be accurately known if they have not been explicitly declared.

*

*

If the implementation returns a value other than "this", then it is required to ensure that * the location information in the returned expression have been set up correctly. * It should not rely on the caller to do this, although for historical reasons many callers do so.

* * @param visitor an expression visitor * @param contextItemType the static type of "." at the point where this expression is invoked. * The parameter is set to null if it is known statically that the context item will be undefined. * If the type of the context item is not known statically, the argument is set to * {@link net.sf.saxon.type.Type#ITEM_TYPE} * @return the original expression, rewritten to perform necessary run-time type checks, * and to perform other type-related optimizations * @throws net.sf.saxon.trans.XPathException * if an error is discovered during this phase * (typically a type error) */ /*@NotNull*/ @Override public Expression typeCheck(ExpressionVisitor visitor, ExpressionVisitor.ContextItemType contextItemType) throws XPathException { Expression select = binding.getSelectExpression(); if (select != null) { binding.setSelectExpression(visitor.typeCheck(select, contextItemType)); adoptChildExpression(select); } binding.checkAgainstRequiredType(visitor); return this; } /** * Perform optimisation of an expression and its subexpressions. This is the third and final * phase of static optimization. *

*

This method is called after all references to functions and variables have been resolved * to the declaration of the function or variable, and after all type checking has been done.

* * @param visitor an expression visitor * @param contextItemType the static type of "." at the point where this expression is invoked. * The parameter is set to null if it is known statically that the context item will be undefined. * If the type of the context item is not known statically, the argument is set to * {@link net.sf.saxon.type.Type#ITEM_TYPE} * @return the original expression, rewritten if appropriate to optimize execution * @throws net.sf.saxon.trans.XPathException * if an error is discovered during this phase * (typically a type error) */ /*@NotNull*/ @Override public Expression optimize(ExpressionVisitor visitor, ExpressionVisitor.ContextItemType contextItemType) throws XPathException { Expression select = binding.getSelectExpression(); if (select != null) { binding.setSelectExpression(visitor.optimize(select, contextItemType)); adoptChildExpression(select); binding.computeEvaluationMode(); } return this; } /** * Copy an expression. This makes a deep copy. * * @return the copy of the original expression */ /*@NotNull*/ @Override public Expression copy() { return new LocalParamSetter(binding); } /** * Get the name of this instruction for diagnostic and tracing purposes */ public int getInstructionNameCode() { return StandardNames.XSL_PARAM; } /** * Get all the XPath expressions associated with this instruction * (in XSLT terms, the expression present on attributes of the instruction, * as distinct from the child instructions in a sequence construction) */ /*@NotNull*/ public Iterator iterateSubExpressions() { return binding.iterateSubExpressions(); } /** * Replace one subexpression by a replacement subexpression * @param original the original subexpression * @param replacement the replacement subexpression * @return true if the original subexpression is found */ public boolean replaceSubExpression(Expression original, Expression replacement) { return binding.replaceSubExpression(original, replacement); } /** * Process the local parameter declaration */ public TailCall processLeavingTail(XPathContext context) throws XPathException { int slotNumber = binding.getSlotNumber(); int wasSupplied = context.useLocalParameter(binding.getParameterId(), slotNumber, binding.isTunnelParam()); switch (wasSupplied) { case ParameterSet.SUPPLIED_AND_CHECKED: // No action needed break; case ParameterSet.SUPPLIED: // if a parameter was supplied by the caller, with no type-checking by the caller, // then we may need to convert it to the type required Expression conversion = binding.getConversion(); int conversionEvaluationMode = binding.getConversionEvaluationMode(); if (conversion != null) { context.setLocalVariable(slotNumber, ExpressionTool.evaluate(conversion, conversionEvaluationMode, context, 10)); // We do an eager evaluation here for safety, because the result of the // type conversion overwrites the slot where the actual supplied parameter // is contained. } break; // don't evaluate the default if a value has been supplied or if it has already been // evaluated by virtue of a forwards reference case ParameterSet.NOT_SUPPLIED: if (binding.isImplicitlyRequiredParam()) { String name = "$" + binding.getVariableQName().getDisplayName(); XPathException e = new XPathException("A value must be supplied for parameter " + name + " because " + "the default value is not a valid instance of the required type"); e.setXPathContext(context); e.setErrorCode("XTDE0610"); throw e; } else if (binding.isRequiredParam()) { String name = "$" + binding.getVariableQName().getDisplayName(); XPathException e = new XPathException("No value supplied for required parameter " + name); e.setXPathContext(context); e.setErrorCode("XTDE0700"); throw e; } context.setLocalVariable(slotNumber, binding.getSelectValue(context)); } return null; } /** * Diagnostic print of expression structure. The abstract expression tree * is written to the supplied output destination. */ public void explain(ExpressionPresenter out) { out.startElement("param"); out.emitAttribute("name", binding.getVariableQName().getDisplayName()); if (binding.getSelectExpression() != null) { binding.getSelectExpression().explain(out); } Expression conversion = binding.getConversion(); if (conversion != null) { out.startElement("conversion"); conversion.explain(out); out.endElement(); } out.endElement(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy