1 package net.sf.saxon.value; 2 import net.sf.saxon.event.SequenceReceiver; 3 import net.sf.saxon.expr.*; 4 import net.sf.saxon.om.*; 5 import net.sf.saxon.trace.Location; 6 import net.sf.saxon.trans.XPathException; 7 import net.sf.saxon.type.ItemType; 8 import net.sf.saxon.type.AnyItemType; 9 10 import java.io.PrintStream ; 11 12 32 33 public class Closure extends Value { 34 35 protected Expression expression; 36 protected XPathContextMajor savedXPathContext; 37 protected int depth = 0; 38 39 43 protected SequenceIterator inputIterator; 44 45 48 51 52 public Closure() { 53 } 54 55 62 63 public static Closure makeIteratorClosure(SequenceIterator iterator) { 64 Closure c = new Closure(); 65 c.inputIterator = iterator; 66 return c; 67 } 68 69 72 73 public static Value make(Expression expression, XPathContext context, int ref) throws XPathException { 74 75 77 if (expression instanceof ErrorExpression) { 78 expression.evaluateItem(context); return null; } 81 82 87 if (expression instanceof TailExpression) { 88 TailExpression tail = (TailExpression)expression; 89 Expression base = tail.getBaseExpression(); 90 if (base instanceof VariableReference) { 91 base = Value.asValue(ExpressionTool.lazyEvaluate(base, context, ref)); 92 if (base instanceof MemoClosure) { 93 SequenceIterator it = base.iterate(null); 94 base = ((GroundedIterator)it).materialize(); 95 } 96 if (base instanceof IntegerRange) { 97 long start = ((IntegerRange)base).getStart() + 1; 98 long end = ((IntegerRange)base).getEnd(); 99 if (start == end) { 100 return new IntegerValue(end); 101 } else { 102 return new IntegerRange(start, end); 103 } 104 } 105 if (base instanceof SequenceExtent) { 106 return new SequenceExtent( 107 (SequenceExtent)base, 108 tail.getStart() - 1, 109 ((SequenceExtent)base).getLength() - tail.getStart() + 1); 110 } 111 } 112 } 113 114 Closure c = context.getController().getConfiguration().getOptimizer().makeClosure(expression, ref); 115 c.expression = expression; 124 c.savedXPathContext = context.newContext(); 125 c.savedXPathContext.setOriginatingConstructType(Location.LAZY_EVALUATION); 126 127 131 134 if (expression instanceof ComputedExpression && 135 (expression.getDependencies() & StaticProperty.DEPENDS_ON_LOCAL_VARIABLES) != 0) { 136 StackFrame localStackFrame = context.getStackFrame(); 137 ValueRepresentation[] local = localStackFrame.getStackFrameValues(); 138 int[] slotsUsed = ((ComputedExpression)expression).getSlotsUsed(); 139 if (local != null) { 140 ValueRepresentation[] savedStackFrame = new ValueRepresentation[local.length]; 141 for (int s=0; s<slotsUsed.length; s++) { 142 int i = slotsUsed[s]; 143 if (local[i] instanceof Closure) { 144 int cdepth = ((Closure)local[i]).depth; 145 if (cdepth >= 10) { 146 local[i] = ExpressionTool.eagerEvaluate((Closure)local[i], context); 147 } else if (cdepth + 1 > c.depth) { 148 c.depth = cdepth + 1; 149 } 150 } 151 savedStackFrame[i] = local[i]; 152 } 153 154 c.savedXPathContext.setStackFrame(localStackFrame.getStackFrameMap(), savedStackFrame); 155 } 156 } 157 158 SequenceIterator currentIterator = context.getCurrentIterator(); 160 if (currentIterator != null) { 161 Item contextItem = currentIterator.current(); 162 AxisIterator single = SingletonIterator.makeIterator(contextItem); 163 single.next(); 164 c.savedXPathContext.setCurrentIterator(single); 165 } 169 170 c.savedXPathContext.setReceiver(null); 171 return c; 172 } 173 174 177 178 public ItemType getItemType() { 179 if (expression == null) { 180 return AnyItemType.getInstance(); 181 } else { 182 return expression.getItemType(); 183 } 184 } 186 187 190 191 public int getCardinality() { 192 if (expression == null) { 193 return StaticProperty.ALLOWS_ZERO_OR_MORE; 194 } else { 195 return expression.getCardinality(); 196 } 197 } 198 199 204 205 public int getSpecialProperties() { 206 if (expression == null) { 207 return StaticProperty.ALLOWS_ZERO_OR_MORE; 208 } else { 209 return expression.getSpecialProperties(); 210 } 211 } 212 213 218 219 public int getImplementationMethod() { 220 return ITERATE_METHOD | PROCESS_METHOD; 221 } 222 223 228 229 public SequenceIterator iterate(XPathContext context) throws XPathException { 230 231 if (inputIterator == null) { 232 inputIterator = expression.iterate(savedXPathContext); 233 return inputIterator; 234 } else { 235 return inputIterator.getAnother(); 242 } 243 244 } 245 246 251 252 public void process(XPathContext context) throws XPathException { 253 XPathContext c2 = savedXPathContext.newContext(); 256 SequenceReceiver out = context.getReceiver(); 257 c2.setTemporaryReceiver(out); 258 expression.process(c2); 259 } 260 261 267 268 public Value reduce() throws XPathException { 269 return new SequenceExtent(iterate(null)).reduce(); 270 } 271 272 275 276 public boolean isIndexable() { 277 return false; 278 } 279 280 public void display(int level, NamePool pool, PrintStream out) { 281 out.println(ExpressionTool.indent(level) + "Closure of expression:"); 282 expression.display(level+1, pool, out); 283 } 284 285 } 286 287 | Popular Tags |