@Override public void resetLocalStaticProperties() { super.resetLocalStaticProperties(); references = new ArrayList<>(); // bug 3233 if (evaluator == Evaluator.VARIABLE && !(getSequence() instanceof VariableReference)) { evaluator = null; setEvaluator(); } }
/** * Type-check the expression. This also has the side-effect of counting the number of references * to the variable (treating references that occur within a loop specially) */ /*@NotNull*/ public Expression typeCheck(ExpressionVisitor visitor, ContextItemStaticInfo contextInfo) throws XPathException { // The order of events is critical here. First we ensure that the type of the // sequence expression is established. This is used to establish the type of the variable, // which in turn is required when type-checking the action part. getSequenceOp().typeCheck(visitor, contextInfo); RoleDiagnostic role = new RoleDiagnostic(RoleDiagnostic.VARIABLE, getVariableQName().getDisplayName(), 0); //role.setSourceLocator(this); setSequence(TypeChecker.strictTypeCheck( getSequence(), requiredType, role, visitor.getStaticContext())); final ItemType actualItemType = getSequence().getItemType(); refineTypeInformation(actualItemType, getSequence().getCardinality(), getSequence() instanceof Literal ? ((Literal) getSequence()).getValue() : null, getSequence().getSpecialProperties(), this); getActionOp().typeCheck(visitor, contextInfo); return this; }
@Override public void resetLocalStaticProperties() { super.resetLocalStaticProperties(); references = new ArrayList<>(); // bug 3233 if (evaluator == Evaluator.VARIABLE && !(getSequence() instanceof VariableReference)) { evaluator = null; setEvaluator(); } }
/** * Type-check the expression. This also has the side-effect of counting the number of references * to the variable (treating references that occur within a loop specially) */ /*@NotNull*/ public Expression typeCheck(ExpressionVisitor visitor, ContextItemStaticInfo contextInfo) throws XPathException { // The order of events is critical here. First we ensure that the type of the // sequence expression is established. This is used to establish the type of the variable, // which in turn is required when type-checking the action part. getSequenceOp().typeCheck(visitor, contextInfo); RoleDiagnostic role = new RoleDiagnostic(RoleDiagnostic.VARIABLE, getVariableQName().getDisplayName(), 0); //role.setSourceLocator(this); setSequence(TypeChecker.strictTypeCheck( getSequence(), requiredType, role, visitor.getStaticContext())); final ItemType actualItemType = getSequence().getItemType(); refineTypeInformation(actualItemType, getSequence().getCardinality(), getSequence() instanceof Literal ? ((Literal) getSequence()).getValue() : null, getSequence().getSpecialProperties(), this); getActionOp().typeCheck(visitor, contextInfo); return this; }
/** * The toString() method for an expression attempts to give a representation of the expression * in an XPath-like form, but there is no guarantee that the syntax will actually be true XPath. * In the case of XSLT instructions, the toString() method gives an abstracted view of the syntax * * @return a representation of the expression as a string */ public String toString() { return "let $" + getVariableEQName() + " := " + getSequence() + " return " + ExpressionTool.parenthesize(getAction()); }
/** * 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() + getAction().getCost(); }
/** * 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() + getAction().getCost(); }
/** * The toString() method for an expression attempts to give a representation of the expression * in an XPath-like form, but there is no guarantee that the syntax will actually be true XPath. * In the case of XSLT instructions, the toString() method gives an abstracted view of the syntax * * @return a representation of the expression as a string */ public String toString() { return "let $" + getVariableEQName() + " := " + getSequence() + " return " + ExpressionTool.parenthesize(getAction()); }
/** * 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. */ public int computeSpecialProperties() { int props = getAction().getSpecialProperties(); int seqProps = getSequence().getSpecialProperties(); if ((seqProps & StaticProperty.NO_NODES_NEWLY_CREATED) == 0) { props &= ~StaticProperty.NO_NODES_NEWLY_CREATED; } return props; }
/** * 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. */ public int computeSpecialProperties() { int props = getAction().getSpecialProperties(); int seqProps = getSequence().getSpecialProperties(); if ((seqProps & StaticProperty.NO_NODES_NEWLY_CREATED) == 0) { props &= ~StaticProperty.NO_NODES_NEWLY_CREATED; } return props; }
public void setEvaluator() { if (needsEagerEvaluation) { setEvaluator(ExpressionTool.eagerEvaluator(getSequence())); } else if (isIndexedVariable()) { setEvaluator(Evaluator.MAKE_INDEXED_VARIABLE); } else if (evaluator == null) { setEvaluator(ExpressionTool.lazyEvaluator(getSequence(), getNominalReferenceCount() > 1)); } }
public void setEvaluator() { if (needsEagerEvaluation) { setEvaluator(ExpressionTool.eagerEvaluator(getSequence())); } else if (isIndexedVariable()) { setEvaluator(Evaluator.MAKE_INDEXED_VARIABLE); } else if (evaluator == null) { setEvaluator(ExpressionTool.lazyEvaluator(getSequence(), getNominalReferenceCount() > 1)); } }
private void inlineReferences() { // Note that the list of references might include references that are no longer reachable on the tree. // We therefore take no action if (a) the parent of the reference is null, or (b) the reference is // not found among the children of its parent. for (VariableReference ref : references) { Expression parent = ref.getParentExpression(); if (parent != null) { Operand o = ExpressionTool.findOperand(parent, ref); if (o != null) { o.setChildExpression(getSequence().copy(new RebindingMap())); } ExpressionTool.resetStaticProperties(parent); } } }
private void inlineReferences() { // Note that the list of references might include references that are no longer reachable on the tree. // We therefore take no action if (a) the parent of the reference is null, or (b) the reference is // not found among the children of its parent. for (VariableReference ref : references) { Expression parent = ref.getParentExpression(); if (parent != null) { Operand o = ExpressionTool.findOperand(parent, ref); if (o != null) { o.setChildExpression(getSequence().copy(new RebindingMap())); } ExpressionTool.resetStaticProperties(parent); } } }
/** * Diagnostic print of expression structure. The abstract expression tree * is written to the supplied output destination. */ public void export(ExpressionPresenter out) throws XPathException { out.startElement("let", this); out.emitAttribute("var", variableName); out.emitAttribute("as", getSequence().getStaticType().toExportString()); ExpressionPresenter.ExportOptions options = (ExpressionPresenter.ExportOptions) out.getOptions(); if (options.target.equals("JS") && options.targetVersion == 2) { out.emitAttribute("asJ", getSequence().getStaticType().toExportString2()); } if (isIndexedVariable()) { out.emitAttribute("indexable", "true"); } out.emitAttribute("slot", getLocalSlotNumber() + ""); if (evaluator == null) { setEvaluator(ExpressionTool.lazyEvaluator(getSequence(), getNominalReferenceCount() > 1)); } out.emitAttribute("eval", getEvaluator().getCode() + ""); getSequence().export(out); getAction().export(out); out.endElement(); }
/** * Diagnostic print of expression structure. The abstract expression tree * is written to the supplied output destination. */ public void export(ExpressionPresenter out) throws XPathException { out.startElement("let", this); out.emitAttribute("var", variableName); out.emitAttribute("as", getSequence().getStaticType().toExportString()); if (isIndexedVariable()) { out.emitAttribute("indexable", "true"); } out.emitAttribute("slot", getLocalSlotNumber() + ""); if (evaluator == null) { setEvaluator(ExpressionTool.lazyEvaluator(getSequence(), getNominalReferenceCount() > 1)); } out.emitAttribute("eval", getEvaluator().getCode() + ""); getSequence().export(out); getAction().export(out); out.endElement(); }
/** * Determine whether multiple occurrences are not only allowed, but likely. * This returns false for an expression that is the atomization of a singleton * node, since in that case it's quite unusual for the typed value to be a * non-singleton sequence. * * @param expression an expression * @return true if multiple occurrences are not only allowed, but likely. Return * false if multiple occurrences are unlikely, even though they might be allowed. * This is typically the case for the atomized sequence that is obtained by atomizing * a singleton node. */ public static boolean expectsMany(Expression expression) { if (expression instanceof VariableReference) { Binding b = ((VariableReference) expression).getBinding(); if (b instanceof LetExpression) { return expectsMany(((LetExpression) b).getSequence()); } } if (expression instanceof Atomizer) { return expectsMany(((Atomizer) expression).getBaseExpression()); } if (expression instanceof FilterExpression) { return expectsMany(((FilterExpression) expression).getSelectExpression()); } return allowsMany(expression.getCardinality()); }
public AbstractExpression exprFor (LetExpression let) { StructuredQName var = let.getVariableQName(); Expression seq = let.getSequence(); Expression returns = let.getAction(); return new FLWOR(exprFor(returns), new LetClause (new Variable(qnameFor(var), getTypeDescription(let.getRequiredType())), exprFor(seq))); }
/** * Copy an expression. This makes a deep copy. * * @return the copy of the original expression * @param rebindings variables whose binding needs to change */ /*@NotNull*/ public Expression copy(RebindingMap rebindings) { LetExpression let = new LetExpression(); ExpressionTool.copyLocationInfo(this, let); let.isIndexedVariable = isIndexedVariable; let.hasLoopingReference = hasLoopingReference; let.setNeedsEagerEvaluation(needsEagerEvaluation); let.setNeedsLazyEvaluation(needsLazyEvaluation); let.setVariableQName(variableName); let.setRequiredType(requiredType); let.setSequence(getSequence().copy(rebindings)); let.setInstruction(isInstruction()); Expression newAction = getAction().copy(rebindings); let.setAction(newAction); ExpressionTool.rebindVariableReferences(newAction, this, let); return let; }
/** * Copy an expression. This makes a deep copy. * * @return the copy of the original expression * @param rebindings variables whose binding needs to change */ /*@NotNull*/ public Expression copy(RebindingMap rebindings) { LetExpression let = new LetExpression(); ExpressionTool.copyLocationInfo(this, let); let.isIndexedVariable = isIndexedVariable; let.hasLoopingReference = hasLoopingReference; let.setNeedsEagerEvaluation(needsEagerEvaluation); let.setNeedsLazyEvaluation(needsLazyEvaluation); let.setVariableQName(variableName); let.setRequiredType(requiredType); let.setSequence(getSequence().copy(rebindings)); let.setInstruction(isInstruction()); Expression newAction = getAction().copy(rebindings); let.setAction(newAction); ExpressionTool.rebindVariableReferences(newAction, this, let); return let; }