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