/** * Create a clone copy of this VariableReference * @return the cloned copy */ public Expression copy() { if (binding == null) { throw new UnsupportedOperationException("Cannot copy a variable reference whose binding is unknown"); } LocalVariableReference ref = new LocalVariableReference(); ref.binding = binding; ref.staticType = staticType; ref.slotNumber = slotNumber; ref.constantValue = constantValue; ref.displayName = displayName; ExpressionTool.copyLocationInfo(this, ref); return ref; }
/** * 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"); } } }
/** * Return the value of the variable * * @param c the XPath dynamic context * @return the value of the variable * @throws XPathException if any dynamic error occurs while evaluating the variable */ /*@NotNull*/ public Sequence<?> evaluateVariable(XPathContext c) throws XPathException { try { return c.getStackFrame().slots[slotNumber]; } catch (ArrayIndexOutOfBoundsException err) { if (slotNumber == -999) { if (binding != null) { try { slotNumber = getBinding().getLocalSlotNumber(); return c.getStackFrame().slots[slotNumber]; } catch (ArrayIndexOutOfBoundsException err2) { // fall through } } throw new ArrayIndexOutOfBoundsException("Local variable $" + getDisplayName() + " has not been allocated a stack frame slot"); } else { int actual = c.getStackFrame().slots.length; throw new ArrayIndexOutOfBoundsException("Local variable $" + getDisplayName() + " uses slot " + slotNumber + " but " + (actual == 0 ? "no" : "only " + c.getStackFrame().slots.length) + " slots" + " are allocated on the stack frame"); } } }
LocalVariableReference ref = new LocalVariableReference(getVariableName()); ref.copyFrom(this); ref.slotNumber = slotNumber; Binding newBinding = rebindings.get(binding); ref.binding = newBinding; ref.binding.addReference(ref, isInLoop()); return ref;
private static void countReferences(Binding binding, Expression exp, List<VariableReference> references, int[] results) { // results[0] = nominal reference count // results[1] = quota nodes visited if (exp instanceof LocalVariableReference) { LocalVariableReference ref = (LocalVariableReference) exp; if (ref.getBinding() == binding) { ref.recomputeInLoop(); results[0] += ref.isInLoop() ? 10 : 1; references.add((LocalVariableReference) exp); } } else if ((exp.getDependencies() & StaticProperty.DEPENDS_ON_LOCAL_VARIABLES) != 0) { if (--results[1] <= 0) { // abandon the search results[0] = 100; results[1] = 0; } else { for (Operand o : exp.operands()) { countReferences(binding, o.getChildExpression(), references, results); } } } }
LocalVariableReference var = new LocalVariableReference(let); Expression isDouble = new InstanceOfExpression( var, SequenceType.makeSequenceType(BuiltInAtomicType.DOUBLE, StaticProperty.ALLOWS_ZERO_OR_ONE)); var = new LocalVariableReference(let); Expression isDecimal = new InstanceOfExpression( var, SequenceType.makeSequenceType(BuiltInAtomicType.DECIMAL, StaticProperty.ALLOWS_ZERO_OR_ONE)); var = new LocalVariableReference(let); Expression isFloat = new InstanceOfExpression( var, SequenceType.makeSequenceType(BuiltInAtomicType.FLOAT, StaticProperty.ALLOWS_ZERO_OR_ONE)); var = new LocalVariableReference(let); Expression isString = new InstanceOfExpression( var, SequenceType.makeSequenceType(BuiltInAtomicType.STRING, StaticProperty.ALLOWS_ZERO_OR_ONE)); var = new LocalVariableReference(let); Expression isUntypedAtomic = new InstanceOfExpression( var, SequenceType.makeSequenceType(BuiltInAtomicType.UNTYPED_ATOMIC, StaticProperty.ALLOWS_ZERO_OR_ONE)); var = new LocalVariableReference(let); Expression isBoolean = new InstanceOfExpression( var, SequenceType.makeSequenceType(BuiltInAtomicType.BOOLEAN, StaticProperty.ALLOWS_ZERO_OR_ONE)); var = new LocalVariableReference(let); NumberFn fn = (NumberFn)SystemFunction.makeSystemFunction("number", new Expression[]{var}); var = new LocalVariableReference(let); var.setStaticType(SequenceType.SINGLE_ATOMIC, null, 0);
LocalVariableReference var = new LocalVariableReference(let); int properties = child.getSpecialProperties() & StaticProperty.NOT_UNTYPED_ATOMIC; var.setStaticType(type, null, properties); var.setInLoop(true); let.addReference(var, true); ExpressionTool.copyLocationInfo(child, var);
Binding binding = var.getBinding(); if (exp instanceof LocalVariableReference) { ((LocalVariableReference)var).setSlotNumber(binding.getLocalSlotNumber());
final LocalVariableReference var = new LocalVariableReference(outerLet); setLocation(var); Expression ioe = new InstanceOfExpression(var, types.get(i).get(0)); for (int j = 1; j < types.get(i).size(); j++) { ioe = new OrExpression(ioe, new InstanceOfExpression(var.copy(new RebindingMap()), types.get(i).get(j)));
public boolean includesBinding(Binding binding) { for (Operand o : operands()) { if (((LocalVariableReference)o.getChildExpression()).getBinding() == binding) { return true; } } return false; }
/** * Reset cached static properties within a subtree, meaning that they have to be * recalulated next time they are required * * @param exp the root of the subtree within which static properties should be reset */ public static void resetPropertiesWithinSubtree(Expression exp) { exp.resetLocalStaticProperties(); if (exp instanceof LocalVariableReference) { LocalVariableReference ref = (LocalVariableReference) exp; Binding binding = ref.getBinding(); if (binding instanceof Assignation) { binding.addReference(ref, ref.isInLoop()); } } for (Operand o : exp.operands()) { resetPropertiesWithinSubtree(o.getChildExpression()); o.getChildExpression().setParentExpression(exp); } }
public Tuple evaluateItem(XPathContext context) throws XPathException { final int n = getSize(); Sequence[] tuple = new Sequence[n]; for (int i=0; i<n; i++) { tuple[i] = getSlot(i).evaluateVariable(context); } return new Tuple(tuple); }
private static void gatherSlotsUsed(Expression exp, IntHashSet slots) { exp = exp.getInterpretedExpression(); if (exp instanceof LocalVariableReference) { slots.add(((LocalVariableReference)exp).getSlotNumber()); } else if (exp instanceof SuppliedParameterReference) { int slot = ((SuppliedParameterReference) exp).getSlotNumber(); slots.add(slot); } else { for (Operand o : exp.operands()) { gatherSlotsUsed(o.getChildExpression(), slots); } } }
/** * Copy an expression. This makes a deep copy. * * @return the copy of the original expression * @param rebindings */ /*@NotNull*/ public Expression copy(RebindingMap rebindings) { int n = getOperanda().getNumberOfOperands(); List<LocalVariableReference> refs2 = new ArrayList<LocalVariableReference>(n); for (int i = 0; i < n; i++) { refs2.add ((LocalVariableReference) getSlot(i).copy(rebindings)); } TupleExpression t2 = new TupleExpression(); ExpressionTool.copyLocationInfo(this, t2); t2.setVariables(refs2); return t2; }
LocalVariableReference var = new LocalVariableReference(let); Expression isDouble = new InstanceOfExpression( var, SequenceType.makeSequenceType(BuiltInAtomicType.DOUBLE, StaticProperty.ALLOWS_ZERO_OR_ONE)); var = new LocalVariableReference(let); Expression isDecimal = new InstanceOfExpression( var, SequenceType.makeSequenceType(BuiltInAtomicType.DECIMAL, StaticProperty.ALLOWS_ZERO_OR_ONE)); var = new LocalVariableReference(let); Expression isFloat = new InstanceOfExpression( var, SequenceType.makeSequenceType(BuiltInAtomicType.FLOAT, StaticProperty.ALLOWS_ZERO_OR_ONE)); var = new LocalVariableReference(let); Expression isString = new InstanceOfExpression( var, SequenceType.makeSequenceType(BuiltInAtomicType.STRING, StaticProperty.ALLOWS_ZERO_OR_ONE)); var = new LocalVariableReference(let); Expression isUntypedAtomic = new InstanceOfExpression( var, SequenceType.makeSequenceType(BuiltInAtomicType.UNTYPED_ATOMIC, StaticProperty.ALLOWS_ZERO_OR_ONE)); var = new LocalVariableReference(let); Expression isBoolean = new InstanceOfExpression( var, SequenceType.makeSequenceType(BuiltInAtomicType.BOOLEAN, StaticProperty.ALLOWS_ZERO_OR_ONE)); var = new LocalVariableReference(let); NumberFn fn = (NumberFn)SystemFunction.makeSystemFunction("number", new Expression[]{var}); var = new LocalVariableReference(let); var.setStaticType(SequenceType.SINGLE_ATOMIC, null, 0);
LocalVariableReference var = new LocalVariableReference(let); int properties = child.getSpecialProperties() & StaticProperty.NOT_UNTYPED_ATOMIC; var.setStaticType(type, null, properties); var.setInLoop(true); let.addReference(var, true); ExpressionTool.copyLocationInfo(child, var);
LocalVariableReference ref = new LocalVariableReference(getVariableName()); ref.copyFrom(this); ref.slotNumber = slotNumber; Binding newBinding = rebindings.get(binding); ref.binding = newBinding; ref.binding.addReference(ref, isInLoop()); return ref;
Binding binding = var.getBinding(); if (exp instanceof LocalVariableReference) { ((LocalVariableReference)var).setSlotNumber(binding.getLocalSlotNumber());
private static void countReferences(Binding binding, Expression exp, List<VariableReference> references, int[] results) { // results[0] = nominal reference count // results[1] = quota nodes visited if (exp instanceof LocalVariableReference) { LocalVariableReference ref = (LocalVariableReference) exp; if (ref.getBinding() == binding) { ref.recomputeInLoop(); results[0] += ref.isInLoop() ? 10 : 1; references.add((LocalVariableReference) exp); } } else if ((exp.getDependencies() & StaticProperty.DEPENDS_ON_LOCAL_VARIABLES) != 0) { if (--results[1] <= 0) { // abandon the search results[0] = 100; results[1] = 0; } else { for (Operand o : exp.operands()) { countReferences(binding, o.getChildExpression(), references, results); } } } }
final LocalVariableReference var = new LocalVariableReference(outerLet); setLocation(var); Expression ioe = new InstanceOfExpression(var, types.get(i).get(0)); for (int j = 1; j < types.get(i).size(); j++) { ioe = new OrExpression(ioe, new InstanceOfExpression(var.copy(new RebindingMap()), types.get(i).get(j)));