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