/** * If the variable is bound to an integer, get the minimum and maximum possible values. * Return null if unknown or not applicable */ public IntegerValue[] getIntegerBoundsForVariable() { return getSequence().getIntegerBounds(); }
/** * If the variable is bound to an integer, get the minimum and maximum possible values. * Return null if unknown or not applicable */ public IntegerValue[] getIntegerBoundsForVariable() { return getSequence().getIntegerBounds(); }
/** * Check to ensure that this expression does not contain any inappropriate updating subexpressions. * This check is overridden for those expressions that permit updating subexpressions. * * @throws net.sf.saxon.trans.XPathException * if the expression has a non-permitted updateing subexpression */ public void checkForUpdatingSubexpressions() throws XPathException { getSequence().checkForUpdatingSubexpressions(); if (getSequence().isUpdatingExpression()) { XPathException err = new XPathException( "An updating expression cannot be used to initialize a variable", "XUST0001"); err.setLocator(getSequence().getLocation()); throw err; } getAction().checkForUpdatingSubexpressions(); }
/** * Return the estimated cost of evaluating an expression. This is a very crude measure based * on the syntactic form of the expression (we have no knowledge of data values). We take * the cost of evaluating a simple scalar comparison or arithmetic expression as 1 (one), * and we assume that a sequence has length 5. The resulting estimates may be used, for * example, to reorder the predicates in a filter expression so cheaper predicates are * evaluated first. */ @Override public int getCost() { return getSequence().getCost() + 5 * getAction().getCost(); }
/** * Check to ensure that this expression does not contain any inappropriate updating subexpressions. * This check is overridden for those expressions that permit updating subexpressions. * * @throws net.sf.saxon.trans.XPathException * if the expression has a non-permitted updateing subexpression */ public void checkForUpdatingSubexpressions() throws XPathException { getSequence().checkForUpdatingSubexpressions(); if (getSequence().isUpdatingExpression()) { XPathException err = new XPathException( "An updating expression cannot be used to initialize a variable", "XUST0001"); err.setLocator(getSequence().getLocation()); throw err; } getAction().checkForUpdatingSubexpressions(); }
/** * Return the estimated cost of evaluating an expression. This is a very crude measure based * on the syntactic form of the expression (we have no knowledge of data values). We take * the cost of evaluating a simple scalar comparison or arithmetic expression as 1 (one), * and we assume that a sequence has length 5. The resulting estimates may be used, for * example, to reorder the predicates in a filter expression so cheaper predicates are * evaluated first. */ @Override public int getCost() { return getSequence().getCost() + 5 * getAction().getCost(); }
/** * Add a representation of this expression to a PathMap. The PathMap captures a map of the nodes visited * by an expression in a source tree. * <p>The default implementation of this method assumes that an expression does no navigation other than * the navigation done by evaluating its subexpressions, and that the subexpressions are evaluated in the * same context as the containing expression. The method must be overridden for any expression * where these assumptions do not hold. For example, implementations exist for AxisExpression, ParentExpression, * and RootExpression (because they perform navigation), and for the doc(), document(), and collection() * functions because they create a new navigation root. Implementations also exist for PathExpression and * FilterExpression because they have subexpressions that are evaluated in a different context from the * calling expression.</p> * * @param pathMap the PathMap to which the expression should be added * @param pathMapNodeSet the PathMapNodeSet to which the paths embodied in this expression should be added * @return the pathMapNodeSet representing the points in the source document that are both reachable by this * expression, and that represent possible results of this expression. For an expression that does * navigation, it represents the end of the arc in the path map that describes the navigation route. For other * expressions, it is the same as the input pathMapNode. */ public PathMap.PathMapNodeSet addToPathMap(PathMap pathMap, PathMap.PathMapNodeSet pathMapNodeSet) { PathMap.PathMapNodeSet varPath = getSequence().addToPathMap(pathMap, pathMapNodeSet); pathMap.registerPathForVariable(this, varPath); return getAction().addToPathMap(pathMap, pathMapNodeSet); }
/** * Add a representation of this expression to a PathMap. The PathMap captures a map of the nodes visited * by an expression in a source tree. * <p>The default implementation of this method assumes that an expression does no navigation other than * the navigation done by evaluating its subexpressions, and that the subexpressions are evaluated in the * same context as the containing expression. The method must be overridden for any expression * where these assumptions do not hold. For example, implementations exist for AxisExpression, ParentExpression, * and RootExpression (because they perform navigation), and for the doc(), document(), and collection() * functions because they create a new navigation root. Implementations also exist for PathExpression and * FilterExpression because they have subexpressions that are evaluated in a different context from the * calling expression.</p> * * @param pathMap the PathMap to which the expression should be added * @param pathMapNodeSet the PathMapNodeSet to which the paths embodied in this expression should be added * @return the pathMapNodeSet representing the points in the source document that are both reachable by this * expression, and that represent possible results of this expression. For an expression that does * navigation, it represents the end of the arc in the path map that describes the navigation route. For other * expressions, it is the same as the input pathMapNode. */ public PathMap.PathMapNodeSet addToPathMap(PathMap pathMap, PathMap.PathMapNodeSet pathMapNodeSet) { PathMap.PathMapNodeSet varPath = getSequence().addToPathMap(pathMap, pathMapNodeSet); pathMap.registerPathForVariable(this, varPath); return getAction().addToPathMap(pathMap, pathMapNodeSet); }
/** * Determine the special properties of this expression * * @return {@link StaticProperty#NON_CREATIVE} (unless the variable is assignable using saxon:assign) */ public int computeSpecialProperties() { int p = super.computeSpecialProperties(); if (binding == null || !binding.isAssignable()) { // if the variable reference is assignable, we mustn't move it, or any expression that contains it, // out of a loop. The way to achieve this is to treat it as a "creative" expression, because the // optimizer recognizes such expressions and handles them with care... p |= StaticProperty.NON_CREATIVE; } if (binding instanceof Assignation) { Expression exp = ((Assignation)binding).getSequence(); if (exp != null) { p |= (exp.getSpecialProperties() & StaticProperty.NOT_UNTYPED); } } if (staticType != null && !Cardinality.allowsMany(staticType.getCardinality()) && staticType.getPrimaryType() instanceof NodeTest) { p |= StaticProperty.SINGLE_DOCUMENT_NODESET; } return p; }
/** * Get the static type of the expression as a UType, following precisely the type * inference rules defined in the XSLT 3.0 specification. * * @return the static item type of the expression according to the XSLT 3.0 defined rules * @param contextItemType the static context item type */ @Override public UType getStaticUType(UType contextItemType) { if (binding != null) { if (binding.isGlobal() || binding instanceof LocalParam || (binding instanceof LetExpression && ((LetExpression)binding).isInstruction()) || binding instanceof LocalVariableBinding) { SequenceType st = binding.getRequiredType(); if (st != null) { return st.getPrimaryType().getUType(); } else { return UType.ANY; } } else if (binding instanceof Assignation) { return ((Assignation) binding).getSequence().getStaticUType(contextItemType); } } return UType.ANY; }
/** * Determine the special properties of this expression * * @return {@link StaticProperty#NO_NODES_NEWLY_CREATED} (unless the variable is assignable using saxon:assign) */ public int computeSpecialProperties() { int p = super.computeSpecialProperties(); if (binding == null || !binding.isAssignable()) { // if the variable reference is assignable, we mustn't move it, or any expression that contains it, // out of a loop. The way to achieve this is to treat it as a "creative" expression, because the // optimizer recognizes such expressions and handles them with care... p |= StaticProperty.NO_NODES_NEWLY_CREATED; } if (binding instanceof Assignation) { Expression exp = ((Assignation) binding).getSequence(); if (exp != null) { p |= exp.getSpecialProperties() & StaticProperty.NOT_UNTYPED_ATOMIC; } } if (staticType != null && !Cardinality.allowsMany(staticType.getCardinality()) && staticType.getPrimaryType() instanceof NodeTest) { p |= StaticProperty.SINGLE_DOCUMENT_NODESET; } return p &~ StaticProperty.ALL_NODES_NEWLY_CREATED; }
/** * Get the static type of the expression as a UType, following precisely the type * inference rules defined in the XSLT 3.0 specification. * * @return the static item type of the expression according to the XSLT 3.0 defined rules * @param contextItemType the static context item type */ @Override public UType getStaticUType(UType contextItemType) { if (binding != null) { if (binding.isGlobal() || binding instanceof LocalParam || (binding instanceof LetExpression && ((LetExpression)binding).isInstruction()) || binding instanceof LocalVariableBinding) { SequenceType st = binding.getRequiredType(); if (st != null) { return st.getPrimaryType().getUType(); } else { return UType.ANY; } } else if (binding instanceof Assignation) { return ((Assignation) binding).getSequence().getStaticUType(contextItemType); } } return UType.ANY; }
/** * Determine the special properties of this expression * * @return {@link StaticProperty#NO_NODES_NEWLY_CREATED} (unless the variable is assignable using saxon:assign) */ public int computeSpecialProperties() { int p = super.computeSpecialProperties(); if (binding == null || !binding.isAssignable()) { // if the variable reference is assignable, we mustn't move it, or any expression that contains it, // out of a loop. The way to achieve this is to treat it as a "creative" expression, because the // optimizer recognizes such expressions and handles them with care... p |= StaticProperty.NO_NODES_NEWLY_CREATED; } if (binding instanceof Assignation) { Expression exp = ((Assignation) binding).getSequence(); if (exp != null) { p |= exp.getSpecialProperties() & StaticProperty.NOT_UNTYPED_ATOMIC; } } if (staticType != null && !Cardinality.allowsMany(staticType.getCardinality()) && staticType.getPrimaryType() instanceof NodeTest) { p |= StaticProperty.SINGLE_DOCUMENT_NODESET; } return p &~ StaticProperty.ALL_NODES_NEWLY_CREATED; }