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/expression/expr_base.h"
19 #include "compiler/expression/expr.h"
20 #include "compiler/expression/fo_expr.h"
21 #include "compiler/expression/flwor_expr.h"
22 #include "compiler/expression/script_exprs.h"
23 #include "compiler/expression/path_expr.h"
24 #include "compiler/expression/expr_iter.h"
25 #include "compiler/expression/expr_visitor.h"
26 #include "compiler/expression/expr_manager.h"
27
28 #include "compiler/api/compilercb.h"
29
30 #include "functions/function.h"
31 #include "functions/library.h"
32 #include "functions/func_errors_and_diagnostics.h"
33
34 #include "types/root_typemanager.h"
35 #include "types/typeops.h"
36
37 #include "system/globalenv.h"
38
39 #include "diagnostics/xquery_diagnostics.h"
40 #include "diagnostics/assert.h"
41
42
43 namespace zorba
44 {
45
46
47 #define DEBUG_RT(e, t) t
48
49 #ifndef DEBUG_RT
50 #define DEBUG_RT(e, t) print_expr_and_type(e, t)
51
print_expr_and_type(expr * e,xqtref_t t)52 static xqtref_t print_expr_and_type(expr* e, xqtref_t t)
53 {
54 if (Properties::instance()->printStaticTypes())
55 {
56 std::cout << "Return type for " << e << ":\n";
57 e->put(std::cout);
58 std::cout << " => " << t->toString() << std::endl;
59 }
60 return t;
61 }
62
63 #endif
64
65
66 typedef std::set<const var_expr *> var_ptr_set;
67
68
69 /////////////////////////////////////////////////////////////////////////////////
70 // //
71 // Base expr class //
72 // //
73 /////////////////////////////////////////////////////////////////////////////////
74
75 /*******************************************************************************
76
77 ********************************************************************************/
78 expr* expr::iter_end_expr = NULL;
79
80 expr** expr::iter_done = &expr::iter_end_expr;
81
82
83 /*******************************************************************************
84
85 ********************************************************************************/
is_sequential(unsigned short theScriptingKind)86 bool expr::is_sequential(unsigned short theScriptingKind)
87 {
88 return (theScriptingKind & (VAR_SETTING_EXPR |
89 APPLYING_EXPR |
90 EXITING_EXPR |
91 BREAKING_EXPR |
92 SEQUENTIAL_FUNC_EXPR)) != 0;
93 }
94
95
checkNonUpdating(const expr * e)96 void expr::checkNonUpdating(const expr* e)
97 {
98 if (e != 0 && e->is_updating())
99 {
100 throw XQUERY_EXCEPTION(err::XUST0001,
101 ERROR_PARAMS(ZED(XUST0001_Generic)),
102 ERROR_LOC(e->get_loc()));
103 }
104 }
105
106
checkSimpleExpr(const expr * e)107 void expr::checkSimpleExpr(const expr* e)
108 {
109 if (e != 0 && e->is_updating())
110 {
111 throw XQUERY_EXCEPTION(err::XUST0001,
112 ERROR_PARAMS(ZED(XUST0001_Generic)),
113 ERROR_LOC(e->get_loc()));
114 }
115
116 if (e != 0 && e->is_sequential())
117 {
118 throw XQUERY_EXCEPTION(zerr::XSST0006, ERROR_LOC(e->get_loc()));
119 }
120 }
121
122
123 /*******************************************************************************
124
125 ********************************************************************************/
expr(CompilerCB * ccb,static_context * sctx,const QueryLoc & loc,expr_kind_t k)126 expr::expr(CompilerCB* ccb, static_context* sctx, const QueryLoc& loc, expr_kind_t k)
127 :
128 theSctx(sctx),
129 theLoc(loc),
130 theKind(k),
131 theFlags1(0),
132 theCCB(ccb)
133 {
134 theScriptingKind = UNKNOWN_SCRIPTING_KIND;
135
136 // This is the default. The constructors for certain exprs set different values.
137 setNonDiscardable(ANNOTATION_FALSE);
138 setUnfoldable(ANNOTATION_FALSE);
139 }
140
141
142 /*******************************************************************************
143
144 ********************************************************************************/
~expr()145 expr::~expr()
146 {
147 }
148
149
150 /*******************************************************************************
151
152 ********************************************************************************/
get_type_manager() const153 TypeManager* expr::get_type_manager() const
154 {
155 return theSctx->get_typemanager();
156 }
157
158
159 /*******************************************************************************
160
161 ********************************************************************************/
is_updating() const162 bool expr::is_updating() const
163 {
164 assert(theScriptingKind != UNKNOWN_SCRIPTING_KIND);
165
166 return (theScriptingKind & UPDATING_EXPR) != 0;
167 }
168
169
is_sequential() const170 bool expr::is_sequential() const
171 {
172 assert(theScriptingKind != UNKNOWN_SCRIPTING_KIND);
173
174 return is_sequential(theScriptingKind);
175 }
176
177
is_vacuous() const178 bool expr::is_vacuous() const
179 {
180 assert(theScriptingKind != UNKNOWN_SCRIPTING_KIND);
181
182 return theScriptingKind == VACUOUS_EXPR;
183 }
184
185
is_simple() const186 bool expr::is_simple() const
187 {
188 assert(theScriptingKind != UNKNOWN_SCRIPTING_KIND);
189
190 return theScriptingKind == SIMPLE_EXPR;
191 }
192
193
is_updating_or_vacuous() const194 bool expr::is_updating_or_vacuous() const
195 {
196 return (is_updating() || is_vacuous());
197 }
198
199
200 /*******************************************************************************
201
202 ********************************************************************************/
set_not_exiting()203 void expr::set_not_exiting()
204 {
205 theScriptingKind &= ~EXITING_EXPR;
206
207 if (theScriptingKind == UNKNOWN_SCRIPTING_KIND)
208 {
209 theScriptingKind = SIMPLE_EXPR;
210 }
211 }
212
213
214 /*******************************************************************************
215
216 ********************************************************************************/
checkScriptingKind() const217 void expr::checkScriptingKind() const
218 {
219 if (is_updating() && is_sequential())
220 {
221 throw XQUERY_EXCEPTION(zerr::XSST0005, ERROR_LOC(get_loc()));
222 }
223
224 #ifndef NDEBUG
225 assert(theScriptingKind != UNKNOWN_SCRIPTING_KIND);
226
227 if (theScriptingKind & VACUOUS_EXPR)
228 assert(theScriptingKind == VACUOUS_EXPR);
229
230 if (theScriptingKind & SIMPLE_EXPR)
231 assert(theScriptingKind == SIMPLE_EXPR);
232
233 if (theScriptingKind & UPDATING_EXPR)
234 assert(theScriptingKind == UPDATING_EXPR);
235 #endif
236 }
237
238
239 /*******************************************************************************
240
241 ********************************************************************************/
clone() const242 expr* expr::clone() const
243 {
244 substitution_t subst;
245 return clone(subst);
246 }
247
248
clone(substitution_t & subst) const249 expr* expr::clone(substitution_t& subst) const
250 {
251 expr* lNewExpr = cloneImpl(subst);
252
253 if (containsPragma())
254 {
255 lNewExpr->setContainsPragma(ANNOTATION_TRUE);
256 std::vector<pragma*> lPragmas;
257 theCCB->lookup_pragmas(this, lPragmas);
258 for (size_t i = 0; i < lPragmas.size(); ++i)
259 {
260 theCCB->add_pragma(lNewExpr, lPragmas[i]);
261 }
262 }
263 return lNewExpr;
264 }
265
266
cloneImpl(substitution_t & subst) const267 expr* expr::cloneImpl(substitution_t& subst) const
268 {
269 throw XQUERY_EXCEPTION(zerr::ZXQP0003_INTERNAL_ERROR, ERROR_LOC(get_loc()));
270 }
271
272
273 /*******************************************************************************
274
275 ********************************************************************************/
accept_children(expr_visitor & v)276 void expr::accept_children(expr_visitor& v)
277 {
278 ExprIterator iter(this);
279 while (!iter.done())
280 {
281 if (**iter != NULL)
282 (**iter)->accept(v);
283
284 iter.next();
285 }
286 }
287
288
289 /*******************************************************************************
290
291 ********************************************************************************/
toString() const292 std::string expr::toString() const
293 {
294 std::ostringstream oss;
295 put(oss);
296 return oss.str();
297 }
298
299
300 /*******************************************************************************
301
302 ********************************************************************************/
setFreeVars(FreeVars & s)303 void expr::setFreeVars(FreeVars& s)
304 {
305 theFreeVars.swap(s);
306 }
307
308
309 /*******************************************************************************
310
311 ********************************************************************************/
clear_annotations()312 void expr::clear_annotations()
313 {
314 theFreeVars.clear();
315
316 if (getProducesSortedNodes() != ANNOTATION_TRUE_FIXED)
317 setProducesSortedNodes(ANNOTATION_UNKNOWN);
318
319 if (getProducesDistinctNodes() != ANNOTATION_TRUE_FIXED)
320 setProducesDistinctNodes(ANNOTATION_UNKNOWN);
321
322 if (getIgnoresSortedNodes() != ANNOTATION_TRUE_FIXED)
323 setIgnoresSortedNodes(ANNOTATION_UNKNOWN);
324
325 if (getIgnoresDuplicateNodes() != ANNOTATION_TRUE_FIXED)
326 setIgnoresDuplicateNodes(ANNOTATION_UNKNOWN);
327
328 if (getNonDiscardable() != ANNOTATION_TRUE_FIXED)
329 setNonDiscardable(ANNOTATION_UNKNOWN);
330
331 if (getUnfoldable() != ANNOTATION_TRUE_FIXED)
332 setUnfoldable(ANNOTATION_UNKNOWN);
333
334 //theFlags1 = 0;
335 //setNonDiscardable(ANNOTATION_FALSE);
336 //setUnfoldable(ANNOTATION_FALSE);
337
338 ExprIterator iter(this);
339 while (!iter.done())
340 {
341 (**iter)->clear_annotations();
342 iter.next();
343 }
344 }
345
346
347
348 /*******************************************************************************
349 Returns true if the expr contains a nondeterministic function call
350 ********************************************************************************/
is_nondeterministic() const351 bool expr::is_nondeterministic() const
352 {
353 if (get_expr_kind() == fo_expr_kind)
354 {
355 const fo_expr* fo = static_cast<const fo_expr*>(this);
356 if (!fo->get_func()->isDeterministic())
357 return true;
358 }
359
360 ExprConstIterator iter(this);
361 while(!iter.done())
362 {
363 const expr* ce = iter.get_expr();
364 if (ce != NULL && ce->is_nondeterministic())
365 return true;
366
367 iter.next();
368 }
369
370 return false;
371 }
372
373
374 /*******************************************************************************
375 Annotation : produces-sorted-nodes
376 Tells whether the expression produces nodes in document order or not.
377 ********************************************************************************/
getProducesSortedNodes() const378 BoolAnnotationValue expr::getProducesSortedNodes() const
379 {
380 return (BoolAnnotationValue)(theFlags1 & PRODUCES_SORTED_NODES_MASK);
381 }
382
383
setProducesSortedNodes(BoolAnnotationValue v)384 void expr::setProducesSortedNodes(BoolAnnotationValue v)
385 {
386 theFlags1 &= ~PRODUCES_SORTED_NODES_MASK;
387 theFlags1 |= v;
388 }
389
390
producesSortedNodes() const391 bool expr::producesSortedNodes() const
392 {
393 return (getProducesSortedNodes() == ANNOTATION_TRUE);
394 }
395
396
397 /*******************************************************************************
398 Annotation : produces-distinct-nodes
399 Tells whether the expression produces distinct nodes or not.
400 ********************************************************************************/
getProducesDistinctNodes() const401 BoolAnnotationValue expr::getProducesDistinctNodes() const
402 {
403 return (BoolAnnotationValue)
404 ((theFlags1 & PRODUCES_DISTINCT_NODES_MASK) >> PRODUCES_DISTINCT_NODES);
405 }
406
407
setProducesDistinctNodes(BoolAnnotationValue v)408 void expr::setProducesDistinctNodes(BoolAnnotationValue v)
409 {
410 theFlags1 &= ~PRODUCES_DISTINCT_NODES_MASK;
411 theFlags1 |= (v << PRODUCES_DISTINCT_NODES);
412 }
413
414
producesDistinctNodes() const415 bool expr::producesDistinctNodes() const
416 {
417 return (getProducesDistinctNodes() == ANNOTATION_TRUE);
418 }
419
420
421 /*******************************************************************************
422 Annotation : ignores-sorted-nodes
423 Tells whether the expression needs to produce nodes in doc order or not.
424 ********************************************************************************/
getIgnoresSortedNodes() const425 BoolAnnotationValue expr::getIgnoresSortedNodes() const
426 {
427 return (BoolAnnotationValue)
428 ((theFlags1 & IGNORES_SORTED_NODES_MASK) >> IGNORES_SORTED_NODES);
429 }
430
431
setIgnoresSortedNodes(BoolAnnotationValue v)432 void expr::setIgnoresSortedNodes(BoolAnnotationValue v)
433 {
434 theFlags1 &= ~IGNORES_SORTED_NODES_MASK;
435 theFlags1 |= (v << IGNORES_SORTED_NODES);
436 }
437
438
ignoresSortedNodes() const439 bool expr::ignoresSortedNodes() const
440 {
441 return (getIgnoresSortedNodes() == ANNOTATION_TRUE);
442 }
443
444
445 /*******************************************************************************
446 Annotation : ignores-duplicates-nodes
447 Tells whether the expression needs to produce distinct nodes or not.
448 ********************************************************************************/
getIgnoresDuplicateNodes() const449 BoolAnnotationValue expr::getIgnoresDuplicateNodes() const
450 {
451 return (BoolAnnotationValue)
452 ((theFlags1 & IGNORES_DUPLICATE_NODES_MASK) >> IGNORES_DUPLICATE_NODES);
453 }
454
455
setIgnoresDuplicateNodes(BoolAnnotationValue v)456 void expr::setIgnoresDuplicateNodes(BoolAnnotationValue v)
457 {
458 theFlags1 &= ~IGNORES_DUPLICATE_NODES_MASK;
459 theFlags1 |= (v << IGNORES_DUPLICATE_NODES);
460 }
461
462
ignoresDuplicateNodes() const463 bool expr::ignoresDuplicateNodes() const
464 {
465 return (getIgnoresDuplicateNodes() == ANNOTATION_TRUE);
466 }
467
468
469 /*******************************************************************************
470
471 ********************************************************************************/
getNonDiscardable() const472 BoolAnnotationValue expr::getNonDiscardable() const
473 {
474 return (BoolAnnotationValue)
475 ((theFlags1 & NON_DISCARDABLE_MASK) >> NON_DISCARDABLE);
476 }
477
478
setNonDiscardable(BoolAnnotationValue v)479 void expr::setNonDiscardable(BoolAnnotationValue v)
480 {
481 theFlags1 &= ~NON_DISCARDABLE_MASK;
482 theFlags1 |= (v << NON_DISCARDABLE);
483 }
484
485
isNonDiscardable() const486 bool expr::isNonDiscardable() const
487 {
488 BoolAnnotationValue v = getNonDiscardable();
489 return (v == ANNOTATION_TRUE || v == ANNOTATION_TRUE_FIXED);
490 }
491
492
493 /*******************************************************************************
494
495 ********************************************************************************/
getUnfoldable() const496 BoolAnnotationValue expr::getUnfoldable() const
497 {
498 return (BoolAnnotationValue)
499 ((theFlags1 & UNFOLDABLE_MASK) >> UNFOLDABLE);
500 }
501
502
setUnfoldable(BoolAnnotationValue v)503 void expr::setUnfoldable(BoolAnnotationValue v)
504 {
505 theFlags1 &= ~UNFOLDABLE_MASK;
506 theFlags1 |= (v << UNFOLDABLE);
507 }
508
509
isUnfoldable() const510 bool expr::isUnfoldable() const
511 {
512 BoolAnnotationValue v = getUnfoldable();
513 return (v == ANNOTATION_TRUE || v == ANNOTATION_TRUE_FIXED);
514 }
515
516
517 /*******************************************************************************
518
519 ********************************************************************************/
getContainsRecursiveCall() const520 BoolAnnotationValue expr::getContainsRecursiveCall() const
521 {
522 return (BoolAnnotationValue)
523 ((theFlags1 & CONTAINS_RECURSIVE_CALL_MASK) >> CONTAINS_RECURSIVE_CALL);
524 }
525
526
setContainsRecursiveCall(BoolAnnotationValue v)527 void expr::setContainsRecursiveCall(BoolAnnotationValue v)
528 {
529 theFlags1 &= ~CONTAINS_RECURSIVE_CALL_MASK;
530 theFlags1 |= (v << CONTAINS_RECURSIVE_CALL);
531 }
532
533
containsRecursiveCall() const534 bool expr::containsRecursiveCall() const
535 {
536 BoolAnnotationValue v = getContainsRecursiveCall();
537 return (v == ANNOTATION_TRUE || v == ANNOTATION_TRUE_FIXED);
538 }
539
540
541 /*******************************************************************************
542
543 ********************************************************************************/
getInUnsafeContext() const544 BoolAnnotationValue expr::getInUnsafeContext() const
545 {
546 return (BoolAnnotationValue)
547 ((theFlags1 & IN_UNSAFE_CONTEXT_MASK) >> IN_UNSAFE_CONTEXT);
548 }
549
550
setInUnsafeContext(BoolAnnotationValue v)551 void expr::setInUnsafeContext(BoolAnnotationValue v)
552 {
553 theFlags1 &= ~IN_UNSAFE_CONTEXT_MASK;
554 theFlags1 |= (v << IN_UNSAFE_CONTEXT);
555 }
556
557
inUnsafeContext() const558 bool expr::inUnsafeContext() const
559 {
560 BoolAnnotationValue v = getInUnsafeContext();
561 return (v == ANNOTATION_TRUE || v == ANNOTATION_TRUE_FIXED);
562 }
563
564
565 /*******************************************************************************
566
567 ********************************************************************************/
getContainsPragma() const568 BoolAnnotationValue expr::getContainsPragma() const
569 {
570 return (BoolAnnotationValue)
571 ((theFlags1 & CONTAINS_PRAGMA_MASK) >> CONTAINS_PRAGMA);
572 }
573
574
setContainsPragma(BoolAnnotationValue v)575 void expr::setContainsPragma(BoolAnnotationValue v)
576 {
577 theFlags1 &= ~CONTAINS_PRAGMA_MASK;
578 theFlags1 |= (v << CONTAINS_PRAGMA);
579 }
580
581
containsPragma() const582 bool expr::containsPragma() const
583 {
584 BoolAnnotationValue v = getContainsPragma();
585 return (v == ANNOTATION_TRUE || v == ANNOTATION_TRUE_FIXED);
586 }
587
588
589 /*******************************************************************************
590 This annotation tells whether the expr must produce nodes that belong to
591 "standalone" trees or not. A tree is standalone if it does not contain
592 references to other trees. Such references are created when the optimizer
593 decides that it is ok to avoid copying the referenced subtree (as would be
594 required by required by a strict implementation of the spec, eg., during
595 node construction).
596 ********************************************************************************/
getMustCopyNodes() const597 BoolAnnotationValue expr::getMustCopyNodes() const
598 {
599 return (BoolAnnotationValue)
600 ((theFlags1 & MUST_COPY_NODES_MASK) >> MUST_COPY_NODES);
601 }
602
603
setMustCopyNodes(BoolAnnotationValue v)604 void expr::setMustCopyNodes(BoolAnnotationValue v)
605 {
606 theFlags1 &= ~MUST_COPY_NODES_MASK;
607 theFlags1 |= (v << MUST_COPY_NODES);
608 }
609
610
611 /*******************************************************************************
612 Return true if the expr does not reference any variables.
613 ********************************************************************************/
is_constant() const614 bool expr::is_constant() const
615 {
616 if (get_expr_kind() == var_expr_kind)
617 {
618 return false;
619 }
620
621 ExprConstIterator iter(this);
622 while (!iter.done())
623 {
624 if (!iter.get_expr()->is_constant())
625 {
626 return false;
627 }
628
629 iter.next();
630 }
631
632 return true;
633 }
634
635
636 /*******************************************************************************
637 Replace all references to "oldExpr" inside "e" with references to "newExpr".
638 ********************************************************************************/
replace_expr(expr * oldExpr,expr * newExpr)639 void expr::replace_expr(expr* oldExpr, expr* newExpr)
640 {
641 ExprIterator iter(this);
642 while (!iter.done())
643 {
644 if ((**iter) == oldExpr)
645 {
646 (**iter) = newExpr;
647 }
648 else
649 {
650 (**iter)->replace_expr(oldExpr, newExpr);
651 }
652
653 iter.next();
654 }
655 }
656
657
658 /*******************************************************************************
659 Return true if the given expr is a subexpr of "this".
660 ********************************************************************************/
contains_expr(const expr * e) const661 bool expr::contains_expr(const expr* e) const
662 {
663 ExprConstIterator iter(this);
664 while (!iter.done())
665 {
666 if (iter.get_expr() == e)
667 {
668 return true;
669 }
670 else if (iter.get_expr()->contains_expr(e))
671 {
672 return true;
673 }
674
675 iter.next();
676 }
677
678 return false;
679 }
680
681
682 /*******************************************************************************
683 Check if the expr tree rooted at e contains any node-constructor expr. If so,
684 e cannot be hoisted.
685 ********************************************************************************/
contains_node_construction() const686 bool expr::contains_node_construction() const
687 {
688 expr_kind_t kind = get_expr_kind();
689
690 if (kind == elem_expr_kind ||
691 kind == attr_expr_kind ||
692 kind == text_expr_kind ||
693 kind == doc_expr_kind ||
694 kind == pi_expr_kind)
695 {
696 return true;
697 }
698
699 ExprConstIterator iter(this);
700 while(!iter.done())
701 {
702 const expr* ce = iter.get_expr();
703 if (ce)
704 {
705 if (ce->contains_node_construction())
706 {
707 return true;
708 }
709 }
710 iter.next();
711 }
712 return false;
713 }
714
715
716 /*******************************************************************************
717
718 ********************************************************************************/
get_exprs_of_kind(expr_kind_t kind,bool deep,std::vector<expr * > & exprs) const719 void expr::get_exprs_of_kind(
720 expr_kind_t kind,
721 bool deep,
722 std::vector<expr*>& exprs) const
723 {
724 if (kind == get_expr_kind())
725 {
726 exprs.push_back(const_cast<expr*>(this));
727
728 if (!deep)
729 return;
730 }
731
732 ExprConstIterator iter(this);
733 while(!iter.done())
734 {
735 const expr* ce = iter.get_expr();
736 if (ce)
737 {
738 ce->get_exprs_of_kind(kind, deep, exprs);
739 }
740
741 iter.next();
742 }
743 }
744
745
746 /*******************************************************************************
747
748 ********************************************************************************/
get_fo_exprs_of_kind(FunctionConsts::FunctionKind kind,bool deep,std::vector<expr * > & exprs) const749 void expr::get_fo_exprs_of_kind(
750 FunctionConsts::FunctionKind kind,
751 bool deep,
752 std::vector<expr*>& exprs) const
753 {
754 if (get_expr_kind() == fo_expr_kind)
755 {
756 if (static_cast<const fo_expr*>(this)->get_func()->getKind() == kind)
757 {
758 exprs.push_back(const_cast<expr*>(this));
759
760 if (!deep)
761 return;
762 }
763 }
764
765 ExprConstIterator iter(this);
766 while(!iter.done())
767 {
768 const expr* ce = iter.get_expr();
769 if (ce)
770 {
771 ce->get_fo_exprs_of_kind(kind, deep, exprs);
772 }
773
774 iter.next();
775 }
776 }
777
778
779 /*******************************************************************************
780 If "this" is a var_expr or a wrapper_expr over a var_expr, return the var_expr;
781 otherwise return NULL.
782 ********************************************************************************/
get_var() const783 const var_expr* expr::get_var() const
784 {
785 expr_kind_t kind = get_expr_kind();
786 const expr* currExpr = this;
787
788 while (kind == wrapper_expr_kind)
789 {
790 const wrapper_expr* wrapperExpr = static_cast<const wrapper_expr*>(currExpr);
791 currExpr = wrapperExpr->get_expr();
792 kind = currExpr->get_expr_kind();
793 }
794
795 if (kind == var_expr_kind)
796 return static_cast<const var_expr*>(currExpr);
797
798 return NULL;
799 }
800
801
802 /*******************************************************************************
803 This method tries to see if "this" is a map with respect to the given expr.
804
805 Let E1 be an expr and E2 be a sub-expr of E1, Then, E1 is a map w.r.t. E2 iff
806
807 for each value v2 of E2 with a cardinality N >= 1:
808
809 v1 == CONCATENATE { v1i, i = 1, ..., N }, where
810
811 v1 is the value of E1 when E2 is bound to v2 and
812 v1i is the value of E1 when E2 is bound to the i-th item in v2
813
814 If the method returns true, then "this" is guaranteed to be a map. If it
815 returns false, it may still be a map, but this algorithm could not determine
816 that.
817 ********************************************************************************/
is_map(expr * e,static_context * sctx) const818 bool expr::is_map(expr* e, static_context* sctx) const
819 {
820 if (is_updating())
821 return false;
822
823 xqtref_t type = e->get_return_type();
824 TypeConstants::quantifier_t q = type->get_quantifier();
825
826 if (q == TypeConstants::QUANT_ONE || q == TypeConstants::QUANT_QUESTION)
827 return true;
828
829 bool found = false;
830
831 return is_map_internal(e, found);
832 }
833
834
is_map_internal(const expr * e,bool & found) const835 bool expr::is_map_internal(const expr* e, bool& found) const
836 {
837 if (found)
838 return true;
839
840 if (this == e)
841 {
842 found = true;
843 return true;
844 }
845
846 switch(get_expr_kind())
847 {
848 #ifdef ZORBA_WITH_DEBUGGER
849 case debugger_expr_kind:
850 {
851 const debugger_expr* debugExpr = static_cast<const debugger_expr *>(this);
852 return debugExpr->get_expr()->is_map_internal(e, found);
853 }
854 #endif
855
856 case order_expr_kind:
857 {
858 const order_expr* orderExpr = static_cast<const order_expr *>(this);
859 return orderExpr->get_expr()->is_map_internal(e, found);
860 }
861
862 case wrapper_expr_kind:
863 {
864 const wrapper_expr* wrapperExpr = static_cast<const wrapper_expr *>(this);
865 return wrapperExpr->get_expr()->is_map_internal(e, found);
866 }
867
868 case const_expr_kind:
869 case var_expr_kind:
870 return true;
871
872 case fo_expr_kind:
873 {
874 const fo_expr* foExpr = static_cast<const fo_expr *>(this);
875 const function* func = foExpr->get_func();
876 csize numArgs = foExpr->num_args();
877
878 for (csize i = 0; i < numArgs; ++i)
879 {
880 const expr* argExpr = foExpr->get_arg(i);
881
882 if (func->isMap(i))
883 {
884 if (argExpr->is_map_internal(e, found) && found)
885 {
886 return true;
887 }
888 else if (found)
889 {
890 return false;
891 }
892 }
893 else if (argExpr->contains_expr(e))
894 {
895 return false;
896 }
897 }
898
899 return true;
900 }
901
902 case flwor_expr_kind:
903 case gflwor_expr_kind:
904 {
905 const flwor_expr* flworExpr = static_cast<const flwor_expr *>(this);
906 bool haveOrderBy = false;
907 csize numClauses = flworExpr->num_clauses();
908
909 for (csize i = 0; i < numClauses; ++i)
910 {
911 const flwor_clause* clause = flworExpr->get_clause(i);
912
913 switch (clause->get_kind())
914 {
915 case flwor_clause::for_clause:
916 {
917 if (found)
918 break;
919
920 if (clause->get_expr()->is_map_internal(e, found) && found)
921 {
922 break;
923 }
924 else if (found)
925 {
926 return false;
927 }
928
929 break;
930 }
931 case flwor_clause::let_clause:
932 case flwor_clause::where_clause:
933 {
934 if (found)
935 break;
936
937 if (clause->get_expr()->contains_expr(e))
938 return false;
939
940 break;
941 }
942 case flwor_clause::window_clause:
943 {
944 if (found)
945 break;
946
947 if (clause->get_expr()->contains_expr(e))
948 return false;
949
950 const window_clause* wc = static_cast<const window_clause*>(clause);
951 flwor_wincond* startCond = wc->get_win_start();
952 flwor_wincond* stopCond = wc->get_win_stop();
953
954 if (startCond && startCond->get_cond()->contains_expr(e))
955 return false;
956
957 if (stopCond && stopCond->get_cond()->contains_expr(e))
958 return false;
959
960 break;
961 }
962 case flwor_clause::group_clause:
963 case flwor_clause::count_clause:
964 {
965 if (found)
966 return false;
967
968 break;
969 }
970 case flwor_clause::order_clause:
971 {
972 if (found)
973 return false;
974
975 const orderby_clause* obc = static_cast<const orderby_clause*>(clause);
976
977 csize numColumns = obc->num_columns();
978 for (csize k = 0; k < numColumns; ++k)
979 {
980 if (obc->get_column_expr(k)->contains_expr(e))
981 return false;
982 }
983
984 haveOrderBy = true;
985 break;
986 }
987 default:
988 ZORBA_ASSERT(false);
989 }
990 } // for each clause
991
992 if (found)
993 {
994 return true;
995 }
996 else
997 {
998 const expr* retExpr = flworExpr->get_return_expr();
999
1000 if (retExpr->is_map_internal(e, found) && found && !haveOrderBy)
1001 {
1002 // TODO: actually we should return true only if the ordering mode for
1003 // the return expr is unordered.
1004 return true;
1005 }
1006 else if (!found)
1007 {
1008 return true;
1009 }
1010 else
1011 {
1012 return false;
1013 }
1014 }
1015 }
1016
1017 case if_expr_kind:
1018 {
1019 const if_expr* ifExpr = static_cast<const if_expr*>(this);
1020
1021 if (ifExpr->get_cond_expr()->contains_expr(e))
1022 return false;
1023
1024 if (ifExpr->get_then_expr()->is_map_internal(e, found) &&
1025 ifExpr->get_else_expr()->is_map_internal(e, found))
1026 return true;
1027
1028 return false;
1029 }
1030
1031 case relpath_expr_kind:
1032 {
1033 const relpath_expr* pathExpr = static_cast<const relpath_expr*>(this);
1034 return (*pathExpr)[0]->is_map_internal(e, found);
1035 }
1036
1037 case treat_expr_kind:
1038 {
1039 const treat_expr* treatExpr = static_cast<const treat_expr*>(this);
1040 TypeConstants::quantifier_t q = treatExpr->get_target_type()->get_quantifier();
1041
1042 if (q == TypeConstants::QUANT_STAR || q == TypeConstants::QUANT_PLUS)
1043 {
1044 const expr* argExpr = treatExpr->get_input();
1045 return argExpr->is_map_internal(e, found);
1046 }
1047
1048 return false;
1049 }
1050
1051 case promote_expr_kind:
1052 {
1053 const promote_expr* promoteExpr = static_cast<const promote_expr*>(this);
1054 TypeConstants::quantifier_t q = promoteExpr->get_target_type()->get_quantifier();
1055
1056 if (q == TypeConstants::QUANT_STAR || q == TypeConstants::QUANT_PLUS)
1057 {
1058 const expr* argExpr = promoteExpr->get_input();
1059 return argExpr->is_map_internal(e, found);
1060 }
1061
1062 return false;
1063 }
1064
1065 case instanceof_expr_kind:
1066 case castable_expr_kind:
1067 case name_cast_expr_kind:
1068 case cast_expr_kind:
1069 case validate_expr_kind:
1070 {
1071 return !contains_expr(e);
1072 }
1073
1074 case doc_expr_kind:
1075 case elem_expr_kind:
1076 case attr_expr_kind:
1077 case text_expr_kind:
1078 case pi_expr_kind:
1079 #ifdef ZORBA_WITH_JSON
1080 case json_object_expr_kind:
1081 case json_direct_object_expr_kind:
1082 case json_array_expr_kind:
1083 #endif
1084 {
1085 return !contains_expr(e);
1086 }
1087
1088 case trycatch_expr_kind:
1089 case extension_expr_kind:
1090 {
1091 return !contains_expr(e);
1092 }
1093
1094 case transform_expr_kind:
1095 {
1096 const transform_expr* transformExpr = static_cast<const transform_expr*>(this);
1097
1098 if (transformExpr->getReturnExpr()->is_map_internal(e, found) && found)
1099 return true;
1100
1101 return !contains_expr(e);
1102 }
1103
1104 case eval_expr_kind:
1105 return false; // TODO
1106
1107 case var_decl_expr_kind:
1108 case var_set_expr_kind:
1109 {
1110 return !contains_expr(e);
1111 }
1112
1113 case apply_expr_kind:
1114 return false;
1115
1116 case block_expr_kind:
1117 case exit_expr_kind:
1118 case flowctl_expr_kind:
1119 case while_expr_kind:
1120 return false; // TODO
1121
1122 case exit_catcher_expr_kind:
1123 {
1124 const exit_catcher_expr* catcherExpr = static_cast<const exit_catcher_expr*>(this);
1125 return catcherExpr->get_expr()->is_map_internal(e, found);
1126 }
1127
1128 case insert_expr_kind:
1129 case delete_expr_kind:
1130 case rename_expr_kind:
1131 case replace_expr_kind:
1132 ZORBA_ASSERT(false);
1133
1134 default:
1135 ZORBA_ASSERT(false);
1136 }
1137
1138 return true;
1139 }
1140
1141
1142 /*******************************************************************************
1143
1144 ********************************************************************************/
get_function_kind() const1145 FunctionConsts::FunctionKind expr::get_function_kind() const
1146 {
1147 if (get_expr_kind() == fo_expr_kind)
1148 {
1149 return static_cast<const fo_expr*>(this)->get_func()->getKind();
1150 }
1151
1152 return FunctionConsts::FN_UNKNOWN;
1153 }
1154
1155
1156 /*******************************************************************************
1157 If "this" is a const expr that returns a qname, evaluate and return this
1158 qname. This method is used to extract the qname from the expression that is
1159 given as an arg to collection and index related functions.
1160 ********************************************************************************/
getQName(static_context * sctx) const1161 const store::Item* expr::getQName(static_context* sctx) const
1162 {
1163 RootTypeManager& rtm = GENV_TYPESYSTEM;
1164
1165 TypeManager* tm = sctx->get_typemanager();
1166
1167 const const_expr* qnameExpr = dynamic_cast<const const_expr*>(this);
1168
1169 if (qnameExpr != NULL)
1170 {
1171 xqtref_t valueType = tm->create_value_type(qnameExpr->get_val());
1172
1173 if (TypeOps::is_subtype(tm, *valueType, *rtm.QNAME_TYPE_ONE, get_loc()))
1174 {
1175 return qnameExpr->get_val();
1176 }
1177 }
1178 else if (get_expr_kind() == promote_expr_kind)
1179 {
1180 // We get here if the optimizer is turned off.
1181
1182 const promote_expr* promoteExpr = static_cast<const promote_expr*>(this);
1183
1184 const expr* argExpr = promoteExpr->get_input();
1185 const fo_expr* dataExpr = dynamic_cast<const fo_expr*>(argExpr);
1186
1187 if (dataExpr != NULL &&
1188 dataExpr->get_func()->getKind() == FunctionConsts::FN_DATA_1)
1189 {
1190 argExpr = dataExpr->get_arg(0);
1191 const const_expr* qnameExpr = dynamic_cast<const const_expr*>(argExpr);
1192
1193 if (qnameExpr != NULL)
1194 {
1195 xqtref_t valueType = tm->create_value_type(qnameExpr->get_val());
1196
1197 if (TypeOps::is_subtype(tm, *valueType, *rtm.QNAME_TYPE_ONE, get_loc()))
1198 {
1199 return qnameExpr->get_val();
1200 }
1201 }
1202 }
1203 }
1204
1205 return NULL;
1206 }
1207
1208
1209
1210 /*******************************************************************************
1211
1212 ********************************************************************************/
get_return_type_with_empty_input(const expr * input) const1213 xqtref_t expr::get_return_type_with_empty_input(const expr* input) const
1214 {
1215 expr* emptyExpr = theCCB->theEM->create_fo_expr(input->get_sctx(),
1216 QueryLoc::null,
1217 GET_BUILTIN_FUNCTION(OP_CONCATENATE_N));
1218 expr::substitution_t subst;
1219 subst[input] = emptyExpr;
1220
1221 expr* cloneExpr = clone(subst);
1222
1223 return cloneExpr->get_return_type();
1224 }
1225
1226
1227 } // namespace zorba
1228 /* vim:set et sw=2 ts=2: */
1229