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 "system/globalenv.h"
19 
20 #include "context/static_context.h"
21 
22 #include "functions/library.h"
23 
24 #include "compiler/expression/flwor_expr.h"
25 #include "compiler/expression/fo_expr.h"
26 #include "compiler/expression/expr.h"
27 #include "compiler/expression/expr_visitor.h"
28 
29 #include "compiler/api/compilercb.h"
30 
31 #include "types/root_typemanager.h"
32 #include "types/typeops.h"
33 
34 #include "diagnostics/assert.h"
35 #include "diagnostics/util_macros.h"
36 #include "diagnostics/xquery_diagnostics.h"
37 
38 namespace zorba
39 {
40 
41 /*******************************************************************************
42 
43 ********************************************************************************/
DEF_EXPR_ACCEPT(flwor_expr)44 DEF_EXPR_ACCEPT (flwor_expr)
45 
46 flwor_clause::~flwor_clause()
47 {
48 }
49 
50 
51 /*******************************************************************************
52 
53 ********************************************************************************/
forletwin_clause(static_context * sctx,CompilerCB * ccb,const QueryLoc & loc,flwor_clause::ClauseKind kind,var_expr * varExpr,expr * domainExpr)54 forletwin_clause::forletwin_clause(
55     static_context* sctx,
56     CompilerCB* ccb,
57     const QueryLoc& loc,
58     flwor_clause::ClauseKind kind,
59     var_expr* varExpr,
60     expr* domainExpr)
61   :
62   flwor_clause(sctx, ccb, loc, kind),
63   theVarExpr(varExpr),
64   theDomainExpr(domainExpr)
65 {
66   if (theVarExpr != NULL)
67     theVarExpr->set_flwor_clause(this);
68 
69   expr::checkNonUpdating(theDomainExpr);
70   //expr::checkSimpleExpr(theDomainExpr);
71 }
72 
73 
~forletwin_clause()74 forletwin_clause::~forletwin_clause()
75 {
76   if (theVarExpr != NULL)
77     theVarExpr->set_flwor_clause(NULL);
78 }
79 
80 
set_expr(expr * v)81 void forletwin_clause::set_expr(expr* v)
82 {
83   theDomainExpr = v;
84 }
85 
86 
set_var(var_expr * v)87 void forletwin_clause::set_var(var_expr* v)
88 {
89   theVarExpr = v;
90 
91   if (theVarExpr != NULL)
92   {
93     theVarExpr->set_flwor_clause(this);
94 
95     if (theKind == window_clause && theVarExpr->get_type() != NULL)
96     {
97       RootTypeManager& rtm = GENV_TYPESYSTEM;
98       TypeManager* tm = theVarExpr->get_type_manager();
99 
100       const QueryLoc& loc = theVarExpr->get_loc();
101 
102       xqtref_t varType = theVarExpr->get_type();
103       xqtref_t domainType = theDomainExpr->get_return_type();
104 
105       if (!TypeOps::is_subtype(tm, *rtm.ITEM_TYPE_STAR, *varType, loc) &&
106           !TypeOps::is_subtype(tm, *domainType, *varType, loc))
107       {
108         theDomainExpr = theCCB->theEM->
109         create_treat_expr(theDomainExpr->get_sctx(),
110                           theDomainExpr->get_loc(),
111                           theDomainExpr,
112                           varType,
113                           TreatIterator::TYPE_MATCH);
114       }
115     }
116   }
117 }
118 
119 
120 /*******************************************************************************
121 
122 ********************************************************************************/
for_clause(static_context * sctx,CompilerCB * ccb,const QueryLoc & loc,var_expr * varExpr,expr * domainExpr,var_expr * posVarExpr,var_expr * scoreVarExpr,bool isAllowingEmpty)123 for_clause::for_clause(
124     static_context* sctx,
125     CompilerCB* ccb,
126     const QueryLoc& loc,
127     var_expr* varExpr,
128     expr* domainExpr,
129     var_expr* posVarExpr,
130     var_expr* scoreVarExpr,
131     bool isAllowingEmpty)
132   :
133   forletwin_clause(sctx, ccb, loc, flwor_clause::for_clause, varExpr, domainExpr),
134   thePosVarExpr(posVarExpr),
135   theScoreVarExpr(scoreVarExpr),
136   theAllowingEmpty(isAllowingEmpty)
137 {
138   if (thePosVarExpr != NULL)
139     thePosVarExpr->set_flwor_clause(this);
140 
141   if (theScoreVarExpr != NULL)
142     theScoreVarExpr->set_flwor_clause(this);
143 
144   if (varExpr != NULL && sctx != NULL)
145   {
146     RootTypeManager& rtm = GENV_TYPESYSTEM;
147     TypeManager* tm = sctx->get_typemanager();
148 
149     xqtref_t declaredType = varExpr->get_type();
150     if (declaredType != NULL)
151     {
152       if (declaredType->is_empty())
153       {
154         RAISE_ERROR(err::XPTY0004, loc,
155         ERROR_PARAMS(ZED(BadType_23o), "empty-sequence"));
156       }
157 
158       xqtref_t domainType = domainExpr->get_return_type();
159 
160       if (!TypeOps::is_subtype(tm, *rtm.ITEM_TYPE_STAR, *declaredType, loc))
161       {
162         declaredType = tm->create_type(*declaredType, TypeConstants::QUANT_STAR);
163 
164         if (!TypeOps::is_subtype(tm, *domainType, *declaredType, loc))
165         {
166           xqtref_t varType = TypeOps::intersect_type(*domainType, *declaredType, tm);
167           if (TypeOps::is_equal(tm, *varType, *rtm.NONE_TYPE, loc))
168           {
169             RAISE_ERROR(err::XPTY0004, loc,
170             ERROR_PARAMS(ZED(BadType_23o),
171                          *domainType,
172                          ZED(NoTreatAs_4),
173                          *declaredType));
174           }
175 
176           domainExpr = theCCB->theEM->create_treat_expr(sctx,
177                                             loc,
178                                             domainExpr,
179                                             declaredType,
180                                             TreatIterator::TYPE_MATCH);
181 
182           set_expr(domainExpr);
183         }
184       }
185     }
186   }
187 }
188 
189 
~for_clause()190 for_clause::~for_clause()
191 {
192   if (thePosVarExpr != NULL)
193     thePosVarExpr->set_flwor_clause(NULL);
194 
195   if (theScoreVarExpr != NULL)
196     theScoreVarExpr->set_flwor_clause(NULL);
197 }
198 
199 
get_pos_var() const200 var_expr* for_clause::get_pos_var() const
201 {
202   return thePosVarExpr;
203 }
204 
205 
get_score_var() const206 var_expr* for_clause::get_score_var() const
207 {
208   return theScoreVarExpr;
209 }
210 
211 
set_pos_var(var_expr * v)212 void for_clause::set_pos_var(var_expr* v)
213 {
214   thePosVarExpr = v;
215   if (thePosVarExpr != NULL)
216     thePosVarExpr->set_flwor_clause(this);
217 }
218 
219 
set_score_var(var_expr * v)220 void for_clause::set_score_var(var_expr* v)
221 {
222   theScoreVarExpr = v;
223   if (theScoreVarExpr != NULL)
224     theScoreVarExpr->set_flwor_clause(this);
225 }
226 
227 
clone(expr::substitution_t & subst) const228 flwor_clause* for_clause::clone(expr::substitution_t& subst) const
229 {
230   expr* domainCopy = theDomainExpr->clone(subst);
231 
232   var_expr* varCopy = theCCB->theEM->create_var_expr(*theVarExpr);
233   subst[theVarExpr] = varCopy;
234 
235   var_expr* posvarCopy = NULL;
236   var_expr* pos_var_ptr = thePosVarExpr;
237   if (pos_var_ptr)
238   {
239     posvarCopy = theCCB->theEM->create_var_expr(*pos_var_ptr);
240     subst[pos_var_ptr] = posvarCopy;
241   }
242 
243   var_expr* scorevarCopy = NULL;
244   var_expr* score_var_ptr = theScoreVarExpr;
245   if (score_var_ptr)
246   {
247     scorevarCopy = theCCB->theEM->create_var_expr(*score_var_ptr);
248     subst[score_var_ptr] = scorevarCopy;
249   }
250 
251   return theCCB->theEM->create_for_clause(theContext,
252                         get_loc(),
253                         varCopy,
254                         domainCopy,
255                         posvarCopy,
256                         scorevarCopy,
257                         theAllowingEmpty);
258 }
259 
260 
261 /*******************************************************************************
262 
263 ********************************************************************************/
let_clause(static_context * sctx,CompilerCB * ccb,const QueryLoc & loc,var_expr * varExpr,expr * domainExpr,bool lazy)264 let_clause::let_clause(
265     static_context* sctx,
266     CompilerCB* ccb,
267     const QueryLoc& loc,
268     var_expr* varExpr,
269     expr* domainExpr,
270     bool lazy)
271   :
272   forletwin_clause(sctx, ccb, loc, flwor_clause::let_clause, varExpr, domainExpr),
273   theScoreVarExpr(NULL),
274   theLazyEval(lazy)
275 {
276   if (theScoreVarExpr != NULL)
277     theScoreVarExpr->set_flwor_clause(this);
278 
279   if (varExpr != NULL && sctx != NULL)
280   {
281     RootTypeManager& rtm = GENV_TYPESYSTEM;
282     TypeManager* tm = sctx->get_typemanager();
283 
284     xqtref_t declaredType = varExpr->get_type();
285 
286     if (declaredType != NULL)
287     {
288       xqtref_t domainType = domainExpr->get_return_type();
289 
290       if (!TypeOps::is_subtype(tm, *rtm.ITEM_TYPE_STAR, *declaredType, loc) &&
291           !TypeOps::is_subtype(tm, *domainType, *declaredType, loc))
292       {
293         xqtref_t varType = TypeOps::intersect_type(*domainType, *declaredType, tm);
294 
295         if (TypeOps::is_equal(tm, *varType, *rtm.NONE_TYPE, loc))
296         {
297           RAISE_ERROR(err::XPTY0004, loc,
298           ERROR_PARAMS(ZED(BadType_23o), *domainType, ZED(NoTreatAs_4), *declaredType));
299         }
300 
301         domainExpr = theCCB->theEM->create_treat_expr(sctx,
302                                     loc,
303                                     domainExpr,
304                                     declaredType,
305                                     TreatIterator::TYPE_MATCH);
306 
307         set_expr(domainExpr);
308       }
309     }
310   }
311 }
312 
313 
~let_clause()314 let_clause::~let_clause()
315 {
316   if (theScoreVarExpr != NULL)
317     theScoreVarExpr->set_flwor_clause(NULL);
318 }
319 
320 
get_score_var() const321 var_expr* let_clause::get_score_var() const
322 {
323   return theScoreVarExpr;
324 }
325 
326 
set_score_var(var_expr * v)327 void let_clause::set_score_var(var_expr* v)
328 {
329   theScoreVarExpr = v;
330   if (theScoreVarExpr != NULL)
331     theScoreVarExpr->set_flwor_clause(this);
332 }
333 
334 
clone(expr::substitution_t & subst) const335 flwor_clause* let_clause::clone(expr::substitution_t& subst) const
336 {
337   expr* domainCopy = theDomainExpr->clone(subst);
338 
339   var_expr* varCopy = theCCB->theEM->create_var_expr(*theVarExpr);
340   subst[theVarExpr] = varCopy;
341 
342 #if 0
343   var_expr* scorevarCopy = NULL;
344   var_expr* score_var_ptr = theScoreVarExpr;
345   if (score_var_ptr)
346   {
347     scorevarCopy = theCCB->theEM->create_var_expr(*score_var_ptr);
348     subst->get(score_var_ptr) = scorevarCopy;
349   }
350 #endif
351 
352   return theCCB->theEM->create_let_clause(theContext,
353                         get_loc(),
354                         varCopy,
355                         domainCopy,
356                         theLazyEval);
357 }
358 
359 
360 
361 /*******************************************************************************
362 
363 ********************************************************************************/
window_clause(static_context * sctx,CompilerCB * ccb,const QueryLoc & loc,window_t winKind,var_expr * varExpr,expr * domainExpr,flwor_wincond * winStart,flwor_wincond * winStop,bool lazy)364 window_clause::window_clause(
365     static_context* sctx,
366     CompilerCB* ccb,
367     const QueryLoc& loc,
368     window_t winKind,
369     var_expr* varExpr,
370     expr* domainExpr,
371     flwor_wincond* winStart,
372     flwor_wincond* winStop,
373     bool lazy)
374   :
375   forletwin_clause(sctx, ccb, loc, flwor_clause::window_clause, varExpr, domainExpr),
376   theWindowKind(winKind),
377   theWinStartCond(winStart),
378   theWinStopCond(winStop),
379   theLazyEval(lazy)
380 {
381   if (theWinStartCond != NULL)
382     theWinStartCond->set_flwor_clause(this);
383 
384   if (theWinStopCond != NULL)
385     theWinStopCond->set_flwor_clause(this);
386 
387   if (winKind == tumbling_window)
388     theLazyEval = true;
389 
390   if (varExpr != NULL && sctx != NULL)
391   {
392     RootTypeManager& rtm = GENV_TYPESYSTEM;
393     TypeManager* tm = sctx->get_typemanager();
394 
395     xqtref_t varType = varExpr->get_type();
396 
397     if (varType != NULL)
398     {
399       xqtref_t domainType = domainExpr->get_return_type();
400 
401       if (!TypeOps::is_subtype(tm, *rtm.ITEM_TYPE_STAR, *varType, loc) &&
402           !TypeOps::is_subtype(tm, *domainType, *varType, loc))
403       {
404         domainExpr = theCCB->theEM->
405         create_treat_expr(sctx,
406                           loc,
407                           domainExpr,
408                           varType,
409                           TreatIterator::TYPE_MATCH);
410 
411         set_expr(domainExpr);
412       }
413     }
414   }
415 }
416 
417 
~window_clause()418 window_clause::~window_clause()
419 {
420   if (theWinStartCond != NULL)
421     theWinStartCond->set_flwor_clause(NULL);
422 
423   if (theWinStopCond != NULL)
424     theWinStopCond->set_flwor_clause(NULL);
425 }
426 
427 
set_win_start(flwor_wincond * cond)428 void window_clause::set_win_start(flwor_wincond* cond)
429 {
430   theWinStartCond = cond;
431   if (theWinStartCond != NULL)
432     theWinStartCond->set_flwor_clause(this);
433 }
434 
435 
set_win_stop(flwor_wincond * cond)436 void window_clause::set_win_stop(flwor_wincond* cond)
437 {
438   theWinStopCond = cond;
439   if (theWinStopCond != NULL)
440     theWinStopCond->set_flwor_clause(this);
441 }
442 
443 
clone(expr::substitution_t & subst) const444 flwor_clause* window_clause::clone(expr::substitution_t& subst) const
445 {
446   expr* domainCopy = theDomainExpr->clone(subst);
447 
448   var_expr* varCopy = theCCB->theEM->create_var_expr(*theVarExpr);
449   subst[theVarExpr] = varCopy;
450 
451   flwor_wincond* cloneStartCond = NULL;
452   flwor_wincond* cloneStopCond = NULL;
453 
454   if (theWinStartCond != NULL)
455     cloneStartCond = theWinStartCond->clone(subst);
456 
457   if (theWinStopCond != NULL)
458     cloneStopCond = theWinStopCond->clone(subst);
459 
460   return theCCB->theEM->create_window_clause(theContext,
461                                              get_loc(),
462                                              theWindowKind,
463                                              varCopy,
464                                              domainCopy,
465                                              cloneStartCond,
466                                              cloneStopCond,
467                                              theLazyEval);
468 }
469 
470 
471 /*******************************************************************************
472 
473 ********************************************************************************/
flwor_wincond(CompilerCB * ccb,static_context * sctx,bool isOnly,const vars & in_vars,const vars & out_vars,expr * cond)474 flwor_wincond::flwor_wincond(
475     CompilerCB* ccb,
476     static_context* sctx,
477     bool isOnly,
478     const vars& in_vars,
479     const vars& out_vars,
480     expr* cond)
481   :
482   theIsOnly(isOnly),
483   theInputVars(in_vars),
484   theOutputVars(out_vars),
485   theCondExpr(cond),
486   theCCB(ccb)
487 {
488   expr::checkSimpleExpr(theCondExpr);
489 
490   if (sctx != NULL)
491   {
492     TypeManager* tm = sctx->get_typemanager();
493 
494     xqtref_t condType = theCondExpr->get_return_type();
495 
496     if(!TypeOps::is_equal(tm,
497                           *condType,
498                           *GENV_TYPESYSTEM.BOOLEAN_TYPE_ONE,
499                           theCondExpr->get_loc()))
500     {
501       theCondExpr = theCCB->theEM->create_fo_expr(theCondExpr->get_sctx(),
502                                 theCondExpr->get_loc(),
503                                 GET_BUILTIN_FUNCTION(FN_BOOLEAN_1),
504                                 theCondExpr);
505     }
506   }
507 }
508 
509 
~flwor_wincond()510 flwor_wincond::~flwor_wincond()
511 {
512   set_flwor_clause(NULL);
513 }
514 
515 
vars()516 flwor_wincond::vars::vars()
517 :
518 posvar(NULL),
519 curr(NULL),
520 prev(NULL),
521 next(NULL)
522 {
523 }
524 
~vars()525 flwor_wincond::vars::~vars()
526 {
527 //  set_flwor_clause(NULL);
528 }
529 
530 
set_flwor_clause(flwor_clause * c)531 void flwor_wincond::vars::set_flwor_clause(flwor_clause* c)
532 {
533   if (posvar != NULL) posvar->set_flwor_clause(c);
534   if (curr != NULL) curr->set_flwor_clause(c);
535   if (prev != NULL) prev->set_flwor_clause(c);
536   if (next != NULL) next->set_flwor_clause(c);
537 }
538 
539 
clone(ExprManager * mgr,flwor_wincond::vars & cloneVars,expr::substitution_t & subst) const540 void flwor_wincond::vars::clone(
541     ExprManager* mgr,
542     flwor_wincond::vars& cloneVars,
543     expr::substitution_t& subst) const
544 {
545   if (posvar != NULL)
546   {
547     var_expr* varCopy = mgr->create_var_expr(*posvar);
548     subst[posvar] = varCopy;
549     cloneVars.posvar = varCopy;
550   }
551 
552   if (curr != NULL)
553   {
554     var_expr* varCopy = mgr->create_var_expr(*curr);
555     subst[curr] = varCopy;
556     cloneVars.curr = varCopy;
557   }
558 
559   if (prev != NULL)
560   {
561     var_expr* varCopy = mgr->create_var_expr(*prev);
562     subst[prev] = varCopy;
563     cloneVars.prev = varCopy;
564   }
565 
566   if (next != NULL)
567   {
568     var_expr* varCopy = mgr->create_var_expr(*next);
569     subst[next] = varCopy;
570     cloneVars.next = varCopy;
571   }
572 }
573 
574 
set_flwor_clause(flwor_clause * c)575 void flwor_wincond::set_flwor_clause(flwor_clause* c)
576 {
577   theInputVars.set_flwor_clause(c);
578   theOutputVars.set_flwor_clause(c);
579 }
580 
581 
clone(expr::substitution_t & subst) const582 flwor_wincond* flwor_wincond::clone(expr::substitution_t& subst) const
583 {
584   flwor_wincond::vars cloneInVars;
585   flwor_wincond::vars cloneOutVars;
586 
587   theInputVars.clone(theCCB->theEM, cloneInVars, subst);
588   theOutputVars.clone(theCCB->theEM, cloneOutVars, subst);
589 
590   expr* cloneCondExpr = theCondExpr->clone(subst);
591 
592   return theCCB->theEM->create_flwor_wincond(NULL,
593                            theIsOnly,
594                            cloneInVars,
595                            cloneOutVars,
596                            cloneCondExpr);
597 }
598 
599 
600 /*******************************************************************************
601 
602 ********************************************************************************/
group_clause(static_context * sctx,CompilerCB * ccb,const QueryLoc & loc,const rebind_list_t & gvars,rebind_list_t ngvars,const std::vector<std::string> & collations)603 group_clause::group_clause(
604      static_context* sctx,
605      CompilerCB* ccb,
606      const QueryLoc& loc,
607      const rebind_list_t& gvars,
608      rebind_list_t ngvars,
609      const std::vector<std::string>& collations)
610   :
611   flwor_clause(sctx, ccb, loc, flwor_clause::group_clause),
612   theGroupVars(gvars),
613   theNonGroupVars(ngvars),
614   theCollations(collations)
615 {
616   csize numGVars = theGroupVars.size();
617   csize numNGVars = theNonGroupVars.size();
618 
619   for (csize i = 0; i < numGVars; ++i)
620     theGroupVars[i].second->set_flwor_clause(this);
621 
622   for (csize i = 0; i < numNGVars; ++i)
623     theNonGroupVars[i].second->set_flwor_clause(this);
624 }
625 
626 
~group_clause()627 group_clause::~group_clause()
628 {
629   csize numGVars = theGroupVars.size();
630   csize numNGVars = theNonGroupVars.size();
631 
632   for (csize i = 0; i < numGVars; ++i)
633     theGroupVars[i].second->set_flwor_clause(NULL);
634 
635   for (csize i = 0; i < numNGVars; ++i)
636     theNonGroupVars[i].second->set_flwor_clause(NULL);
637 }
638 
639 
get_input_for_group_var(const var_expr * var)640 expr* group_clause::get_input_for_group_var(const var_expr* var)
641 {
642   csize numVars = theGroupVars.size();
643   for (csize i = 0; i < numVars; ++i)
644   {
645     if (theGroupVars[i].second == var)
646       return theGroupVars[i].first;
647   }
648 
649   return NULL;
650 }
651 
652 
get_input_for_nongroup_var(const var_expr * var)653 expr* group_clause::get_input_for_nongroup_var(const var_expr* var)
654 {
655   csize numVars = theNonGroupVars.size();
656   for (csize i = 0; i < numVars; ++i)
657   {
658     if (theNonGroupVars[i].second == var)
659       return theNonGroupVars[i].first;
660   }
661 
662   return NULL;
663 }
664 
665 
clone(expr::substitution_t & subst) const666 flwor_clause* group_clause::clone(expr::substitution_t& subst) const
667 {
668   csize numGroupVars = theGroupVars.size();
669   csize numNonGroupVars = theNonGroupVars.size();
670 
671   rebind_list_t cloneGroupVars(numGroupVars);
672   rebind_list_t cloneNonGroupVars(numNonGroupVars);
673 
674   ExprManager* exprMgr = NULL;
675 
676   if (numGroupVars > 0)
677     exprMgr = theGroupVars[0].first->get_ccb()->theEM;
678   else if (numNonGroupVars > 0)
679     exprMgr = theNonGroupVars[0].first->get_ccb()->theEM;
680 
681   for (csize i = 0; i < numGroupVars; ++i)
682   {
683     cloneGroupVars[i].first = theGroupVars[i].first->clone(subst);
684     cloneGroupVars[i].second = exprMgr->create_var_expr(*theGroupVars[i].second);
685     subst[theGroupVars[i].second] = cloneGroupVars[i].second;
686   }
687 
688   for (csize i = 0; i < numNonGroupVars; ++i)
689   {
690     cloneNonGroupVars[i].first = theNonGroupVars[i].first->clone(subst);
691     cloneNonGroupVars[i].second = exprMgr->create_var_expr(*theNonGroupVars[i].second);
692     subst[theNonGroupVars[i].second] = cloneNonGroupVars[i].second;
693   }
694 
695   return theCCB->theEM->create_group_clause(theContext,
696                           get_loc(),
697                           cloneGroupVars,
698                           cloneNonGroupVars,
699                           theCollations);
700 }
701 
702 
703 /*******************************************************************************
704 
705 ********************************************************************************/
orderby_clause(static_context * sctx,CompilerCB * ccb,const QueryLoc & loc,bool stable,const std::vector<OrderModifier> & modifiers,const std::vector<expr * > & orderingExprs)706 orderby_clause::orderby_clause(
707     static_context* sctx,
708     CompilerCB* ccb,
709     const QueryLoc& loc,
710     bool stable,
711     const std::vector<OrderModifier>& modifiers,
712     const std::vector<expr*>& orderingExprs)
713   :
714   flwor_clause(sctx, ccb, loc, flwor_clause::order_clause),
715   theStableOrder(stable),
716   theModifiers(modifiers),
717   theOrderingExprs(orderingExprs)
718 {
719   std::vector<expr*>::const_iterator ite = orderingExprs.begin();
720   std::vector<expr*>::const_iterator end = orderingExprs.end();
721 
722   for (; ite != end; ++ite)
723   {
724     expr::checkSimpleExpr((*ite));
725   }
726 }
727 
728 
clone(expr::substitution_t & subst) const729 flwor_clause* orderby_clause::clone(expr::substitution_t& subst) const
730 {
731   csize numColumns = num_columns();
732 
733   std::vector<expr*> cloneExprs(numColumns);
734 
735   for (csize i = 0; i < numColumns; ++i)
736   {
737     cloneExprs[i] = theOrderingExprs[i]->clone(subst);
738   }
739 
740   return theCCB->theEM->create_orderby_clause(theContext,
741                             get_loc(),
742                             theStableOrder,
743                             theModifiers,
744                             cloneExprs);
745 }
746 
747 
748 /*******************************************************************************
749 
750 ********************************************************************************/
materialize_clause(static_context * sctx,CompilerCB * ccb,const QueryLoc & loc)751 materialize_clause::materialize_clause(
752     static_context* sctx,
753     CompilerCB* ccb,
754     const QueryLoc& loc)
755   :
756   flwor_clause(sctx, ccb, loc, flwor_clause::materialize_clause)
757 {
758 }
759 
760 
clone(expr::substitution_t & subst) const761 flwor_clause* materialize_clause::clone(expr::substitution_t& subst) const
762 {
763   // we will reach here under the following scenario:
764   // 1. We do plan seriazation
765   // 2. getPlan is called on udf A; this causes a mat clause to be created
766   //    during the codegen on A's body
767   // 3. getPlan is called on udf B, which invokes A, and A's body is
768   //    inlined (and as a result cloned) inside B's body.
769   return theCCB->theEM->create_materialize_clause(theContext, get_loc());
770 }
771 
772 
773 /*******************************************************************************
774 
775 ********************************************************************************/
count_clause(static_context * sctx,CompilerCB * ccb,const QueryLoc & loc,var_expr * var)776 count_clause::count_clause(
777     static_context* sctx,
778     CompilerCB* ccb,
779     const QueryLoc& loc,
780     var_expr* var)
781   :
782   flwor_clause(sctx, ccb, loc, flwor_clause::count_clause),
783   theVarExpr(var)
784 {
785 }
786 
787 
~count_clause()788 count_clause::~count_clause()
789 {
790   if (theVarExpr != NULL)
791     theVarExpr->set_flwor_clause(NULL);
792 }
793 
794 
clone(expr::substitution_t & subst) const795 flwor_clause* count_clause::clone(expr::substitution_t& subst) const
796 {
797   ExprManager* exprMgr = theVarExpr->get_ccb()->theEM;
798 
799   var_expr* cloneVar = exprMgr->create_var_expr(*theVarExpr);
800   subst[theVarExpr] = cloneVar;
801 
802   return theCCB->theEM->create_count_clause(theContext, get_loc(), cloneVar);
803 }
804 
805 
806 /*******************************************************************************
807 
808 ********************************************************************************/
where_clause(static_context * sctx,CompilerCB * ccb,const QueryLoc & loc,expr * where)809 where_clause::where_clause(
810     static_context* sctx,
811     CompilerCB* ccb,
812     const QueryLoc& loc,
813     expr* where)
814   :
815   flwor_clause(sctx, ccb, loc, flwor_clause::where_clause),
816   theWhereExpr(where)
817 {
818   expr::checkSimpleExpr(theWhereExpr);
819 }
820 
821 
set_expr(expr * where)822 void where_clause::set_expr(expr* where)
823 {
824   theWhereExpr = where;
825 }
826 
827 
clone(expr::substitution_t & subst) const828 flwor_clause* where_clause::clone(expr::substitution_t& subst) const
829 {
830   expr* cloneExpr = theWhereExpr->clone(subst);
831 
832   return theCCB->theEM->create_where_clause(theContext, get_loc(), cloneExpr);
833 }
834 
835 
836 /*******************************************************************************
837 
838 ********************************************************************************/
flwor_expr(CompilerCB * ccb,static_context * sctx,const QueryLoc & loc,bool general)839 flwor_expr::flwor_expr(
840     CompilerCB* ccb,
841     static_context* sctx,
842     const QueryLoc& loc,
843     bool general)
844   :
845   expr(ccb, sctx, loc, (general ? gflwor_expr_kind : flwor_expr_kind)),
846   theIsGeneral(general),
847   theHasSequentialClauses(false),
848   theReturnExpr(NULL)
849 {
850   theScriptingKind = SIMPLE_EXPR;
851 }
852 
853 
854 /*******************************************************************************
855 
856 ********************************************************************************/
get_clause(csize i) const857 flwor_clause* flwor_expr::get_clause(csize i) const
858 {
859   assert(i < theClauses.size());
860 
861   return theClauses[i];
862 }
863 
864 
865 /*******************************************************************************
866 
867 ********************************************************************************/
remove_clause(csize pos)868 void flwor_expr::remove_clause(csize pos)
869 {
870   assert(pos < theClauses.size());
871 
872   if (theClauses[pos]->theFlworExpr == this)
873     theClauses[pos]->theFlworExpr = NULL;
874 
875   theClauses.erase(theClauses.begin() + pos);
876 }
877 
878 
879 /*******************************************************************************
880 
881 ********************************************************************************/
add_clause(flwor_clause * c,bool computeScriptingKind)882 void flwor_expr::add_clause(flwor_clause* c, bool computeScriptingKind)
883 {
884   theClauses.push_back(c);
885   c->theFlworExpr = this;
886 
887   if (computeScriptingKind)
888     compute_scripting_kind();
889 }
890 
891 
892 /*******************************************************************************
893 
894 ********************************************************************************/
add_clause(csize pos,flwor_clause * c)895 void flwor_expr::add_clause(csize pos, flwor_clause* c)
896 {
897   theClauses.insert(theClauses.begin() + pos, c);
898   c->theFlworExpr = this;
899 
900   compute_scripting_kind();
901 }
902 
903 
904 /*******************************************************************************
905 
906 ********************************************************************************/
add_where(expr * e)907 void flwor_expr::add_where(expr* e)
908 {
909   where_clause* whereClause = theCCB->theEM->
910   create_where_clause(theSctx, e->get_loc(), e);
911 
912   add_clause(whereClause);
913 }
914 
915 
916 /*******************************************************************************
917   For simple flwor only. If a where clause exists already, replace its expr
918   with the given expr. Otherwise, add a where clause with the given expr.
919 ********************************************************************************/
set_where(expr * e)920 void flwor_expr::set_where(expr* e)
921 {
922   ZORBA_ASSERT(e != NULL);
923 
924   csize numClauses = num_clauses();
925   csize i;
926 
927   for (i = 0; i < numClauses; ++i)
928   {
929     if (theClauses[i]->get_kind() != flwor_clause::for_clause &&
930         theClauses[i]->get_kind() != flwor_clause::let_clause)
931     {
932       break;
933     }
934   }
935 
936   if (i == numClauses)
937   {
938     add_where(e);
939     return;
940   }
941 
942   if (theClauses[i]->get_kind() == flwor_clause::where_clause)
943   {
944     where_clause* wc = reinterpret_cast<where_clause*>(theClauses[i]);
945     wc->set_expr(e);
946     return;
947   }
948 
949   where_clause* wc = theCCB->theEM->create_where_clause(theSctx, e->get_loc(), e);
950   theClauses.insert(theClauses.begin() + i, wc);
951   wc->theFlworExpr = this;
952 }
953 
954 
955 /*******************************************************************************
956   For simple flwor only.
957 ********************************************************************************/
remove_where_clause()958 void flwor_expr::remove_where_clause()
959 {
960   csize numClauses = num_clauses();
961   for (csize i = 0; i < numClauses; ++i)
962   {
963     if (theClauses[i]->get_kind() == flwor_clause::where_clause)
964     {
965       theClauses[i]->theFlworExpr = NULL;
966       theClauses.erase(theClauses.begin() + i);
967       return;
968     }
969   }
970 }
971 
972 
973 /*******************************************************************************
974   For simple flwor only.
975 ********************************************************************************/
get_where() const976 expr* flwor_expr::get_where() const
977 {
978   csize numClauses = num_clauses();
979   for (csize i = 0; i < numClauses; ++i)
980   {
981     if (theClauses[i]->get_kind() == flwor_clause::where_clause)
982       return reinterpret_cast<where_clause*>(theClauses[i])->get_expr();
983   }
984 
985   return NULL;
986 }
987 
988 
989 /*******************************************************************************
990   For simple flwor only.
991 ********************************************************************************/
get_group_clause() const992 group_clause* flwor_expr::get_group_clause() const
993 {
994   csize numClauses = num_clauses();
995   for (csize i = 0; i < numClauses; ++i)
996   {
997     if (theClauses[i]->get_kind() == flwor_clause::group_clause)
998       return reinterpret_cast<group_clause*>(theClauses[i]);
999   }
1000 
1001   return NULL;
1002 }
1003 
1004 
1005 /*******************************************************************************
1006   For simple flwor only.
1007 ********************************************************************************/
get_order_clause() const1008 orderby_clause* flwor_expr::get_order_clause() const
1009 {
1010   csize numClauses = num_clauses();
1011   for (csize i = 0; i < numClauses; ++i)
1012   {
1013     if (theClauses[i]->get_kind() == flwor_clause::order_clause)
1014       return reinterpret_cast<orderby_clause*>(theClauses[i]);
1015   }
1016 
1017   return NULL;
1018 }
1019 
1020 
1021 /*******************************************************************************
1022   For simple flwor only.
1023 ********************************************************************************/
num_forlet_clauses()1024 csize flwor_expr::num_forlet_clauses()
1025 {
1026   csize num = 0;
1027   csize numClauses = num_clauses();
1028   for (csize i = 0; i < numClauses; ++i)
1029   {
1030     const flwor_clause* c = theClauses[i];
1031 
1032     if (c->get_kind() == flwor_clause::for_clause ||
1033         c->get_kind() == flwor_clause::let_clause)
1034     {
1035       ++num;
1036     }
1037   }
1038 
1039   return num;
1040 }
1041 
1042 
1043 /*******************************************************************************
1044 
1045 ********************************************************************************/
defines_variable(const var_expr * v) const1046 long flwor_expr::defines_variable(const var_expr* v) const
1047 {
1048   const flwor_clause* varClause = v->get_flwor_clause();
1049 
1050   if (varClause == NULL)
1051     return -1;
1052 
1053   csize numClauses = theClauses.size();
1054 
1055   for (csize i = 0; i < numClauses; ++i)
1056   {
1057     if (theClauses[i] == varClause)
1058       return i;
1059   }
1060 
1061   return -1;
1062 }
1063 
1064 
1065 /*******************************************************************************
1066   Put in the given vector the var_exprs for the variables defined by this flwor
1067   expr.
1068 ********************************************************************************/
get_vars_defined(std::vector<var_expr * > & varExprs) const1069 void flwor_expr::get_vars_defined(std::vector<var_expr*>& varExprs) const
1070 {
1071   csize numClauses = theClauses.size();
1072 
1073   for (csize i = 0; i < numClauses; ++i)
1074   {
1075     const flwor_clause* c = theClauses[i];
1076 
1077     if (c->get_kind() == flwor_clause::for_clause)
1078     {
1079       const for_clause* fc = static_cast<const for_clause *>(c);
1080 
1081       varExprs.push_back(fc->get_var());
1082 
1083       if (fc->get_pos_var())
1084         varExprs.push_back(fc->get_pos_var());
1085     }
1086     else if (c->get_kind() == flwor_clause::let_clause)
1087     {
1088       const let_clause* lc = static_cast<const let_clause *>(c);
1089 
1090       varExprs.push_back(lc->get_var());
1091     }
1092     else if (c->get_kind() == flwor_clause::window_clause)
1093     {
1094       const window_clause* wc = static_cast<const window_clause *>(c);
1095 
1096       varExprs.push_back(wc->get_var());
1097 
1098       const flwor_wincond* startCond = wc->get_win_start();
1099       const flwor_wincond* stopCond = wc->get_win_stop();
1100       const flwor_wincond::vars& startVars = startCond->get_out_vars();
1101       const flwor_wincond::vars& stopVars = stopCond->get_out_vars();
1102 
1103       if (startVars.posvar) varExprs.push_back(startVars.posvar);
1104       if (startVars.curr) varExprs.push_back(startVars.curr);
1105       if (startVars.prev) varExprs.push_back(startVars.prev);
1106       if (startVars.next) varExprs.push_back(startVars.next);
1107 
1108       if (stopVars.posvar) varExprs.push_back(stopVars.posvar);
1109       if (stopVars.curr) varExprs.push_back(stopVars.curr);
1110       if (stopVars.prev) varExprs.push_back(stopVars.prev);
1111       if (stopVars.next) varExprs.push_back(stopVars.next);
1112     }
1113   }
1114 }
1115 
1116 
1117 /*******************************************************************************
1118 
1119 ********************************************************************************/
compute_scripting_kind()1120 void flwor_expr::compute_scripting_kind()
1121 {
1122   ulong numClauses = num_clauses();
1123 
1124   for (ulong i = 0; i < numClauses; ++i)
1125   {
1126     const flwor_clause* c = theClauses[i];
1127     flwor_clause::ClauseKind k = c->get_kind();
1128 
1129     if (k == flwor_clause::for_clause ||
1130         k == flwor_clause::let_clause ||
1131         k == flwor_clause::window_clause)
1132     {
1133       const forletwin_clause* c2 = static_cast<const forletwin_clause*>(c);
1134 
1135       theScriptingKind |= c2->get_expr()->get_scripting_detail();
1136 
1137       if (c2->get_expr()->is_sequential())
1138         theHasSequentialClauses = true;
1139     }
1140   }
1141 
1142   const expr* ret = get_return_expr();
1143   if (ret)
1144     theScriptingKind |= ret->get_scripting_detail();
1145 
1146   if (is_sequential(theScriptingKind))
1147   {
1148     theScriptingKind &= ~SIMPLE_EXPR;
1149     theScriptingKind &= ~VACUOUS_EXPR;
1150   }
1151 
1152   if (theScriptingKind & UPDATING_EXPR)
1153   {
1154     theScriptingKind &= ~SIMPLE_EXPR;
1155     theScriptingKind &= ~VACUOUS_EXPR;
1156   }
1157 
1158   if (theScriptingKind & VACUOUS_EXPR)
1159   {
1160     if (ret && ret->is_vacuous())
1161       theScriptingKind &= ~SIMPLE_EXPR;
1162     else
1163       theScriptingKind &= ~VACUOUS_EXPR;
1164   }
1165 
1166   checkScriptingKind();
1167 }
1168 
1169 
1170 /*******************************************************************************
1171 
1172 ********************************************************************************/
cloneImpl(substitution_t & subst) const1173 expr* flwor_expr::cloneImpl(substitution_t& subst) const
1174 {
1175   ulong numClauses = num_clauses();
1176 
1177   flwor_expr* cloneFlwor = theCCB->theEM->create_flwor_expr(theSctx, get_loc(), theIsGeneral);
1178 
1179   for (ulong i = 0; i < numClauses; ++i)
1180   {
1181     flwor_clause* cloneClause = theClauses[i]->clone(subst);
1182 
1183     cloneFlwor->add_clause(cloneClause, false);
1184   }
1185 
1186   cloneFlwor->set_return_expr(theReturnExpr->clone(subst));
1187 
1188   return cloneFlwor;
1189 }
1190 
1191 
1192 } // namespace zorba
1193 /* vim:set et sw=2 ts=2: */
1194