package client.net.sf.saxon.ce.expr;
import client.net.sf.saxon.ce.trans.XPathException;
import client.net.sf.saxon.ce.type.ItemType;
import client.net.sf.saxon.ce.type.TypeHierarchy;
import client.net.sf.saxon.ce.value.SequenceExtent;
import client.net.sf.saxon.ce.value.Value;
import java.util.Iterator;
/**
* Unary Expression: an expression taking a single operand expression
*/
public abstract class UnaryExpression extends Expression {
protected Expression operand;
protected UnaryExpression() {}
public UnaryExpression(Expression p0) {
operand = p0;
adoptChildExpression(p0);
}
public Expression getBaseExpression() {
return operand;
}
/**
* Simplify an expression
* @return the simplified expression
* @param visitor an expression visitor
*/
public Expression simplify(ExpressionVisitor visitor) throws XPathException {
operand = visitor.simplify(operand);
return this;
}
/**
* Type-check the expression. Default implementation for unary operators that accept
* any kind of operand
*/
public Expression typeCheck(ExpressionVisitor visitor, ItemType contextItemType) throws XPathException {
operand = visitor.typeCheck(operand, contextItemType);
// if the operand value is known, pre-evaluate the expression
try {
if (operand instanceof Literal) {
return Literal.makeLiteral(Value.asValue(
SequenceExtent.makeSequenceExtent(
iterate(visitor.getStaticContext().makeEarlyEvaluationContext()))));
}
//return (Value)ExpressionTool.eagerEvaluate(this, env.makeEarlyEvaluationContext());
} catch (XPathException err) {
// if early evaluation fails, suppress the error: the value might
// not be needed at run-time
}
return this;
}
/**
* Perform optimisation of an expression and its subexpressions.
* <p/>
* <p>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.</p>
*
* @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 client.net.sf.saxon.ce.type.Type#ITEM_TYPE}
* @return the original expression, rewritten if appropriate to optimize execution
* @throws XPathException if an error is discovered during this phase
* (typically a type error)
*/
public Expression optimize(ExpressionVisitor visitor, ItemType contextItemType) throws XPathException {
operand = visitor.optimize(operand, contextItemType);
// if the operand value is known, pre-evaluate the expression
try {
if (operand instanceof Literal) {
return Literal.makeLiteral(Value.asValue(
SequenceExtent.makeSequenceExtent(
iterate(visitor.getStaticContext().makeEarlyEvaluationContext()))));
}
} catch (XPathException err) {
// if early evaluation fails, suppress the error: the value might
// not be needed at run-time
}
return this;
}
/**
* Promote this expression if possible
*/
public Expression promote(PromotionOffer offer, Expression parent) throws XPathException {
Expression exp = offer.accept(parent, this);
if (exp != null) {
return exp;
} else {
operand = doPromotion(operand, offer);
return this;
}
}
/**
* Get the immediate subexpressions of this expression
*/
public Iterator<Expression> iterateSubExpressions() {
return monoIterator(operand);
}
/**
* 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) {
boolean found = false;
if (operand == original) {
operand = replacement;
found = true;
}
return found;
}
/**
* 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() {
return operand.getSpecialProperties();
}
/**
* Determine the static cardinality. Default implementation returns the cardinality of the operand
*/
public int computeCardinality() {
return operand.getCardinality();
}
/**
* Determine the data type of the expression, if possible. The default
* implementation for unary expressions returns the item type of the operand
* @return the item type of the items in the result sequence, insofar as this
* is known statically.
* @param th the type hierarchy cache
*/
public ItemType getItemType(TypeHierarchy th) {
return operand.getItemType(th);
}
/**
* Is this expression the same as another expression?
*/
public boolean equals(Object other) {
return other != null && this.getClass().equals(other.getClass()) &&
this.operand.equals(((UnaryExpression)other).operand);
}
/**
* get HashCode for comparing two expressions. Note that this hashcode gives the same
* result for (A op B) and for (B op A), whether or not the operator is commutative.
*/
public int hashCode() {
return ("UnaryExpression " + getClass()).hashCode() ^ operand.hashCode();
}
/**
* 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
*/
public String toString() {
return getClass().getName() + "(" + operand.toString() + ")";
}
}
// 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.