/** * Get the display name of the variable. This is taken from the variable binding if possible * @return the display name (a lexical QName */ public String getDisplayName() { if (binding != null) { return binding.getVariableQName().getDisplayName(); } else { return displayName; } }
/** * Evaluate this variable * @param c the XPath dynamic context * @return the value of the variable * @throws XPathException if any error occurs */ public ValueRepresentation evaluateVariable(XPathContext c) throws XPathException { try { return binding.evaluateVariable(c); } catch (NullPointerException err) { if (binding == null) { throw new IllegalStateException("Variable $" + displayName + " has not been fixed up"); } else { throw err; } } }
/** * Get the static cardinality */ public int computeCardinality() { if (staticType == null) { if (binding == null) { return StaticProperty.ALLOWS_ZERO_OR_MORE; } else if (binding instanceof LetExpression) { return binding.getRequiredType().getCardinality(); } else if (binding instanceof Assignation) { return StaticProperty.EXACTLY_ONE; } else if (binding.getRequiredType() == null) { return StaticProperty.ALLOWS_ZERO_OR_MORE; } else { return binding.getRequiredType().getCardinality(); } } else { return staticType.getCardinality(); } }
public int getIntrinsicDependencies() { int d = 0; if (binding == null) { // assume the worst d |= (StaticProperty.DEPENDS_ON_LOCAL_VARIABLES | StaticProperty.DEPENDS_ON_ASSIGNABLE_GLOBALS); } else if (binding.isGlobal()) { if (binding.isAssignable()) { d |= StaticProperty.DEPENDS_ON_ASSIGNABLE_GLOBALS; } } else { d |= StaticProperty.DEPENDS_ON_LOCAL_VARIABLES; } return d; }
if (e2 instanceof VariableReference) { result[0] = ((VariableReference) e2).getBinding().getVariableQName().getLocalPart(); result[0] = bind.getVariableQName().getClarkName(); result[1] = getValues(bind.evaluateVariable(ctx)); } catch (NullPointerException ee) { result[1] = null;
/** * 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 (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; }
private static void gatherSlotsUsed(Expression exp, IntHashSet slots) { if (exp instanceof VariableReference) { Binding binding = ((VariableReference)exp).getBinding(); if (binding == null) { throw new NullPointerException("Unbound variable at line " + exp.getLineNumber()); } if (!binding.isGlobal()) { int slot = binding.getLocalSlotNumber(); if (slot != -1) { if (!slots.contains(slot)) { slots.add(slot); } } } } else { Iterator iter = exp.iterateSubExpressions(); while (iter.hasNext()) { Expression sub = (Expression)iter.next(); gatherSlotsUsed(sub, slots); } } }
public TailCall processLeavingTail(XPathContext context) throws XPathException { if (binding==null) { throw new IllegalStateException("saxon:assign binding has not been fixed up"); } ValueRepresentation value = getSelectValue(context); if (value instanceof Closure) { value = SequenceExtent.makeSequenceExtent(((Closure)value).iterate()); } if (binding instanceof GeneralVariable) { if (binding.isGlobal()) { context.getController().getBindery().assignGlobalVariable((GlobalVariable)binding, value); } else { throw new UnsupportedOperationException("Local variables are not assignable"); } } else { } return null; }
/** * Replace this VariableReference where appropriate by a more efficient implementation. This * can only be done after all slot numbers are allocated. The efficiency is gained by binding the * VariableReference directly to a local or global slot, rather than going via the Binding object * @param parent the parent expression of this variable reference */ public void refineVariableReference(Expression parent) { if (binding instanceof Assignation || binding instanceof LocalParam || binding instanceof UserFunctionParameter) { // A LocalVariableReference can be evaluated directly, without going via the Binding object. int slot = binding.getLocalSlotNumber(); if (slot < 0) { // if slots haven't been allocated yet, we've come here too early. // See test group036 with -T option for an example. return; } LocalVariableReference ref = new LocalVariableReference(); ref.setSlotNumber(slot); ref.binding = binding; ref.staticType = staticType; ref.displayName = displayName; ExpressionTool.copyLocationInfo(this, ref); boolean found = parent.replaceSubExpression(this, ref); if (!found) { throw new IllegalStateException("Child expression not found in parent"); } } }
/** * Type-check the expression. At this stage details of the static type must be known. * If the variable has a compile-time value, this is substituted for the variable reference */ /*@NotNull*/ public Expression typeCheck(ExpressionVisitor visitor, ContextItemStaticInfo contextInfo) throws XPathException { if (constantValue != null) { binding = null; return Literal.makeLiteral(constantValue, this); } // if (staticType == null) { // throw new IllegalStateException("Variable $" + getDisplayName() + " has not been fixed up"); // } // following code removed because it causes error181 to blow the stack - need to check for circularities well // if (binding instanceof GlobalVariable) { // ((GlobalVariable)binding).typeCheck(visitor, AnyItemType.getInstance()); // } if (binding != null) { recomputeInLoop(); binding.addReference(this, inLoop); } return this; }
/** * For an expression that returns an integer or a sequence of integers, get * a lower and upper bound on the values of the integers that may be returned, from * static analysis. The default implementation returns null, meaning "unknown" or * "not applicable". Other implementations return an array of two IntegerValue objects, * representing the lower and upper bounds respectively. The values * UNBOUNDED_LOWER and UNBOUNDED_UPPER are used by convention to indicate that * the value may be arbitrarily large. The values MAX_STRING_LENGTH and MAX_SEQUENCE_LENGTH * are used to indicate values limited by the size of a string or the size of a sequence. * * @return the lower and upper bounds of integer values in the result, or null to indicate * unknown or not applicable. */ @Override public IntegerValue[] getIntegerBounds() { if (binding != null) { return binding.getIntegerBoundsForVariable(); } else { return null; } }
public int getIntrinsicDependencies() { int d = 0; if (binding == null) { // assume the worst d |= (StaticProperty.DEPENDS_ON_LOCAL_VARIABLES | StaticProperty.DEPENDS_ON_ASSIGNABLE_GLOBALS); } else if (binding.isGlobal()) { if (binding.isAssignable()) { d |= StaticProperty.DEPENDS_ON_ASSIGNABLE_GLOBALS; } } else { d |= StaticProperty.DEPENDS_ON_LOCAL_VARIABLES; } return d; }
/** * 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 (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; }
private static void gatherSlotsUsed(Expression exp, IntHashSet slots) { if (exp instanceof VariableReference) { Binding binding = ((VariableReference)exp).getBinding(); if (binding == null) { throw new NullPointerException("Unbound variable at line " + exp.getLineNumber()); } if (!binding.isGlobal()) { int slot = binding.getLocalSlotNumber(); if (slot != -1) { if (!slots.contains(slot)) { slots.add(slot); } } } } else { Iterator iter = exp.iterateSubExpressions(); while (iter.hasNext()) { Expression sub = (Expression)iter.next(); gatherSlotsUsed(sub, slots); } } }
public TailCall processLeavingTail(XPathContext context) throws XPathException { if (binding==null) { throw new IllegalStateException("saxon:assign binding has not been fixed up"); } ValueRepresentation value = getSelectValue(context); if (value instanceof Closure) { value = SequenceExtent.makeSequenceExtent(((Closure)value).iterate()); } if (binding instanceof GeneralVariable) { if (binding.isGlobal()) { context.getController().getBindery().assignGlobalVariable((GlobalVariable)binding, value); } else { throw new UnsupportedOperationException("Local variables are not assignable"); } } else { } return null; }
/** * Replace this VariableReference where appropriate by a more efficient implementation. This * can only be done after all slot numbers are allocated. The efficiency is gained by binding the * VariableReference directly to a local or global slot, rather than going via the Binding object * @param parent the parent expression of this variable reference */ public void refineVariableReference(Expression parent) { if (binding instanceof Assignation || binding instanceof LocalParam || binding instanceof UserFunctionParameter) { // A LocalVariableReference can be evaluated directly, without going via the Binding object. int slot = binding.getLocalSlotNumber(); if (slot < 0) { // if slots haven't been allocated yet, we've come here too early. // See test group036 with -T option for an example. return; } LocalVariableReference ref = new LocalVariableReference(); ref.setSlotNumber(slot); ref.binding = binding; ref.staticType = staticType; ref.displayName = displayName; ExpressionTool.copyLocationInfo(this, ref); boolean found = parent.replaceSubExpression(this, ref); if (!found) { throw new IllegalStateException("Child expression not found in parent"); } } }
/** * Type-check the expression. At this stage details of the static type must be known. * If the variable has a compile-time value, this is substituted for the variable reference */ /*@NotNull*/ public Expression typeCheck(ExpressionVisitor visitor, ContextItemStaticInfo contextInfo) throws XPathException { if (constantValue != null) { binding = null; return Literal.makeLiteral(constantValue, this); } // if (staticType == null) { // throw new IllegalStateException("Variable $" + getDisplayName() + " has not been fixed up"); // } // following code removed because it causes error181 to blow the stack - need to check for circularities well // if (binding instanceof GlobalVariable) { // ((GlobalVariable)binding).typeCheck(visitor, AnyItemType.getInstance()); // } if (binding != null) { recomputeInLoop(); binding.addReference(this, inLoop); } return this; }
/** * For an expression that returns an integer or a sequence of integers, get * a lower and upper bound on the values of the integers that may be returned, from * static analysis. The default implementation returns null, meaning "unknown" or * "not applicable". Other implementations return an array of two IntegerValue objects, * representing the lower and upper bounds respectively. The values * UNBOUNDED_LOWER and UNBOUNDED_UPPER are used by convention to indicate that * the value may be arbitrarily large. The values MAX_STRING_LENGTH and MAX_SEQUENCE_LENGTH * are used to indicate values limited by the size of a string or the size of a sequence. * * @return the lower and upper bounds of integer values in the result, or null to indicate * unknown or not applicable. */ @Override public IntegerValue[] getIntegerBounds() { if (binding != null) { return binding.getIntegerBoundsForVariable(); } else { return null; } }