1 /*
2 * Copyright 2006-2008 The FLWOR Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "stdafx.h"
17
18 #include "compiler/rewriter/tools/expr_tools.h"
19 #include "compiler/rewriter/framework/rewriter_context.h"
20 #include "compiler/expression/flwor_expr.h"
21 #include "compiler/expression/expr.h"
22 #include "compiler/expression/path_expr.h"
23 #include "compiler/expression/ft_expr.h"
24 #include "compiler/expression/ftnode.h"
25 #include "compiler/expression/expr_iter.h"
26
27 #include "functions/func_errors_and_diagnostics.h"
28
29 #include "types/typeops.h"
30
31 #include <iterator>
32
33 namespace zorba
34 {
35
36 namespace expr_tools
37 {
38
39 static void add_wincond_vars(const flwor_wincond*, ulong&, VarIdMap&, IdVarMap*);
40
41 static void add_var(var_expr*, ulong&, VarIdMap&, IdVarMap*);
42
43 static void remove_wincond_vars(const flwor_wincond*, const VarIdMap&, DynamicBitset&);
44
45 static void set_bit(var_expr*, const VarIdMap&, DynamicBitset&, bool);
46
47
48 /*******************************************************************************
49
50 ********************************************************************************/
count_variable_uses_rec(const expr * e,const var_expr * var,int limit,int & count)51 bool count_variable_uses_rec(
52 const expr* e,
53 const var_expr* var,
54 int limit,
55 int& count)
56 {
57 if (limit > 0 && count >= limit)
58 {
59 return false;
60 }
61
62 if (e == var)
63 {
64 ++count;
65 return true;
66 }
67
68 if (e->get_expr_kind() == if_expr_kind)
69 {
70 const if_expr* ifExpr = static_cast<const if_expr*>(e);
71
72 int thenCount = 0;
73 int elseCount = 0;
74
75 if (!count_variable_uses_rec(ifExpr->get_cond_expr(), var, limit, count))
76 return false;
77
78 if (!count_variable_uses_rec(ifExpr->get_then_expr(), var, limit, thenCount))
79 {
80 count = thenCount;
81 return false;
82 }
83
84 if (!count_variable_uses_rec(ifExpr->get_else_expr(), var, limit, elseCount))
85 {
86 count = elseCount;
87 return false;
88 }
89
90 count += (thenCount > elseCount ? thenCount : elseCount);
91 }
92 else
93 {
94 ExprConstIterator iter(e);
95 while (!iter.done())
96 {
97 if (!count_variable_uses_rec(iter.get_expr(), var, limit, count))
98 return false;
99
100 iter.next();
101 }
102 }
103
104 return true;
105 }
106
107
108 /*******************************************************************************
109
110 ********************************************************************************/
count_variable_uses(const expr * root,const var_expr * var,int limit=0)111 int count_variable_uses(const expr* root, const var_expr* var, int limit = 0)
112 {
113 int count = 0;
114
115 count_variable_uses_rec(root, var, limit, count);
116
117 return count;
118 }
119
120
121 /*******************************************************************************
122 copy annotations when wrapping an expression in a new one
123 ********************************************************************************/
fix_annotations(expr * new_expr,const expr * old_expr)124 expr* fix_annotations(expr* new_expr, const expr* old_expr)
125 {
126 if (old_expr == NULL)
127 {
128 switch (new_expr->get_expr_kind())
129 {
130 case fo_expr_kind:
131 old_expr = static_cast<const fo_expr*>(new_expr)->get_arg(0);
132 break;
133 default:
134 assert(false);
135 return NULL;
136 }
137 }
138
139 const expr::FreeVars& old_set = old_expr->getFreeVars();
140 const expr::FreeVars& new_set = new_expr->getFreeVars();
141
142 expr::FreeVars s;
143 std::set_union(old_set.begin(),
144 old_set.end(),
145 new_set.begin(),
146 new_set.end(),
147 inserter(s, s.begin()));
148
149 new_expr->setFreeVars(s);
150
151 return new_expr;
152 }
153
154
155
156 /*******************************************************************************
157 Replace all references to "oldVar" inside "e" with references to "newVar".
158 ********************************************************************************/
replace_var(expr * e,const var_expr * oldVar,var_expr * newVar)159 void replace_var(expr* e, const var_expr* oldVar, var_expr* newVar)
160 {
161 if (e->get_expr_kind() == wrapper_expr_kind)
162 {
163 wrapper_expr* wrapper = reinterpret_cast<wrapper_expr*>(e);
164
165 if (wrapper->get_expr() == oldVar)
166 {
167 wrapper->set_expr(newVar);
168 return;
169 }
170 }
171
172 ExprIterator iter(e);
173 while (!iter.done())
174 {
175 replace_var((**iter), oldVar, newVar);
176 iter.next();
177 }
178 }
179
180
181 /////////////////////////////////////////////////////////////////////////////////
182 // //
183 // //
184 // //
185 /////////////////////////////////////////////////////////////////////////////////
186
187
188 /*******************************************************************************
189 Let FLWOR(e) be the set of flwor exprs within the expr tree rooted at expr e.
190 Let FV(e) be the set of variables defined in any of the flwor exprs in FLWOR(e).
191 This method assigns a prefix id to each variable in FV(e) and stores the mapping
192 between var_expr and prefix id in "varmap". It also returns the number of vars
193 in FV(e).
194
195 Given 2 vars v1 and v2 in FV(e), their prefix ids allows to check if v1 is
196 defined before v2: v1 is defined before v2 iff id(v1) < id(v2).
197 ********************************************************************************/
index_flwor_vars(const expr * e,ulong & numVars,VarIdMap & varidmap,IdVarMap * idvarmap)198 void index_flwor_vars(
199 const expr* e,
200 ulong& numVars,
201 VarIdMap& varidmap,
202 IdVarMap* idvarmap)
203 {
204 if (e->get_expr_kind() == flwor_expr_kind ||
205 e->get_expr_kind() == gflwor_expr_kind)
206 {
207 const flwor_expr* flwor = static_cast<const flwor_expr *>(e);
208
209 for (flwor_expr::clause_list_t::const_iterator i = flwor->clause_begin();
210 i != flwor->clause_end();
211 ++i)
212 {
213 const flwor_clause* c = *i;
214
215 if (c->get_kind() == flwor_clause::for_clause)
216 {
217 const for_clause* fc = static_cast<const for_clause *>(c);
218
219 add_var(fc->get_var(), numVars, varidmap, idvarmap);
220 add_var(fc->get_pos_var(), numVars, varidmap, idvarmap);
221 add_var(fc->get_score_var(), numVars, varidmap, idvarmap);
222
223 index_flwor_vars(fc->get_expr(), numVars, varidmap, idvarmap);
224 }
225 else if (c->get_kind() == flwor_clause::let_clause)
226 {
227 const let_clause* lc = static_cast<const let_clause *>(c);
228
229 add_var(lc->get_var(), numVars, varidmap, idvarmap);
230 add_var(lc->get_score_var(), numVars, varidmap, idvarmap);
231
232 index_flwor_vars(lc->get_expr(), numVars, varidmap, idvarmap);
233 }
234 else if (c->get_kind() == flwor_clause::window_clause)
235 {
236 const window_clause* wc = static_cast<const window_clause *>(c);
237
238 add_var(wc->get_var(), numVars, varidmap, idvarmap);
239
240 index_flwor_vars(wc->get_expr(), numVars, varidmap, idvarmap);
241
242 flwor_wincond* startCond = wc->get_win_start();
243 flwor_wincond* stopCond = wc->get_win_stop();
244
245 if (startCond != NULL)
246 add_wincond_vars(startCond, numVars, varidmap, idvarmap);
247
248 if (stopCond != NULL)
249 add_wincond_vars(stopCond, numVars, varidmap, idvarmap);
250 }
251 else if (c->get_kind() == flwor_clause::group_clause)
252 {
253 const group_clause* gc = static_cast<const group_clause *>(c);
254
255 const flwor_clause::rebind_list_t& gvars = gc->get_grouping_vars();
256 csize numGroupVars = gvars.size();
257
258 for (csize i = 0; i < numGroupVars; ++i)
259 {
260 add_var(gvars[i].second, numVars, varidmap, idvarmap);
261 }
262
263 const flwor_clause::rebind_list_t& ngvars = gc->get_nongrouping_vars();
264 csize numNonGroupVars = ngvars.size();
265
266 for (csize i = 0; i < numNonGroupVars; ++i)
267 {
268 add_var(ngvars[i].second, numVars, varidmap, idvarmap);
269 }
270 }
271 else if (c->get_kind() == flwor_clause::count_clause)
272 {
273 const count_clause* cc = static_cast<const count_clause *>(c);
274
275 add_var(cc->get_var(), numVars, varidmap, idvarmap);
276 }
277 else if (c->get_kind() == flwor_clause::where_clause)
278 {
279 const where_clause* wc = static_cast<const where_clause *>(c);
280
281 index_flwor_vars(wc->get_expr(), numVars, varidmap, idvarmap);
282 }
283 else if (c->get_kind() == flwor_clause::order_clause)
284 {
285 const orderby_clause* obc = static_cast<const orderby_clause *>(c);
286 csize numExprs = obc->num_columns();
287 for (csize i = 0; i < numExprs; ++i)
288 {
289 index_flwor_vars(obc->get_column_expr(i), numVars, varidmap, idvarmap);
290 }
291 }
292 }
293
294 index_flwor_vars(flwor->get_return_expr(), numVars, varidmap, idvarmap);
295 }
296 else if (e->get_expr_kind() == trycatch_expr_kind)
297 {
298 const trycatch_expr* trycatch = static_cast<const trycatch_expr*>(e);
299
300 index_flwor_vars(trycatch->get_try_expr(), numVars, varidmap, idvarmap);
301
302 csize numClauses = trycatch->clause_count();
303
304 for (csize i = 0; i < numClauses; ++i)
305 {
306 const catch_clause* clause = (*trycatch)[i];
307
308 catch_clause::var_map_t& trycatchVars =
309 const_cast<catch_clause*>(clause)->get_vars();
310
311 catch_clause::var_map_t::const_iterator ite = trycatchVars.begin();
312 catch_clause::var_map_t::const_iterator end = trycatchVars.end();
313 for (; ite != end; ++ite)
314 {
315 var_expr* trycatchVar = (*ite).second;
316 add_var(trycatchVar, numVars, varidmap, idvarmap);
317 }
318
319 index_flwor_vars(trycatch->get_catch_expr(i), numVars, varidmap, idvarmap);
320 }
321 }
322 else
323 {
324 ExprConstIterator iter(e);
325 while(!iter.done())
326 {
327 const expr* ce = iter.get_expr();
328 if (ce)
329 {
330 index_flwor_vars(ce, numVars, varidmap, idvarmap);
331 }
332 iter.next();
333 }
334 }
335 }
336
337
338 /*******************************************************************************
339
340 ********************************************************************************/
add_wincond_vars(const flwor_wincond * cond,ulong & numVars,VarIdMap & varidmap,IdVarMap * idvarmap)341 static void add_wincond_vars(
342 const flwor_wincond* cond,
343 ulong& numVars,
344 VarIdMap& varidmap,
345 IdVarMap* idvarmap)
346 {
347 const flwor_wincond::vars& inVars = cond->get_in_vars();
348 const flwor_wincond::vars& outVars = cond->get_out_vars();
349
350 add_var(inVars.posvar, numVars, varidmap, idvarmap);
351 add_var(inVars.curr, numVars, varidmap, idvarmap);
352 add_var(inVars.prev, numVars, varidmap, idvarmap);
353 add_var(inVars.next, numVars, varidmap, idvarmap);
354
355 index_flwor_vars(cond->get_cond(), numVars, varidmap, idvarmap);
356
357 add_var(outVars.posvar, numVars, varidmap, idvarmap);
358 add_var(outVars.curr, numVars, varidmap, idvarmap);
359 add_var(outVars.prev, numVars, varidmap, idvarmap);
360 add_var(outVars.next, numVars, varidmap, idvarmap);
361 }
362
363
364 /*******************************************************************************
365
366 ********************************************************************************/
add_var(var_expr * v,ulong & numVars,VarIdMap & varidmap,IdVarMap * idvarmap)367 static void add_var(
368 var_expr* v,
369 ulong& numVars,
370 VarIdMap& varidmap,
371 IdVarMap* idvarmap)
372 {
373 if (v != NULL)
374 {
375 varidmap[v] = numVars++;
376 if (idvarmap)
377 idvarmap->push_back(v);
378 }
379 }
380
381
382 /*******************************************************************************
383 For each expr E in the expr tree rooted at "e", this method computes the set
384 of variables that belong to FV(e) and are referenced by E. Let V(E) be this
385 set. V(E) is implemented as a bitset ("freeset") whose size is equal to the
386 size of FV(e) and whose i-th bit is on iff the var with prefix id i belongs
387 to V(E). The mapping between E and V(E) is stored in "freevarMap".
388 ********************************************************************************/
build_expr_to_vars_map(expr * e,const VarIdMap & varmap,DynamicBitset & freeset,ExprVarsMap & freevarMap)389 void build_expr_to_vars_map(
390 expr* e,
391 const VarIdMap& varmap,
392 DynamicBitset& freeset,
393 ExprVarsMap& freevarMap)
394 {
395 if (e->get_expr_kind() == var_expr_kind)
396 {
397 set_bit(static_cast<var_expr *>(e), varmap, freeset, true);
398 freevarMap[e] = freeset;
399 return;
400 }
401
402 csize numVars = freeset.size();
403
404 DynamicBitset eFreeset(numVars);
405 ExprIterator iter(e);
406 while(!iter.done())
407 {
408 expr* ce = **iter;
409 if (ce)
410 {
411 eFreeset.reset();
412 build_expr_to_vars_map(ce, varmap, eFreeset, freevarMap);
413 freeset.set_union(eFreeset);
414 }
415 iter.next();
416 }
417
418 // A flwor does not depend on the vars that are defined inside the flwor itself,
419 // so remove these vars from the freeset of the flwor, if they have been added
420 // there.
421 if (e->get_expr_kind() == flwor_expr_kind ||
422 e->get_expr_kind() == gflwor_expr_kind)
423 {
424 flwor_expr* flwor = static_cast<flwor_expr *>(e);
425
426 for(flwor_expr::clause_list_t::const_iterator i = flwor->clause_begin();
427 i != flwor->clause_end();
428 ++i)
429 {
430 const flwor_clause* c = *i;
431
432 if (c->get_kind() == flwor_clause::for_clause)
433 {
434 const for_clause* fc = static_cast<const for_clause *>(c);
435
436 set_bit(fc->get_var(), varmap, freeset, false);
437 set_bit(fc->get_pos_var(), varmap, freeset, false);
438 set_bit(fc->get_score_var(), varmap, freeset, false);
439 }
440 else if (c->get_kind() == flwor_clause::let_clause)
441 {
442 const let_clause* lc = static_cast<const let_clause *>(c);
443
444 set_bit(lc->get_var(), varmap, freeset, false);
445 set_bit(lc->get_score_var(), varmap, freeset, false);
446 }
447 else if (c->get_kind() == flwor_clause::window_clause)
448 {
449 const window_clause* wc = static_cast<const window_clause *>(c);
450
451 set_bit(wc->get_var(), varmap, freeset, false);
452
453 flwor_wincond* startCond = wc->get_win_start();
454 flwor_wincond* stopCond = wc->get_win_stop();
455
456 if (startCond != NULL)
457 remove_wincond_vars(startCond, varmap, freeset);
458
459 if (stopCond != NULL)
460 remove_wincond_vars(stopCond, varmap, freeset);
461 }
462 else if (c->get_kind() == flwor_clause::group_clause)
463 {
464 const group_clause* gc = static_cast<const group_clause *>(c);
465
466 const flwor_clause::rebind_list_t& gvars = gc->get_grouping_vars();
467 csize numGroupVars = gvars.size();
468
469 for (csize i = 0; i < numGroupVars; ++i)
470 {
471 set_bit(gvars[i].second, varmap, freeset, false);
472 }
473
474 const flwor_clause::rebind_list_t& ngvars = gc->get_nongrouping_vars();
475 csize numNonGroupVars = ngvars.size();
476
477 for (csize i = 0; i < numNonGroupVars; ++i)
478 {
479 set_bit(ngvars[i].second, varmap, freeset, false);
480 }
481 }
482 else if (c->get_kind() == flwor_clause::count_clause)
483 {
484 const count_clause* cc = static_cast<const count_clause *>(c);
485
486 set_bit(cc->get_var(), varmap, freeset, false);
487 }
488 }
489 }
490 else if (e->get_expr_kind() == trycatch_expr_kind)
491 {
492 trycatch_expr* trycatch = static_cast<trycatch_expr*>(e);
493
494 csize numClauses = trycatch->clause_count();
495
496 for (csize i = 0; i < numClauses; ++i)
497 {
498 const catch_clause* clause = (*trycatch)[i];
499
500 catch_clause::var_map_t& trycatchVars =
501 const_cast<catch_clause*>(clause)->get_vars();
502
503 catch_clause::var_map_t::const_iterator ite = trycatchVars.begin();
504 catch_clause::var_map_t::const_iterator end = trycatchVars.end();
505 for (; ite != end; ++ite)
506 {
507 var_expr* trycatchVar = (*ite).second;
508 set_bit(trycatchVar, varmap, freeset, false);
509 }
510 }
511 }
512
513 freevarMap[e] = freeset;
514 }
515
516
517 /*******************************************************************************
518
519 ********************************************************************************/
remove_wincond_vars(const flwor_wincond * cond,const VarIdMap & varmap,DynamicBitset & freeset)520 static void remove_wincond_vars(
521 const flwor_wincond* cond,
522 const VarIdMap& varmap,
523 DynamicBitset& freeset)
524 {
525 const flwor_wincond::vars& inVars = cond->get_in_vars();
526 const flwor_wincond::vars& outVars = cond->get_out_vars();
527
528 set_bit(inVars.posvar, varmap, freeset, false);
529 set_bit(inVars.curr, varmap, freeset, false);
530 set_bit(inVars.prev, varmap, freeset, false);
531 set_bit(inVars.next, varmap, freeset, false);
532
533 set_bit(outVars.posvar, varmap, freeset, false);
534 set_bit(outVars.curr, varmap, freeset, false);
535 set_bit(outVars.prev, varmap, freeset, false);
536 set_bit(outVars.next, varmap, freeset, false);
537 }
538
539
540 /*******************************************************************************
541
542 ********************************************************************************/
set_bit(var_expr * v,const VarIdMap & varmap,DynamicBitset & freeset,bool value)543 static void set_bit(
544 var_expr* v,
545 const VarIdMap& varmap,
546 DynamicBitset& freeset,
547 bool value)
548 {
549 if (v == NULL)
550 return;
551
552 VarIdMap::const_iterator i = varmap.find(v);
553 if (i != varmap.end())
554 freeset.set(i->second, value);
555 }
556
557
558 /////////////////////////////////////////////////////////////////////////////////
559 // //
560 // //
561 // //
562 /////////////////////////////////////////////////////////////////////////////////
563
564
565 #if 0
566 /*******************************************************************************
567
568 ********************************************************************************/
569 static void set_must_copy(expr* target, BoolAnnotationValue v)
570 {
571 assert(v != ANNOTATION_UNKNOWN);
572
573 if (target == NULL)
574 return;
575
576 switch (target->getMustCopyNodes())
577 {
578 case ANNOTATION_UNKNOWN:
579 {
580 target->setMustCopyNodes(v);
581 return;
582 }
583 case ANNOTATION_TRUE_FIXED:
584 {
585 return;
586 }
587 case ANNOTATION_TRUE:
588 {
589 if (v == ANNOTATION_TRUE_FIXED)
590 target->setMustCopyNodes(v);
591
592 return;
593 }
594 case ANNOTATION_FALSE:
595 {
596 target->setMustCopyNodes(v);
597 return;
598 }
599 }
600 }
601
602
603 /*******************************************************************************
604 If the no-node-copy annotation of the target expr is not set to false
605 already, set it to the value of the no-node-copy annotations of the
606 source expr.
607 ********************************************************************************/
608 static void pushdown_must_copy(expr* src, expr* target)
609 {
610 set_must_copy(target, src->getMustCopyNodes());
611 }
612
613
614 /*******************************************************************************
615
616 ********************************************************************************/
617 static void pushdown_window_vars(const flwor_wincond* cond, expr* target)
618 {
619 const flwor_wincond::vars& inVars = cond->get_in_vars();
620
621 if (inVars.curr)
622 pushdown_must_copy(inVars.curr, target);
623
624 if (inVars.prev)
625 pushdown_must_copy(inVars.prev, target);
626
627 if (inVars.next)
628 pushdown_must_copy(inVars.next, target);
629
630 const flwor_wincond::vars& outVars = cond->get_out_vars();
631
632 if (outVars.curr)
633 pushdown_must_copy(outVars.curr, target);
634
635 if (outVars.prev)
636 pushdown_must_copy(outVars.prev, target);
637
638 if (outVars.next)
639 pushdown_must_copy(outVars.next, target);
640 }
641
642
643 /*******************************************************************************
644
645 ********************************************************************************/
646 void computeMustCopyProperty(expr* inExpr)
647 {
648 switch(inExpr->get_expr_kind())
649 {
650 case const_expr_kind:
651 {
652 return;
653 }
654
655 case var_expr_kind:
656 {
657 var_expr* e = static_cast<var_expr*>(inExpr);
658
659 switch (e->get_kind())
660 {
661 case var_expr::for_var:
662 case var_expr::let_var:
663 case var_expr::pos_var:
664 case var_expr::win_var:
665 case var_expr::score_var:
666 case var_expr::wincond_out_var:
667 case var_expr::wincond_out_pos_var:
668 case var_expr::wincond_in_var:
669 case var_expr::wincond_in_pos_var:
670 case var_expr::count_var:
671 case var_expr::groupby_var:
672 case var_expr::non_groupby_var:
673 case var_expr::copy_var:
674 {
675 return;
676 }
677
678 case var_expr::arg_var:
679 {
680 return;
681 //expr* argExpr = argExprs[e->get_param_pos()];
682 //pushdown_no_node_copy(inExpr, argExpr);
683 }
684
685 case var_expr::prolog_var:
686 case var_expr::local_var:
687 {
688 // TODO: pass into this function a map with one entry per in-scope var.
689 // The entry maps the var to the most recently encountered assignment
690 // expr for this var.
691 return;
692 }
693
694 case var_expr::catch_var:
695 {
696 // TODO: associate the catch var with the try clause and keep track inside the
697 // try_catch expr of all the fn:error() calls that return an item()* seq.
698 return;
699 }
700
701 case var_expr::eval_var: // TODO
702 default:
703 {
704 ZORBA_ASSERT(false);
705 }
706 }
707
708 break;
709 }
710
711 case doc_expr_kind:
712 {
713 doc_expr* e = static_cast<doc_expr*>(inExpr);
714 pushdown_must_copy(inExpr, e->getContent());
715 break;
716 }
717
718 case elem_expr_kind:
719 {
720 elem_expr* e = static_cast<elem_expr*>(inExpr);
721 pushdown_must_copy(inExpr, e->getContent());
722 pushdown_must_copy(inExpr, e->getAttrs());
723 set_must_copy(e->getQNameExpr(), ANNOTATION_FALSE);
724 break;
725 }
726
727 case attr_expr_kind:
728 {
729 attr_expr* e = static_cast<attr_expr*>(inExpr);
730 pushdown_must_copy(inExpr, e->getValueExpr());
731 set_must_copy(e->getQNameExpr(), ANNOTATION_FALSE);
732 break;
733 }
734
735 case text_expr_kind:
736 {
737 text_expr* e = static_cast<text_expr*>(inExpr);
738 set_must_copy(e->get_text(), ANNOTATION_FALSE);
739 break;
740 }
741
742 case pi_expr_kind:
743 {
744 pi_expr* e = static_cast<pi_expr*>(inExpr);
745 set_must_copy(e->get_target_expr(), ANNOTATION_FALSE);
746 set_must_copy(e->get_content_expr(), ANNOTATION_FALSE);
747 break;
748 }
749
750 case relpath_expr_kind:
751 {
752 const relpath_expr* e = static_cast<const relpath_expr*>(inExpr);
753
754 std::vector<expr*>::const_iterator ite = e->begin();
755 std::vector<expr*>::const_iterator end = e->end();
756
757 for (++ite; ite != end; ++ite)
758 {
759 axis_step_expr* axisExpr = static_cast<axis_step_expr*>((*ite));
760 axis_kind_t axisKind = axisExpr->getAxis();
761
762 if (axisKind != axis_kind_child &&
763 axisKind != axis_kind_descendant &&
764 axisKind != axis_kind_self &&
765 axisKind != axis_kind_attribute)
766 {
767 set_must_copy((*e)[0], ANNOTATION_TRUE_FIXED);
768 break;
769 }
770 }
771
772 break;
773 }
774
775 case flwor_expr_kind:
776 case gflwor_expr_kind:
777 {
778 flwor_expr* e = static_cast<flwor_expr*>(inExpr);
779
780 pushdown_must_copy(inExpr, e->get_return_expr());
781
782 csize i = e->num_clauses();
783 for (; i > 0; --i)
784 {
785 flwor_clause* clause = e->get_clause(i-1);
786
787 switch(clause->get_kind())
788 {
789 case flwor_clause::for_clause:
790 {
791 for_clause* fc = static_cast<for_clause*>(clause);
792 pushdown_must_copy(fc->get_var(), fc->get_expr());
793 computeMustCopyProperty(fc->get_expr());
794 break;
795 }
796 case flwor_clause::let_clause:
797 {
798 let_clause* lc = static_cast<let_clause*>(clause);
799 pushdown_must_copy(lc->get_var(), lc->get_expr());
800 computeMustCopyProperty(lc->get_expr());
801 break;
802 }
803 case flwor_clause::window_clause:
804 {
805 window_clause* wc = static_cast<window_clause*>(clause);
806
807 pushdown_must_copy(wc->get_var(), wc->get_expr());
808
809 const flwor_wincond* startCond = wc->get_win_start();
810 const flwor_wincond* endCond = wc->get_win_start();
811
812 if (startCond)
813 {
814 set_must_copy(startCond->get_cond(), ANNOTATION_FALSE);
815
816 computeMustCopyProperty(startCond->get_cond());
817
818 pushdown_window_vars(startCond, wc->get_expr());
819 }
820
821 if (endCond)
822 {
823 set_must_copy(endCond->get_cond(), ANNOTATION_FALSE);
824
825 computeMustCopyProperty(endCond->get_cond());
826
827 pushdown_window_vars(endCond, wc->get_expr());
828 }
829
830 computeMustCopyProperty(wc->get_expr());
831 break;
832 }
833 case flwor_clause::where_clause:
834 {
835 where_clause* cc = static_cast<where_clause*>(clause);
836 set_must_copy(cc->get_expr(), ANNOTATION_FALSE);
837 computeMustCopyProperty(cc->get_expr());
838 break;
839 }
840 case flwor_clause::group_clause:
841 {
842 group_clause* gc = static_cast<group_clause*>(clause);
843
844 flwor_clause::rebind_list_t::iterator ite = gc->beginGroupVars();
845 flwor_clause::rebind_list_t::iterator end = gc->endGroupVars();
846
847 for (; ite != end; ++ite)
848 {
849 pushdown_must_copy((*ite).second, (*ite).first);
850 }
851
852 ite = gc->beginNonGroupVars();
853 end = gc->endNonGroupVars();
854
855 for (; ite != end; ++ite)
856 {
857 pushdown_must_copy((*ite).second, (*ite).first);
858 }
859
860 break;
861 }
862 case flwor_clause::order_clause:
863 {
864 orderby_clause* ob = static_cast<orderby_clause*>(clause);
865
866 std::vector<expr*>::iterator ite = ob->begin();
867 std::vector<expr*>::iterator end = ob->end();
868
869 for (; ite != end; ++ite)
870 {
871 set_must_copy((*ite), ANNOTATION_FALSE);
872 computeMustCopyProperty(*ite);
873 }
874 break;
875 }
876 case flwor_clause::count_clause:
877 {
878 break;
879 }
880 default:
881 ZORBA_ASSERT(false);
882 }
883 }
884
885 return;
886 }
887
888 case if_expr_kind:
889 {
890 if_expr* e = static_cast<if_expr*>(inExpr);
891 pushdown_must_copy(inExpr, e->get_cond_expr());
892 pushdown_must_copy(inExpr, e->get_then_expr());
893 pushdown_must_copy(inExpr, e->get_else_expr());
894 break;
895 }
896
897 case trycatch_expr_kind:
898 {
899 trycatch_expr* e = static_cast<trycatch_expr*>(inExpr);
900 pushdown_must_copy(inExpr, e->get_try_expr());
901
902 csize numCatches = e->clause_count();
903 for (csize i = 0; i < numCatches; ++i)
904 {
905 pushdown_must_copy(inExpr, e->get_catch_expr(i));
906 }
907 break;
908 }
909
910 case fo_expr_kind:
911 {
912 fo_expr* e = static_cast<fo_expr*>(inExpr);
913 function* func = e->get_func();
914
915 csize numArgs = e->num_args();
916
917 for (csize i = 0; i < numArgs; ++i)
918 {
919 set_must_copy(e->get_arg(i), func->mustCopyInputNodes(e, i));
920 }
921
922 break;
923 }
924
925 case dynamic_function_invocation_expr_kind:
926 case function_item_expr_kind:
927 {
928 ZORBA_ASSERT(false); // TODO
929 }
930
931 case castable_expr_kind:
932 case instanceof_expr_kind:
933 case cast_expr_kind:
934 {
935 cast_or_castable_base_expr* e = static_cast<cast_or_castable_base_expr*>(inExpr);
936 set_must_copy(e, ANNOTATION_FALSE);
937 pushdown_must_copy(inExpr, e->get_input());
938 break;
939 }
940
941 case treat_expr_kind:
942 case promote_expr_kind:
943 {
944 cast_base_expr* e = static_cast<cast_base_expr*>(inExpr);
945
946 if (TypeOps::is_subtype(e->get_type_manager(),
947 *e->get_target_type(),
948 *GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_STAR))
949 {
950 set_must_copy(e, ANNOTATION_FALSE);
951 }
952
953 pushdown_must_copy(inExpr, e->get_input());
954 break;
955 }
956
957 case name_cast_expr_kind:
958 {
959 name_cast_expr* e = static_cast<name_cast_expr*>(inExpr);
960 set_must_copy(e, ANNOTATION_FALSE);
961 pushdown_must_copy(inExpr, e->get_input());
962 break;
963 }
964
965 case validate_expr_kind:
966 {
967 validate_expr* e = static_cast<validate_expr*>(inExpr);
968 set_must_copy(e, ANNOTATION_TRUE_FIXED);
969 pushdown_must_copy(inExpr, e->get_expr());
970 break;
971 }
972
973 case extension_expr_kind:
974 {
975 extension_expr* e = static_cast<extension_expr*>(inExpr);
976 pushdown_must_copy(inExpr, e->get_expr());
977 break;
978 }
979
980 case order_expr_kind:
981 {
982 order_expr* e = static_cast<order_expr*>(inExpr);
983 pushdown_must_copy(inExpr, e->get_expr());
984 break;
985 }
986
987 case delete_expr_kind:
988 case insert_expr_kind:
989 case rename_expr_kind:
990 case replace_expr_kind:
991 {
992 update_expr_base* e = static_cast<update_expr_base*>(inExpr);
993
994 set_must_copy(e->getTargetExpr(), ANNOTATION_TRUE_FIXED);
995
996 if (e->get_expr_kind() == rename_expr_kind)
997 {
998 set_must_copy(e->getSourceExpr(), ANNOTATION_FALSE);
999 }
1000 else if (e->get_expr_kind() == replace_expr_kind)
1001 {
1002 replace_expr* re = static_cast<replace_expr*>(inExpr);
1003
1004 if (re->getType() == store::UpdateConsts::VALUE_OF_NODE)
1005 {
1006 set_must_copy(e->getSourceExpr(), ANNOTATION_FALSE);
1007 }
1008 else
1009 {
1010 set_must_copy(e->getSourceExpr(), ANNOTATION_TRUE_FIXED);
1011 }
1012 }
1013 else
1014 {
1015 set_must_copy(e->getSourceExpr(), ANNOTATION_TRUE_FIXED);
1016 }
1017
1018 break;
1019 }
1020
1021 #if 0
1022 case transform_expr_kind:
1023
1024 case block_expr_kind:
1025 case var_decl_expr_kind:
1026 case apply_expr_kind:
1027 case exit_expr_kind:
1028 case exit_catcher_expr_kind:
1029 case flowctl_expr_kind:
1030 case while_expr_kind:
1031
1032 case eval_expr_kind:
1033 case debugger_expr_kind:
1034
1035 #endif
1036
1037 case wrapper_expr_kind:
1038 {
1039 wrapper_expr* e = static_cast<wrapper_expr*>(inExpr);
1040 pushdown_must_copy(inExpr, e->get_expr());
1041 break;
1042 }
1043
1044 case function_trace_expr_kind:
1045 {
1046 function_trace_expr* e = static_cast<function_trace_expr*>(inExpr);
1047 pushdown_must_copy(inExpr, e->get_expr());
1048 break;
1049 }
1050
1051 #ifndef ZORBA_NO_FULL_TEXT
1052 case ft_expr_kind:
1053 {
1054 ft_expr* e = static_cast<ft_expr*>(inExpr);
1055 set_must_copy(e, ANNOTATION_FALSE);
1056 set_must_copy(e->get_range(), ANNOTATION_TRUE_FIXED);
1057 set_must_copy(e->get_ignore(), ANNOTATION_TRUE_FIXED);
1058 break;
1059 }
1060 #endif /* ZORBA_NO_FULL_TEXT */
1061
1062 case axis_step_expr_kind:
1063 case match_expr_kind:
1064 default:
1065 ZORBA_ASSERT(false);
1066 }
1067
1068 ExprIterator iter(inExpr);
1069 while (!iter.done())
1070 {
1071 computeMustCopyProperty(*iter);
1072 iter.next();
1073 }
1074 }
1075 #endif
1076
1077
1078 }
1079 }
1080
1081 /* vim:set et sw=2 ts=2: */
1082