1 package net.sf.saxon.expr; 2 import net.sf.saxon.instruct.TailCall; 3 import net.sf.saxon.instruct.TailCallReturner; 4 import net.sf.saxon.om.Item; 5 import net.sf.saxon.om.NamePool; 6 import net.sf.saxon.om.SequenceIterator; 7 import net.sf.saxon.om.ValueRepresentation; 8 import net.sf.saxon.trans.XPathException; 9 import net.sf.saxon.type.ItemType; 10 import net.sf.saxon.type.SchemaType; 11 import net.sf.saxon.value.Value; 12 13 import java.io.PrintStream ; 14 15 20 21 public class LetExpression extends Assignation implements TailCallReturner { 22 23 int refCount; 29 30 public LetExpression() {} 31 32 35 36 public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException { 37 38 if (declaration==null) { 39 return this; 41 } 42 43 47 sequence = sequence.typeCheck(env, contextItemType); 48 49 RoleLocator role = new RoleLocator(RoleLocator.VARIABLE, new Integer (nameCode), 0, env.getNamePool()); 50 role.setSourceLocator(this); 51 sequence = TypeChecker.strictTypeCheck( 52 sequence, declaration.getRequiredType(), role, env); 53 ItemType actualItemType = sequence.getItemType(); 54 declaration.refineTypeInformation(actualItemType, 55 sequence.getCardinality(), 56 (sequence instanceof Value ? (Value)sequence : null), 57 sequence.getSpecialProperties()); 58 59 action = action.typeCheck(env, contextItemType); 60 return this; 61 } 62 63 80 81 public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException { 82 if (declaration != null) { 83 refCount = declaration.getReferenceCount(this); 84 if (refCount == 0) { 85 return action; 87 } 88 declaration = null; } 90 91 int tries = 0; 92 while (tries++ < 5) { 93 Expression seq2 = sequence.optimize(opt, env, contextItemType); 94 if (seq2 == sequence) { 95 break; 96 } 97 sequence = seq2; 98 adoptChildExpression(sequence); 99 resetStaticProperties(); 100 } 101 102 tries = 0; 103 while (tries++ < 5) { 104 Expression act2 = action.optimize(opt, env, contextItemType); 105 if (act2 == action) { 106 break; 107 } 108 action = act2; 109 adoptChildExpression(action); 110 resetStaticProperties(); 111 } 112 113 115 Expression p = promoteWhereClause(null); 116 if (p != null) { 117 return p; 118 } 119 120 return this; 121 } 122 123 124 131 132 public void checkPermittedContents(SchemaType parentType, StaticContext env, boolean whole) throws XPathException { 133 action.checkPermittedContents(parentType, env, whole); 134 } 135 136 139 140 public SequenceIterator iterate(XPathContext context) throws XPathException { 141 LetExpression let = this; 143 while (true) { 144 ValueRepresentation val = let.eval(context); 145 context.setLocalVariable(let.slotNumber, val); 146 if (let.action instanceof LetExpression) { 147 let = (LetExpression)let.action; 148 } else { 149 break; 150 } 151 } 152 return let.action.iterate(context); 153 } 154 155 158 159 protected ValueRepresentation eval(XPathContext context) throws XPathException { 160 return ExpressionTool.lazyEvaluate(sequence, context, refCount); 162 } 163 164 167 168 public Item evaluateItem(XPathContext context) throws XPathException { 169 LetExpression let = this; 171 while (true) { 172 ValueRepresentation val = let.eval(context); 173 context.setLocalVariable(let.slotNumber, val); 174 if (let.action instanceof LetExpression) { 175 let = (LetExpression)let.action; 176 } else { 177 break; 178 } 179 } 180 return let.action.evaluateItem(context); 181 } 182 183 187 188 public void process(XPathContext context) throws XPathException { 189 LetExpression let = this; 191 while (true) { 192 ValueRepresentation val = let.eval(context); 193 context.setLocalVariable(let.slotNumber, val); 194 if (let.action instanceof LetExpression) { 195 let = (LetExpression)let.action; 196 } else { 197 break; 198 } 199 } 200 let.action.process(context); 201 } 202 203 204 209 210 public ItemType getItemType() { 211 return action.getItemType(); 212 } 213 214 217 218 public int computeCardinality() { 219 return action.getCardinality(); 220 } 221 222 227 228 public int computeSpecialProperties() { 229 return action.getSpecialProperties(); 230 } 231 232 235 236 public boolean markTailFunctionCalls() { 237 return ExpressionTool.markTailFunctionCalls(action); 238 } 239 240 243 244 public Expression promote(PromotionOffer offer) throws XPathException { 245 Expression exp = offer.accept(this); 246 if (exp != null) { 247 return exp; 248 } else { 249 sequence = doPromotion(sequence, offer); 251 if (offer.action == PromotionOffer.INLINE_VARIABLE_REFERENCES || 252 offer.action == PromotionOffer.UNORDERED || 253 offer.action == PromotionOffer.REPLACE_CURRENT) { 254 action = doPromotion(action, offer); 255 } else if (offer.action == PromotionOffer.RANGE_INDEPENDENT 256 ) { 258 Binding[] savedBindingList = offer.bindingList; 261 Binding[] newBindingList = new Binding[offer.bindingList.length+1]; 262 System.arraycopy(offer.bindingList, 0, newBindingList, 0, offer.bindingList.length); 263 newBindingList[offer.bindingList.length] = this; 264 offer.bindingList = newBindingList; 265 action = doPromotion(action, offer); 266 offer.bindingList = savedBindingList; 267 } 268 if (sequence instanceof VariableReference) { 272 action = replaceVariable(offer.getOptimizer(), sequence); 273 return action; 274 } 275 if (sequence instanceof LazyExpression && 277 ((LazyExpression)sequence).getBaseExpression() instanceof VariableReference) { 278 action = replaceVariable(offer.getOptimizer(), ((LazyExpression)sequence).getBaseExpression()); 279 return action; 280 } 281 282 return this; 283 } 284 } 285 286 private Expression replaceVariable(Optimizer opt, Expression seq) throws XPathException { 287 PromotionOffer offer2 = new PromotionOffer(opt); 288 offer2.action = PromotionOffer.INLINE_VARIABLE_REFERENCES; 289 Binding[] bindingList = {this}; 290 offer2.bindingList = bindingList; 291 offer2.containingExpression = seq; 292 Expression newAction = doPromotion(action, offer2); 293 return newAction; 294 } 295 296 307 308 public TailCall processLeavingTail(XPathContext context) throws XPathException { 309 LetExpression let = this; 311 while (true) { 312 ValueRepresentation val = let.eval(context); 313 context.setLocalVariable(let.slotNumber, val); 314 if (let.action instanceof LetExpression) { 315 let = (LetExpression)let.action; 316 } else { 317 break; 318 } 319 } 320 if (let.action instanceof TailCallReturner) { 321 return ((TailCallReturner)let.action).processLeavingTail(context); 322 } else { 323 let.action.process(context); 324 return null; 325 } 326 } 327 328 331 332 public void display(int level, NamePool pool, PrintStream out) { 333 out.println(ExpressionTool.indent(level) + "let $" + getVariableName(pool) + 334 "[refCount=" + refCount + "] :="); 335 sequence.display(level+1, pool, out); 336 out.println(ExpressionTool.indent(level) + "return"); 337 action.display(level+1, pool, out); 338 } 339 340 } 341 342 343 344 | Popular Tags |