001: package net.sf.saxon.expr;
002:
003: import net.sf.saxon.om.NamePool;
004: import net.sf.saxon.trans.DynamicError;
005: import net.sf.saxon.trans.XPathException;
006: import net.sf.saxon.type.ItemType;
007: import net.sf.saxon.type.TypeHierarchy;
008: import net.sf.saxon.value.Value;
009:
010: import java.io.PrintStream;
011: import java.util.Iterator;
012:
013: /**
014: * Unary Expression: an expression taking a single operand expression
015: */
016:
017: public abstract class UnaryExpression extends ComputedExpression {
018:
019: protected Expression operand;
020:
021: public UnaryExpression(Expression p0) {
022: operand = p0;
023: Container parent = (p0 instanceof ComputedExpression ? ((ComputedExpression) p0)
024: .getParentExpression()
025: : null);
026: adoptChildExpression(p0);
027: setParentExpression(parent);
028: }
029:
030: public Expression getBaseExpression() {
031: return operand;
032: }
033:
034: /**
035: * Simplify an expression
036: * @return the simplified expression
037: */
038:
039: public Expression simplify(StaticContext env) throws XPathException {
040: operand = operand.simplify(env);
041: return this ;
042: }
043:
044: /**
045: * Type-check the expression. Default implementation for unary operators that accept
046: * any kind of operand
047: */
048:
049: public Expression typeCheck(StaticContext env,
050: ItemType contextItemType) throws XPathException {
051: operand = operand.typeCheck(env, contextItemType);
052: // if the operand value is known, pre-evaluate the expression
053: try {
054: if (operand instanceof Value) {
055: return ExpressionTool.eagerEvaluate(this , env
056: .makeEarlyEvaluationContext());
057: }
058: } catch (DynamicError err) {
059: // if early evaluation fails, suppress the error: the value might
060: // not be needed at run-time
061: }
062: return this ;
063: }
064:
065: /**
066: * Perform optimisation of an expression and its subexpressions.
067: * <p/>
068: * <p>This method is called after all references to functions and variables have been resolved
069: * to the declaration of the function or variable, and after all type checking has been done.</p>
070: *
071: * @param opt the optimizer in use. This provides access to supporting functions; it also allows
072: * different optimization strategies to be used in different circumstances.
073: * @param env the static context of the expression
074: * @param contextItemType the static type of "." at the point where this expression is invoked.
075: * The parameter is set to null if it is known statically that the context item will be undefined.
076: * If the type of the context item is not known statically, the argument is set to
077: * {@link net.sf.saxon.type.Type#ITEM_TYPE}
078: * @return the original expression, rewritten if appropriate to optimize execution
079: * @throws net.sf.saxon.trans.StaticError if an error is discovered during this phase
080: * (typically a type error)
081: */
082:
083: public Expression optimize(Optimizer opt, StaticContext env,
084: ItemType contextItemType) throws XPathException {
085: operand = operand.optimize(opt, env, contextItemType);
086: // if the operand value is known, pre-evaluate the expression
087: try {
088: if (operand instanceof Value) {
089: return ExpressionTool.eagerEvaluate(this , env
090: .makeEarlyEvaluationContext());
091: }
092: } catch (DynamicError err) {
093: // if early evaluation fails, suppress the error: the value might
094: // not be needed at run-time
095: }
096: return this ;
097: }
098:
099: /**
100: * Promote this expression if possible
101: */
102:
103: public Expression promote(PromotionOffer offer)
104: throws XPathException {
105: Expression exp = offer.accept(this );
106: if (exp != null) {
107: return exp;
108: } else {
109: operand = doPromotion(operand, offer);
110: return this ;
111: }
112: }
113:
114: /**
115: * Get the immediate subexpressions of this expression
116: */
117:
118: public Iterator iterateSubExpressions() {
119: return new MonoIterator(operand);
120: }
121:
122: /**
123: * Get the static properties of this expression (other than its type). The result is
124: * bit-signficant. These properties are used for optimizations. In general, if
125: * property bit is set, it is true, but if it is unset, the value is unknown.
126: */
127:
128: public int computeSpecialProperties() {
129: return operand.getSpecialProperties();
130: }
131:
132: /**
133: * Determine the static cardinality. Default implementation returns the cardinality of the operand
134: */
135:
136: public int computeCardinality() {
137: return operand.getCardinality();
138: }
139:
140: /**
141: * Determine the data type of the expression, if possible. The default
142: * implementation for unary expressions returns the item type of the operand
143: * @return the item type of the items in the result sequence, insofar as this
144: * is known statically.
145: * @param th
146: */
147:
148: public ItemType getItemType(TypeHierarchy th) {
149: return operand.getItemType(th);
150: }
151:
152: /**
153: * Is this expression the same as another expression?
154: */
155:
156: public boolean equals(Object other) {
157: return this .getClass().equals(other.getClass())
158: && this .operand
159: .equals(((UnaryExpression) other).operand);
160: }
161:
162: /**
163: * get HashCode for comparing two expressions. Note that this hashcode gives the same
164: * result for (A op B) and for (B op A), whether or not the operator is commutative.
165: */
166:
167: public int hashCode() {
168: return ("UnaryExpression " + getClass()).hashCode()
169: ^ operand.hashCode();
170: }
171:
172: /**
173: * Diagnostic print of expression structure
174: */
175:
176: public void display(int level, NamePool pool, PrintStream out) {
177: out.println(ExpressionTool.indent(level)
178: + displayOperator(pool));
179: operand.display(level + 1, pool, out);
180: }
181:
182: /**
183: * Give a string representation of the operator for use in diagnostics
184: * @return the operator, as a string
185: */
186:
187: protected abstract String displayOperator(NamePool pool);
188:
189: }
190:
191: //
192: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
193: // you may not use this file except in compliance with the License. You may obtain a copy of the
194: // License at http://www.mozilla.org/MPL/
195: //
196: // Software distributed under the License is distributed on an "AS IS" basis,
197: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
198: // See the License for the specific language governing rights and limitations under the License.
199: //
200: // The Original Code is: all this file.
201: //
202: // The Initial Developer of the Original Code is Michael H. Kay.
203: //
204: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
205: //
206: // Contributor(s): none.
207: //
|