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 <iostream>
19 #include <list>
20 #include <stack>
21 #include <vector>
22 
23 #include <zorba/config.h>
24 #include <zorba/diagnostic_list.h>
25 #include "diagnostics/assert.h"
26 
27 #include "util/hashmap32.h"
28 #include "util/stl_util.h"
29 #include "util/tracer.h"
30 
31 #include "system/globalenv.h"
32 #include "system/properties.h"
33 
34 #include "compiler/api/compilercb.h"
35 #include "compiler/codegen/plan_visitor.h"
36 #include "compiler/expression/expr.h"
37 #include "compiler/expression/expr_visitor.h"
38 #include "compiler/expression/flwor_expr.h"
39 #include "compiler/expression/fo_expr.h"
40 #include "compiler/expression/script_exprs.h"
41 #include "compiler/expression/json_exprs.h"
42 #include "compiler/expression/update_exprs.h"
43 #ifndef ZORBA_NO_FULL_TEXT
44 #include "compiler/expression/ft_expr.h"
45 #include "compiler/expression/ftnode.h"
46 #include "compiler/expression/ftnode_visitor.h"
47 #endif /* ZORBA_NO_FULL_TEXT */
48 #include "compiler/expression/function_item_expr.h"
49 #include "compiler/expression/path_expr.h"
50 #include "compiler/expression/var_expr.h"
51 #include "compiler/parser/parse_constants.h"
52 
53 #include "context/namespace_context.h"
54 #include "context/static_context.h"
55 #include "context/static_context_consts.h"
56 #include "context/dynamic_context.h"
57 
58 #include "runtime/visitors/printer_visitor_api.h"
59 #include "runtime/visitors/iterprinter.h"
60 #include "runtime/sequences/SequencesImpl.h"
61 #include "runtime/sequences/sequences.h"
62 #include "runtime/core/sequencetypes.h"
63 #include "runtime/core/item_iterator.h"
64 #include "runtime/core/var_iterators.h"
65 #include "runtime/core/constructors.h"
66 #include "runtime/json/json_constructors.h"
67 #include "runtime/core/apply_updates.h"
68 #include "runtime/core/path_iterators.h"
69 #include "runtime/core/nodeid_iterators.h"
70 #include "runtime/core/flwor_iterator.h"
71 #include "runtime/core/trycatch.h"
72 #include "runtime/errors_and_diagnostics/other_diagnostics.h"
73 #include "runtime/core/gflwor/common.h"
74 #include "runtime/core/gflwor/groupby_iterator.h"
75 #include "runtime/core/gflwor/tuplestream_iterator.h"
76 #include "runtime/core/gflwor/for_iterator.h"
77 #include "runtime/core/gflwor/outerfor_iterator.h"
78 #include "runtime/core/gflwor/let_iterator.h"
79 #include "runtime/core/gflwor/window_iterator.h"
80 #include "runtime/core/gflwor/where_iterator.h"
81 #include "runtime/core/gflwor/count_iterator.h"
82 #include "runtime/core/gflwor/tuplesource_iterator.h"
83 #include "runtime/core/gflwor/orderby_iterator.h"
84 #include "runtime/full_text/full_text.h"
85 #include "runtime/schema/schema.h"
86 #include "runtime/scripting/scripting.h"
87 #include "runtime/util/flowctl_exception.h"
88 #include "runtime/update/update.h"
89 #include "runtime/indexing/index_ddl.h"
90 #ifdef ZORBA_WITH_DEBUGGER
91 #include "runtime/debug/debug_iterator.h"
92 #endif
93 #include "runtime/eval/eval.h"
94 #include "runtime/function_item/function_item.h"
95 #include "runtime/function_item/function_item_iter.h"
96 #include "runtime/function_item/dynamic_fncall_iterator.h"
97 #include "runtime/misc/materialize.h"
98 
99 #ifdef ZORBA_WITH_DEBUGGER
100 #include "debugger/debugger_commons.h"
101 #endif
102 
103 #include "functions/function.h"
104 #include "functions/udf.h"
105 #include "functions/library.h"
106 
107 #include "types/typeops.h"
108 
109 #include "store/api/store.h"
110 #include "store/api/item.h"
111 #include "store/api/item_factory.h"
112 #include "store/api/iterator.h"
113 
114 
115 //#define XQUF_STATIC_TYPING_STRICT 1
116 #define XQUF_STATIC_TYPING_SAFE 1
117 
118 #define QLOCDECL const QueryLoc& qloc = v.get_loc(); (void) qloc
119 
120 #define SCTXDECL static_context* sctx = v.get_sctx(); (void)sctx;
121 
122 #ifndef NDEBUG
123 
124 #define CODEGEN_TRACE(msg)                                         \
125   QLOCDECL;                                                        \
126   SCTXDECL;                                                        \
127   if (Properties::instance()->traceCodegen())                      \
128   {                                                                \
129     std::cout << (msg) << TRACE << ", stk size " << itstack.size() \
130               << std::endl << std::endl;                           \
131     v.put(std::cout);                                              \
132     std::cout << "StackTop:" << std::endl;                         \
133     print_stack();                                                 \
134   }
135 
136 #define CODEGEN_TRACE_IN(msg)  \
137   CODEGEN_TRACE(std::string(++theDepth, ' ') + msg)
138 
139 #define CODEGEN_TRACE_OUT(msg) \
140   CODEGEN_TRACE(std::string(theDepth--, ' ') + msg)
141 
142 #else
143 #define CODEGEN_TRACE(msg) QLOCDECL; SCTXDECL;
144 #define CODEGEN_TRACE_IN(msg) CODEGEN_TRACE(msg)
145 #define CODEGEN_TRACE_OUT(msg) CODEGEN_TRACE(msg)
146 #endif
147 
148 
149 namespace zorba
150 {
151 
152 class plan_visitor;
153 
154 
155 typedef rchandle<ForVarIterator> ForVarIter_t;
156 typedef rchandle<LetVarIterator> LetVarIter_t;
157 
158 
159 #define ITEM_FACTORY (GENV.getStore().getItemFactory())
160 
161 namespace plan_visitor_ns
162 {
163 
pop_stack(std::stack<T> & stk)164 template <typename T> T pop_stack(std::stack<T> &stk)
165 {
166   assert (! stk.empty ());
167   T x = stk.top ();
168   stk.pop ();
169   return x;
170 }
171 
peek_stack(std::stack<T> & stk)172 template<class T> T& peek_stack(std::stack<T> &stk)
173 {
174   ZORBA_ASSERT (! stk.empty ());
175   return stk.top ();
176 }
177 
178 } // namespace plan_visitor_ns
179 
180 
181 template <typename V>
182 struct vector_destroyer
183 {
operator ()zorba::vector_destroyer184   void operator()(const struct hash64map<std::vector<V> *>::entry& entry)
185   {
186     delete (const_cast<struct hash64map<std::vector<V> *>::entry&>(entry)).val;
187   }
188 };
189 
190 
191 /*******************************************************************************
192 
193 ********************************************************************************/
194 class VarRebind : public SimpleRCObject
195 {
196 public:
197   PlanIter_t               theInputVar;
198   std::vector<PlanIter_t>  theOutputVarRefs;
199 };
200 
201 
202 typedef rchandle<VarRebind> VarRebind_t;
203 
204 
205 /*******************************************************************************
206   A FlworClauseVarMap is created for each flwor clause that defines variables.
207   If M is such a clause, then for each variable Vi defined by M, theVarExprs[i]
208   and theVarRebinds[i] contain an entry for Vi. theVarExprs[i] contains the
209   var_expr representing the Vi definition.
210 ********************************************************************************/
211 class FlworClauseVarMap : public SimpleRCObject
212 {
213 public:
214   bool                          theIsGeneral;
215   const flwor_clause          * theClause;
216 
217   std::vector<var_expr*>        theVarExprs;
218   std::vector<VarRebind_t>      theVarRebinds;
219 
220 public:
FlworClauseVarMap(const flwor_clause * cl,bool general)221   FlworClauseVarMap(const flwor_clause* cl, bool general)
222     :
223     theIsGeneral(general),
224     theClause(cl)
225   {
226   }
227 
~FlworClauseVarMap()228   ~FlworClauseVarMap() { }
229 
find_var(const var_expr * var) const230   long find_var(const var_expr* var) const
231   {
232     csize numVars = theVarExprs.size();
233     for (csize i = 0; i < numVars; ++i)
234     {
235       if (theVarExprs[i] == var)
236         return i;
237     }
238 
239     return -1;
240   }
241 };
242 
243 
244 typedef rchandle<FlworClauseVarMap> FlworClauseVarMap_t;
245 
246 
247 /******************************************************************************
248 
249  ******************************************************************************/
250 
251 #ifndef ZORBA_NO_FULL_TEXT
252 
253 class plan_ftnode_visitor : public ftnode_visitor
254 {
255 public:
256   typedef std::vector<PlanIter_t> PlanIter_list_t;
257 
plan_ftnode_visitor(plan_visitor * v)258   plan_ftnode_visitor( plan_visitor* v ) : plan_visitor_( v ) { }
259 
260   expr_visitor* get_expr_visitor();
261 
get_sub_iters()262   PlanIter_list_t& get_sub_iters() { return sub_iters_; }
263 
264 protected:
265   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftand );
266   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftextension_selection );
267   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftmild_not );
268   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftor );
269   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftprimary_with_options );
270   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftrange );
271   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftselection );
272   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftunary_not );
273   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftweight );
274   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftwords );
275   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftwords_times );
276 
277   // FTPosFilters
278   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftcontent_filter );
279   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftdistance_filter );
280   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftorder_filter );
281   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftscope_filter );
282   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftwindow_filter );
283 
284   // FTMatchOptions
285   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftcase_option );
286   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftdiacritics_option );
287   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftextension_option );
288   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftlanguage_option );
289   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftmatch_options );
290   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftstem_option );
291   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftstop_word_option );
292   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftstop_words );
293   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftthesaurus_id );
294   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftthesaurus_option );
295   DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftwild_card_option );
296 
297 private:
298   plan_visitor   * plan_visitor_;
299   PlanIter_list_t  sub_iters_;
300 };
301 
302 #endif /* ZORBA_NO_FULL_TEXT */
303 
304 
305 /******************************************************************************
306 
307 *******************************************************************************/
308 class plan_visitor : public expr_visitor
309 {
310 #ifndef ZORBA_NO_FULL_TEXT
311   friend class plan_ftnode_visitor;
312 #endif /* ZORBA_NO_FULL_TEXT */
313 
314   typedef enum
315   {
316     ELEMENT_CONTENT = 0,
317     ATTRIBUTE_CONTENT,
318     TEXT_CONTENT,
319     UPDATE_CONTEXT
320   } EnclosedExprContext;
321 
322 protected:
323   static std::vector<PlanIter_t>             no_var_iters;
324 
325 protected:
326   uint32_t                                   theDepth;
327 
328   std::stack<PlanIter_t>                     itstack;
329 
330   std::stack<expr*>                          theConstructorsStack;
331   std::stack<EnclosedExprContext>            theEnclosedContextStack;
332   std::stack<bool>                           theCopyNodesStack;
333 
334   ulong                                      theNextDynamicVarId;
335 
336   hash64map<std::vector<LetVarIter_t> *>   * arg_var_iter_map;
337   hash64map<std::vector<LetVarIter_t> *>     catchvar_iter_map;
338   hash64map<std::vector<ForVarIter_t> *>     copy_var_iter_map;
339 
340   std::vector<FlworClauseVarMap_t>           theClauseStack;
341 
342   CompilerCB                               * theCCB;
343 
344 #ifdef ZORBA_WITH_DEBUGGER
345   std::stack<DebugIterator*>                 theDebuggerStack;
346 #endif
347 
348 #ifndef ZORBA_NO_FULL_TEXT
349   plan_ftnode_visitor                      * plan_ftnode_visitor_;
350 #endif /* ZORBA_NO_FULL_TEXT */
351 
352 public:
353 
plan_visitor(CompilerCB * ccb,ulong nextDynamicVarId,hash64map<std::vector<LetVarIter_t> * > * arg_var_map=NULL)354 plan_visitor(
355     CompilerCB* ccb,
356     ulong nextDynamicVarId,
357     hash64map<std::vector<LetVarIter_t>*>* arg_var_map = NULL)
358   :
359   theDepth(0),
360   theNextDynamicVarId(nextDynamicVarId),
361   arg_var_iter_map(arg_var_map),
362   theCCB(ccb)
363 {
364 #ifndef ZORBA_NO_FULL_TEXT
365   plan_ftnode_visitor_ = new plan_ftnode_visitor( this );
366 #endif /* ZORBA_NO_FULL_TEXT */
367 }
368 
369 
~plan_visitor()370 ~plan_visitor()
371 {
372   for_each(
373     catchvar_iter_map.begin(),
374     catchvar_iter_map.end(),
375     vector_destroyer<LetVarIter_t>()
376   );
377   for_each(
378     copy_var_iter_map.begin(),
379     copy_var_iter_map.end(),
380     vector_destroyer<ForVarIter_t>()
381   );
382 #ifndef ZORBA_NO_FULL_TEXT
383   delete plan_ftnode_visitor_;
384 #endif /* ZORBA_NO_FULL_TEXT */
385 }
386 
387 
getNextDynamicVarId() const388 ulong getNextDynamicVarId() const
389 {
390   return theNextDynamicVarId;
391 }
392 
393 
394 #ifndef ZORBA_NO_FULL_TEXT
get_ftnode_visitor()395 ftnode_visitor* get_ftnode_visitor()
396 {
397   return plan_ftnode_visitor_;
398 }
399 #endif /* ZORBA_NO_FULL_TEXT */
400 
401 
pop_itstack()402 PlanIter_t pop_itstack()
403 {
404   return plan_visitor_ns::pop_stack(itstack);
405 }
406 
407 
push_itstack(PlanIterator * iter)408 void push_itstack(PlanIterator* iter)
409 {
410   itstack.push(iter);
411 }
412 
413 
print_stack()414 void print_stack()
415 {
416   if (itstack.empty())
417   {
418     std::cout << "EMPTY" << std::endl;
419   }
420   else
421   {
422     XMLIterPrinter vp(std::cout);
423     print_iter_plan(vp, plan_visitor_ns::peek_stack(itstack));
424   }
425 }
426 
427 
is_enclosed_expr(expr * e)428 bool is_enclosed_expr(expr* e)
429 {
430   fo_expr* foExpr = dynamic_cast<fo_expr*>(e);
431   if (foExpr != NULL &&
432       foExpr->get_func()->getKind() == FunctionConsts::OP_ENCLOSED_1)
433     return true;
434 
435   return false;
436 }
437 
438 
begin_visit(expr & v)439 bool begin_visit(expr& v)
440 {
441   CODEGEN_TRACE_IN("");
442   return true;
443 }
444 
end_visit(expr & v)445 void end_visit(expr& v)
446 {
447   CODEGEN_TRACE_OUT("");
448 }
449 
450 
451 /***************************************************************************//**
452 
453 ********************************************************************************/
begin_visit(function_item_expr & v)454 bool begin_visit(function_item_expr& v)
455 {
456   CODEGEN_TRACE_IN("");
457   return true;
458 }
459 
end_visit(function_item_expr & v)460 void end_visit(function_item_expr& v)
461 {
462   CODEGEN_TRACE_OUT("");
463   store::Item_t lQName = v.get_qname();
464   store::Item_t lFItem;
465 
466   bool isInline = (lQName == 0);
467 
468   if (!isInline)
469   {
470     // literal function item
471     lFItem = new FunctionItem(theCCB, sctx, &v);
472   }
473   else
474   {
475     // inline function
476     std::vector<PlanIter_t> lVariableValues;
477     size_t lSize = v.get_vars().size();
478     for (size_t i = 0; i < lSize; ++i)
479     {
480       lVariableValues.push_back(pop_itstack());
481     }
482     lFItem = new FunctionItem(theCCB, sctx, &v, lVariableValues);
483   }
484 
485   push_itstack(new SingletonIterator (sctx, qloc, lFItem));
486 }
487 
488 
489 /***************************************************************************//**
490 
491 ********************************************************************************/
begin_visit(dynamic_function_invocation_expr & v)492 bool begin_visit(dynamic_function_invocation_expr& v)
493 {
494   CODEGEN_TRACE_IN("");
495   return true;
496 }
497 
end_visit(dynamic_function_invocation_expr & v)498 void end_visit(dynamic_function_invocation_expr& v)
499 {
500   CODEGEN_TRACE_OUT("");
501 
502   ulong numArgs = (ulong)v.get_args().size() + 1;
503 
504   std::vector<PlanIter_t> argIters(numArgs);
505 
506   for (size_t i = 1; i < numArgs; ++i)
507   {
508     argIters[i] = pop_itstack();
509   }
510 
511   argIters[0] = pop_itstack();
512 
513   push_itstack(new DynamicFnCallIterator(sctx, qloc, argIters));
514 }
515 
516 
517 /***************************************************************************//**
518 
519 ********************************************************************************/
begin_visit(function_trace_expr & v)520 bool begin_visit(function_trace_expr& v)
521 {
522   CODEGEN_TRACE_IN("");
523   return true;
524 }
525 
end_visit(function_trace_expr & v)526 void end_visit(function_trace_expr& v)
527 {
528   CODEGEN_TRACE_OUT("");
529   std::vector<PlanIter_t> argv;
530   argv.push_back(pop_itstack());
531   std::auto_ptr<FunctionTraceIterator> lDummyIter(
532       new FunctionTraceIterator(sctx, qloc, argv));
533   lDummyIter->setFunctionName(v.getFunctionName());
534   lDummyIter->setFunctionArity(v.getFunctionArity());
535   lDummyIter->setFunctionLocation(v.getFunctionLocation());
536   lDummyIter->setFunctionCallLocation(v.getFunctionCallLocation());
537   push_itstack(lDummyIter.release());
538 }
539 
begin_visit(wrapper_expr & v)540 bool begin_visit(wrapper_expr& v)
541 {
542   CODEGEN_TRACE_IN("");
543   return true;
544 }
545 
end_visit(wrapper_expr & v)546 void end_visit(wrapper_expr& v)
547 {
548   CODEGEN_TRACE_OUT("");
549   PlanIter_t iter = pop_itstack();
550   iter->setLocation (v.get_loc());
551   push_itstack(iter);
552 }
553 
554 
555 /***************************************************************************//**
556 
557 ********************************************************************************/
begin_visit(block_expr & v)558 bool begin_visit(block_expr& v)
559 {
560   CODEGEN_TRACE_IN("");
561   return true;
562 }
563 
end_visit(block_expr & v)564 void end_visit(block_expr& v)
565 {
566   CODEGEN_TRACE_OUT("");
567 
568   ulong numArgs = v.size();
569   checked_vector<PlanIter_t> args(numArgs);
570 
571   for (ulong i = numArgs; i > 0; --i)
572   {
573     PlanIter_t arg = pop_itstack();
574     args[i-1] = arg;
575   }
576 
577   push_itstack(new SequentialIterator(sctx, qloc, args));
578 }
579 
580 
581 /***************************************************************************//**
582 
583 ********************************************************************************/
begin_visit(apply_expr & v)584 bool begin_visit(apply_expr& v)
585 {
586   CODEGEN_TRACE_IN("");
587   return true;
588 }
589 
end_visit(apply_expr & v)590 void end_visit(apply_expr& v)
591 {
592   CODEGEN_TRACE_OUT("");
593 
594   PlanIter_t arg = pop_itstack();
595 
596   push_itstack(new ApplyIterator(sctx, qloc, v.discardsXDM(), arg));
597 }
598 
599 
600 /***************************************************************************//**
601 
602 ********************************************************************************/
begin_visit(var_decl_expr & v)603 bool begin_visit(var_decl_expr& v)
604 {
605   CODEGEN_TRACE_IN("");
606 
607   var_expr* varExpr = v.get_var_expr();
608   if (varExpr->get_unique_id() == 0)
609     varExpr->set_unique_id(theNextDynamicVarId++);
610 
611   return true;
612 }
613 
end_visit(var_decl_expr & v)614 void end_visit(var_decl_expr& v)
615 {
616   CODEGEN_TRACE_OUT("");
617 
618   var_expr* varExpr = v.get_var_expr();
619   expr* initExpr = v.get_init_expr();
620 
621   checked_vector<PlanIter_t> args;
622   bool singleItem = false;
623 
624   if (initExpr != NULL)
625   {
626     args.push_back(pop_itstack());
627 
628     xqtref_t exprType = initExpr->get_return_type();
629 
630     if (exprType->get_quantifier() == TypeConstants::QUANT_ONE)
631       singleItem = true;
632   }
633 
634   push_itstack(new CtxVarDeclareIterator(sctx,
635                                          qloc,
636                                          args,
637                                          varExpr->get_unique_id(),
638                                          varExpr->get_name(),
639                                          varExpr->is_external(),
640                                          singleItem));
641 }
642 
643 
644 /***************************************************************************//**
645 
646 ********************************************************************************/
begin_visit(var_set_expr & v)647 bool begin_visit(var_set_expr& v)
648 {
649   CODEGEN_TRACE_IN("");
650   return true;
651 }
652 
653 
end_visit(var_set_expr & v)654 void end_visit(var_set_expr& v)
655 {
656   CODEGEN_TRACE_OUT("");
657 
658   const var_expr* varExpr = v.get_var_expr();
659 
660   xqtref_t exprType = v.get_expr()->get_return_type();
661 
662   PlanIter_t exprIter = pop_itstack();
663 
664   CtxVarAssignIterator* iter =
665   new CtxVarAssignIterator(sctx,
666                            qloc,
667                            varExpr->get_unique_id(),
668                            varExpr->get_name(),
669                            (varExpr->get_kind() == var_expr::local_var),
670                            exprIter);
671 
672   if (exprType->get_quantifier() == TypeConstants::QUANT_ONE)
673     iter->setSingleItem();
674 
675   push_itstack(iter);
676 }
677 
678 
679 /*******************************************************************************
680   VarRef expr
681 ********************************************************************************/
682 
begin_visit(var_expr & v)683 bool begin_visit(var_expr& v)
684 {
685   CODEGEN_TRACE_IN("");
686   return true;
687 }
688 
689 
end_visit(var_expr & v)690 void end_visit(var_expr& v)
691 {
692   CODEGEN_TRACE_OUT("");
693 
694   general_var_codegen(v);
695 }
696 
697 
698 template<class Iter>
base_var_codegen(const var_expr & var,hash64map<std::vector<rchandle<Iter>> * > & varMap)699 PlanIter_t base_var_codegen(
700     const var_expr& var,
701     hash64map<std::vector<rchandle<Iter> > *>& varMap)
702 {
703   std::vector<rchandle<Iter> >* varRefs = NULL;
704   bool bound = varMap.get((uint64_t) &var, varRefs);
705   ZORBA_ASSERT(bound);
706 
707   Iter* iter = new Iter(var.get_sctx(), var.get_loc(), var.get_name());
708 
709   varRefs->push_back(iter);
710 
711   return iter;
712 }
713 
714 
create_var_iter(const var_expr & var,bool forvar)715 PlanIter_t create_var_iter(const var_expr& var, bool forvar)
716 {
717   PlanIter_t iter;
718   if (forvar)
719   {
720     iter = new ForVarIterator(var.get_sctx(), var.get_loc(), var.get_name());
721   }
722   else
723   {
724     iter = new LetVarIterator(var.get_sctx(), var.get_loc(), var.get_name());
725   }
726   return iter;
727 }
728 
729 
general_var_codegen(const var_expr & var)730 void general_var_codegen(const var_expr& var)
731 {
732   const QueryLoc& qloc = var.get_loc();
733   static_context* sctx = var.get_sctx();
734 
735   bool isForVar = false;
736 
737   switch (var.get_kind())
738   {
739   case var_expr::for_var:
740   case var_expr::pos_var:
741   case var_expr::wincond_out_var:
742   case var_expr::wincond_out_pos_var:
743   case var_expr::groupby_var:
744   case var_expr::count_var:
745 
746   case var_expr::wincond_in_var:
747   case var_expr::wincond_in_pos_var:
748   {
749     isForVar = true;
750     // fall through
751   }
752 
753   case var_expr::let_var:
754   case var_expr::win_var:
755   case var_expr::non_groupby_var:
756   {
757     ZORBA_ASSERT(!theClauseStack.empty());
758 
759     long stackSize = (long)theClauseStack.size();
760     long varPos;
761     VarRebind_t varRebind;
762     PlanIter_t varIter;
763 
764     // Look for the inner-most clause C that knows about this variable. C is
765     // either the clause D_C that defines the var, or the inner-most orderby
766     // or materialize clause the comes after D_C and rebinds the var to its
767     // output.
768     long i = stackSize - 1;
769     while(true)
770     {
771       if ((varPos = theClauseStack[i]->find_var(&var)) >= 0)
772         break;
773 
774       --i;
775       ZORBA_ASSERT(i >= 0);
776     }
777 
778     // Create a var ref iter in the output of C.
779     varIter = create_var_iter(var, isForVar);
780 
781     FlworClauseVarMap* clauseVarMap = theClauseStack[i];
782 
783     flwor_expr* flworExpr = clauseVarMap->theClause->get_flwor_expr();
784 
785     clauseVarMap->theVarRebinds[varPos]->theOutputVarRefs.push_back(varIter);
786 
787     if (clauseVarMap->theIsGeneral || flworExpr->is_sequential())
788     {
789       // For each orderby or materialize clause O after C, bind the var iter
790       // created by the previous clause to the input of O, and then create a new
791       // var iter and put it to the output of O.
792       for (++i; i < stackSize; ++i)
793       {
794         clauseVarMap = theClauseStack[i];
795 
796         ZORBA_ASSERT(clauseVarMap->find_var(&var) < 0);
797 
798         if (flworExpr == clauseVarMap->theClause->get_flwor_expr() &&
799             ((clauseVarMap->theClause->get_kind() == flwor_clause::order_clause &&
800               flworExpr->is_general()) ||
801              clauseVarMap->theClause->get_kind() == flwor_clause::materialize_clause))
802         {
803           varRebind = new VarRebind;
804 
805           clauseVarMap->theVarExprs.push_back(const_cast<var_expr*>(&var));
806           clauseVarMap->theVarRebinds.push_back(varRebind);
807 
808           varRebind->theInputVar = varIter;
809 
810           varIter = create_var_iter(var, isForVar);
811 
812           varRebind->theOutputVarRefs.push_back(varIter);
813         }
814       }
815     }
816 
817     push_itstack(varIter);
818     break;
819   }
820 
821   case var_expr::arg_var:
822   {
823     PlanIter_t iter = base_var_codegen(var, *arg_var_iter_map);
824     push_itstack(iter);
825     break;
826   }
827 
828   case var_expr::catch_var:
829   {
830     PlanIter_t iter = base_var_codegen(var, catchvar_iter_map);
831     push_itstack(iter);
832     break;
833   }
834 
835   case var_expr::copy_var:
836   {
837     PlanIter_t iter = base_var_codegen(var, copy_var_iter_map);
838     push_itstack(iter);
839     break;
840   }
841 
842   case var_expr::prolog_var:
843   {
844     push_itstack(new CtxVarIterator(sctx,
845                                     qloc,
846                                     var.get_unique_id(),
847                                     var.get_name(),
848                                     false));
849     break;
850   }
851   case var_expr::local_var:
852   {
853     push_itstack(new CtxVarIterator(sctx,
854                                     qloc,
855                                     var.get_unique_id(),
856                                     var.get_name(),
857                                     true));
858     break;
859   }
860 
861   case var_expr::unknown_var:
862   case var_expr::eval_var:
863   case var_expr::score_var:
864   {
865     ZORBA_ASSERT(false);
866     break;
867   }
868   }
869 }
870 
871 
872 /*******************************************************************************
873   FLWOR expr
874 ********************************************************************************/
begin_visit(flwor_expr & v)875 bool begin_visit(flwor_expr& v)
876 {
877   CODEGEN_TRACE_IN("");
878 
879   bool isGeneral = v.is_general();
880 
881   csize numClauses = v.num_clauses();
882 
883   if (v.is_sequential())
884   {
885     if (!isGeneral)
886     {
887       if (v.has_sequential_clauses())
888       {
889         csize numForClauses = 0;
890 
891         for (csize i = 0; i < numClauses; ++i)
892         {
893           const flwor_clause* c = v.get_clause(i);
894 
895           if (c->get_kind() == flwor_clause::for_clause)
896           {
897             ++numForClauses;
898 
899             if (c->get_expr()->is_sequential())
900             {
901               // TODO: do not convert to general flwor if the whole flwor consists
902               // of a single FOR followed by RETURN.
903               isGeneral = true;
904               v.set_general(true);
905               break;
906             }
907           }
908           else if (c->get_kind() == flwor_clause::let_clause)
909           {
910             if (c->get_expr()->is_sequential())
911             {
912               if (numForClauses > 0)
913               {
914                 isGeneral = true;
915                 v.set_general(true);
916                 break;
917               }
918             }
919           }
920           else
921           {
922             break;
923           }
924         }
925       }
926 
927       // Note: a materialize clause may exist already in case plan serialization
928       // is on (see comment in materialize_clause::clone)
929       if (!isGeneral &&
930           v.get_return_expr()->is_sequential() &&
931           v.get_clause(numClauses-1)->get_kind() != flwor_clause::materialize_clause &&
932           (v.get_order_clause() != NULL || v.get_group_clause() == NULL))
933       {
934         materialize_clause* mat =
935         theCCB->theEM->create_materialize_clause(v.get_sctx(),
936                                             v.get_return_expr()->get_loc());
937 
938         v.add_clause(mat);
939         ++numClauses;
940       }
941     } // !isGeneral
942 
943     if (isGeneral)
944     {
945       std::vector<OrderModifier> modifiers;
946       std::vector<expr*> orderingExprs;
947 
948       csize numForClauses = 0;
949       csize i = 0;
950 
951       while (i < numClauses)
952       {
953         const flwor_clause* c = v.get_clause(i);
954 
955         flwor_clause::ClauseKind k = c->get_kind();
956 
957         switch (k)
958         {
959         case flwor_clause::for_clause:
960         case flwor_clause::let_clause:
961         case flwor_clause::window_clause:
962         {
963           if (k == flwor_clause::for_clause || k == flwor_clause::window_clause)
964           {
965             xqtref_t domainType = c->get_expr()->get_return_type();
966             if (domainType->get_quantifier() != TypeConstants::QUANT_ONE)
967               ++numForClauses;
968           }
969 
970           if (c->get_expr()->is_sequential())
971           {
972             if (k == flwor_clause::for_clause ||
973                 k == flwor_clause::window_clause ||
974                 numForClauses > 0)
975             {
976               theCCB->theXQueryDiagnostics->add_warning(
977               NEW_XQUERY_WARNING(zwarn::ZWST0004_AMBIGUOUS_SEQUENTIAL_FLWOR,
978                                  WARN_LOC(c->get_loc())));
979 
980               if (i > 0 &&
981                   v.get_clause(i-1)->get_kind() != flwor_clause::order_clause &&
982                   v.get_clause(i-1)->get_kind() != flwor_clause::group_clause)
983               {
984                 orderby_clause* mat =
985                 theCCB->theEM->create_orderby_clause(v.get_sctx(),
986                                    c->get_loc(),
987                                    true,
988                                    modifiers,
989                                    orderingExprs);
990 
991                 v.add_clause(i, mat);
992                 ++i;
993                 ++numClauses;
994               }
995 
996               if (i == numClauses -1 ||
997                   (i < numClauses - 1 &&
998                    v.get_clause(i+1)->get_kind() != flwor_clause::group_clause))
999               {
1000                 orderby_clause* mat =
1001                 theCCB->theEM->create_orderby_clause(v.get_sctx(),
1002                                    c->get_loc(),
1003                                    true,
1004                                    modifiers,
1005                                    orderingExprs);
1006 
1007                 v.add_clause(i+1, mat);
1008                 ++numClauses;
1009               }
1010             }
1011           }
1012 
1013           break;
1014         }
1015         case flwor_clause::where_clause:
1016         case flwor_clause::group_clause:
1017         case flwor_clause::order_clause:
1018         case flwor_clause::count_clause:
1019         {
1020           break;
1021         }
1022         default:
1023           ZORBA_ASSERT(false);
1024         }
1025 
1026         ++i;
1027       }
1028 
1029       const flwor_clause* lastClause = v.get_clause(v.num_clauses()-1);
1030 
1031       if (v.get_return_expr()->is_sequential() &&
1032           lastClause->get_kind() != flwor_clause::order_clause &&
1033           lastClause->get_kind() != flwor_clause::group_clause)
1034       {
1035         orderby_clause* mat =
1036         theCCB->theEM->create_orderby_clause(v.get_sctx(),
1037                            v.get_return_expr()->get_loc(),
1038                            true,
1039                            modifiers,
1040                            orderingExprs);
1041 
1042         v.add_clause(mat);
1043         ++numClauses;
1044       }
1045     }
1046   }
1047 
1048   for (csize i = 0; i < numClauses; ++i)
1049   {
1050     const flwor_clause* c = v.get_clause(i);
1051 
1052     switch (c->get_kind())
1053     {
1054 
1055     case flwor_clause::for_clause:
1056     {
1057       visit_flwor_clause(c, isGeneral);
1058 
1059       const for_clause* fc = reinterpret_cast<const for_clause*>(c);
1060       fc->get_expr()->accept(*this);
1061       break;
1062     }
1063 
1064     case flwor_clause::let_clause:
1065     {
1066       visit_flwor_clause(c, isGeneral);
1067 
1068       const for_clause* fc = reinterpret_cast<const for_clause*>(c);
1069       fc->get_expr()->accept(*this);
1070       break;
1071     }
1072 
1073     case flwor_clause::window_clause:
1074     {
1075       visit_flwor_clause(c, isGeneral);
1076 
1077       const window_clause* wc = reinterpret_cast<const window_clause*>(c);
1078 
1079       flwor_wincond* startCond = wc->get_win_start();
1080       flwor_wincond* stopCond = wc->get_win_stop();
1081 
1082       if (startCond)
1083         startCond->get_cond()->accept(*this);
1084 
1085       if (stopCond)
1086         stopCond->get_cond()->accept(*this);
1087 
1088       wc->get_expr()->accept(*this);
1089 
1090       break;
1091     }
1092 
1093     case flwor_clause::group_clause:
1094     {
1095       const group_clause* gc = reinterpret_cast<const group_clause*>(c);
1096 
1097       const flwor_clause::rebind_list_t& gvars = gc->get_grouping_vars();
1098       const flwor_clause::rebind_list_t& ngvars = gc->get_nongrouping_vars();
1099 
1100       for (ulong i = 0; i < gvars.size(); ++i)
1101       {
1102         gvars[i].first->accept(*this);
1103       }
1104 
1105       for (ulong i = 0; i < ngvars.size(); ++i)
1106       {
1107         ngvars[i].first->accept(*this);
1108       }
1109 
1110       visit_flwor_clause(c, isGeneral);
1111 
1112       break;
1113     }
1114 
1115     case flwor_clause::order_clause:
1116     {
1117       const orderby_clause* oc = reinterpret_cast<const orderby_clause*>(c);
1118 
1119       ulong numCols = oc->num_columns();
1120       for (ulong i = 0; i < numCols; ++i)
1121       {
1122         oc->get_column_expr(i)->accept(*this);
1123       }
1124 
1125       visit_flwor_clause(c, isGeneral);
1126 
1127       break;
1128     }
1129 
1130     case flwor_clause::materialize_clause:
1131     {
1132       visit_flwor_clause(c, isGeneral);
1133 
1134       break;
1135     }
1136 
1137     case flwor_clause::count_clause:
1138     {
1139       visit_flwor_clause(c, isGeneral);
1140       break;
1141     }
1142 
1143     case flwor_clause::where_clause:
1144     {
1145       const where_clause* wc = reinterpret_cast<const where_clause*>(c);
1146       wc->get_expr()->accept(*this);
1147       break;
1148     }
1149     default:
1150       ZORBA_ASSERT(false);
1151     }
1152   }
1153 
1154   v.get_return_expr()->accept(*this);
1155 
1156   // Do not visit the children of this flwor expr; this was done already by
1157   // this method
1158   return false;
1159 }
1160 
1161 
end_visit(flwor_expr & v)1162 void end_visit(flwor_expr& v)
1163 {
1164   CODEGEN_TRACE_OUT("");
1165 
1166   if (!v.is_general())
1167   {
1168     flwor_codegen(v);
1169   }
1170   else
1171   {
1172     PlanIter_t ret = pop_itstack();
1173 
1174     PlanIter_t gflwor = gflwor_codegen(v, v.num_clauses() - 1);
1175 
1176     push_itstack(new flwor::TupleStreamIterator(sctx, qloc, gflwor, ret, false));
1177   }
1178 }
1179 
1180 
visit_flwor_clause(const flwor_clause * c,bool general)1181 void visit_flwor_clause(const flwor_clause* c, bool general)
1182 {
1183   if (c->get_kind() == flwor_clause::where_clause)
1184     return;
1185 
1186   FlworClauseVarMap_t clauseVarMap = new FlworClauseVarMap(c, general);
1187 
1188   switch (c->get_kind())
1189   {
1190   case flwor_clause::for_clause:
1191   {
1192     const for_clause* fc = static_cast<const for_clause *>(c);
1193 
1194     VarRebind_t varRebind = new VarRebind;
1195     clauseVarMap->theVarExprs.push_back(fc->get_var());
1196     clauseVarMap->theVarRebinds.push_back(varRebind);
1197 
1198     if (fc->get_pos_var() != NULL)
1199     {
1200       varRebind = new VarRebind;
1201       clauseVarMap->theVarExprs.push_back(fc->get_pos_var());
1202       clauseVarMap->theVarRebinds.push_back(varRebind);
1203     }
1204 
1205     break;
1206   }
1207 
1208   case flwor_clause::let_clause:
1209   {
1210     const let_clause* lc = static_cast<const let_clause *>(c);
1211 
1212     VarRebind_t varRebind = new VarRebind;
1213     clauseVarMap->theVarExprs.push_back(lc->get_var());
1214     clauseVarMap->theVarRebinds.push_back(varRebind);
1215 
1216     break;
1217   }
1218 
1219   case flwor_clause::window_clause:
1220   {
1221     const window_clause* wc = static_cast<const window_clause *>(c);
1222 
1223     VarRebind_t varRebind = new VarRebind;
1224     clauseVarMap->theVarExprs.push_back(wc->get_var());
1225     clauseVarMap->theVarRebinds.push_back(varRebind);
1226 
1227     init_wincond_var_maps(wc->get_win_stop(), clauseVarMap);
1228     init_wincond_var_maps(wc->get_win_start(), clauseVarMap);
1229 
1230     break;
1231   }
1232 
1233   case flwor_clause::group_clause:
1234   {
1235     const group_clause* gbc = static_cast<const group_clause *>(c);
1236     const group_clause::rebind_list_t& grouping_vars = gbc->get_grouping_vars();
1237     const group_clause::rebind_list_t& nongrouping_vars = gbc->get_nongrouping_vars();
1238 
1239     for (unsigned i = 0; i < grouping_vars.size(); ++i)
1240     {
1241       VarRebind_t varRebind = new VarRebind;
1242       clauseVarMap->theVarExprs.push_back(grouping_vars[i].second);
1243       clauseVarMap->theVarRebinds.push_back(varRebind);
1244     }
1245 
1246     for (unsigned i = 0; i < nongrouping_vars.size(); ++i)
1247     {
1248       VarRebind_t varRebind = new VarRebind;
1249       clauseVarMap->theVarExprs.push_back(nongrouping_vars[i].second);
1250       clauseVarMap->theVarRebinds.push_back(varRebind);
1251     }
1252 
1253     break;
1254   }
1255 
1256   case flwor_clause::order_clause:
1257   case flwor_clause::materialize_clause:
1258   {
1259     break;
1260   }
1261 
1262   case flwor_clause::count_clause:
1263   {
1264     const count_clause* cl = static_cast<const count_clause *>(c);
1265 
1266     VarRebind_t varRebind = new VarRebind;
1267     clauseVarMap->theVarExprs.push_back(cl->get_var());
1268     clauseVarMap->theVarRebinds.push_back(varRebind);
1269 
1270     break;
1271   }
1272 
1273   default:
1274     ZORBA_ASSERT(false);
1275   }
1276 
1277   if (clauseVarMap != NULL)
1278     theClauseStack.push_back(clauseVarMap);
1279 }
1280 
1281 
init_wincond_var_maps(const flwor_wincond * cond,FlworClauseVarMap * clauseVarMap)1282 void init_wincond_var_maps(
1283     const flwor_wincond* cond,
1284     FlworClauseVarMap* clauseVarMap)
1285 {
1286   if (cond == NULL)
1287     return;
1288 
1289   const flwor_wincond::vars& inVars = cond->get_in_vars();
1290   const flwor_wincond::vars& outVars = cond->get_out_vars();
1291 
1292   if (inVars.posvar != NULL)
1293   {
1294     VarRebind_t varRebind = new VarRebind;
1295     clauseVarMap->theVarExprs.push_back(inVars.posvar);
1296     clauseVarMap->theVarRebinds.push_back(varRebind);
1297   }
1298 
1299   if (inVars.curr != NULL)
1300   {
1301     VarRebind_t varRebind = new VarRebind;
1302     clauseVarMap->theVarExprs.push_back(inVars.curr);
1303     clauseVarMap->theVarRebinds.push_back(varRebind);
1304   }
1305 
1306   if (inVars.prev != NULL)
1307   {
1308     VarRebind_t varRebind = new VarRebind;
1309     clauseVarMap->theVarExprs.push_back(inVars.prev);
1310     clauseVarMap->theVarRebinds.push_back(varRebind);
1311   }
1312 
1313   if (inVars.next != NULL)
1314   {
1315     VarRebind_t varRebind = new VarRebind;
1316     clauseVarMap->theVarExprs.push_back(inVars.next);
1317     clauseVarMap->theVarRebinds.push_back(varRebind);
1318   }
1319 
1320   if (outVars.posvar != NULL)
1321   {
1322     VarRebind_t varRebind = new VarRebind;
1323     clauseVarMap->theVarExprs.push_back(outVars.posvar);
1324     clauseVarMap->theVarRebinds.push_back(varRebind);
1325   }
1326 
1327   if (outVars.curr != NULL)
1328   {
1329     VarRebind_t varRebind = new VarRebind;
1330     clauseVarMap->theVarExprs.push_back(outVars.curr);
1331     clauseVarMap->theVarRebinds.push_back(varRebind);
1332   }
1333 
1334   if (outVars.prev != NULL)
1335   {
1336     VarRebind_t varRebind = new VarRebind;
1337     clauseVarMap->theVarExprs.push_back(outVars.prev);
1338     clauseVarMap->theVarRebinds.push_back(varRebind);
1339   }
1340 
1341   if (outVars.next != NULL)
1342   {
1343     VarRebind_t varRebind = new VarRebind;
1344     clauseVarMap->theVarExprs.push_back(outVars.next);
1345     clauseVarMap->theVarRebinds.push_back(varRebind);
1346   }
1347 }
1348 
1349 
1350 struct wincond_var_iters
1351 {
1352   std::vector<PlanIter_t> * inPos;
1353   std::vector<PlanIter_t> * inCurr;
1354   std::vector<PlanIter_t> * inPrev;
1355   std::vector<PlanIter_t> * inNext;
1356 
1357   std::vector<PlanIter_t> * outPos;
1358   std::vector<PlanIter_t> * outCurr;
1359   std::vector<PlanIter_t> * outPrev;
1360   std::vector<PlanIter_t> * outNext;
1361 
wincond_var_iterszorba::plan_visitor::wincond_var_iters1362   wincond_var_iters(
1363         const flwor_wincond* cond,
1364         FlworClauseVarMap* clauseVarMap,
1365         ulong& varPos)
1366   {
1367     const flwor_wincond::vars& inVars = cond->get_in_vars();
1368     const flwor_wincond::vars& outVars = cond->get_out_vars();
1369 
1370     inPos = ((inVars.posvar != NULL) ?
1371              &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1372              &plan_visitor::no_var_iters);
1373 
1374     inCurr = (inVars.curr != NULL ?
1375               &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1376               &plan_visitor::no_var_iters);
1377 
1378     inPrev = (inVars.prev != NULL ?
1379               &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1380               &plan_visitor::no_var_iters);
1381 
1382     inNext = (inVars.next != NULL ?
1383               &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1384               &plan_visitor::no_var_iters);
1385 
1386     outPos = (outVars.posvar != NULL ?
1387               &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1388               &plan_visitor::no_var_iters);
1389 
1390     outCurr = (outVars.curr != NULL ?
1391                &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1392                &plan_visitor::no_var_iters);
1393 
1394     outPrev = (outVars.prev != NULL ?
1395                &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1396                &plan_visitor::no_var_iters);
1397 
1398     outNext = (outVars.next != NULL ?
1399                &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1400                &plan_visitor::no_var_iters);
1401   }
1402 };
1403 
1404 
nativeColumnSort(expr * colExpr)1405 bool nativeColumnSort(expr* colExpr)
1406 {
1407   const QueryLoc& loc = colExpr->get_loc();
1408   TypeManager* tm = colExpr->get_type_manager();
1409   RootTypeManager& rtm = GENV_TYPESYSTEM;
1410 
1411   xqtref_t colType = colExpr->get_return_type();
1412 
1413   if (colType->type_kind() == XQType::NODE_TYPE_KIND)
1414   {
1415     colType = static_cast<const NodeXQType*>(colType.getp())->get_content_type();
1416   }
1417 
1418   if (colType != NULL &&
1419       TypeOps::is_subtype(tm, *colType, *rtm.ANY_ATOMIC_TYPE_STAR, loc) &&
1420       !TypeOps::is_equal(tm,
1421                          *TypeOps::prime_type(tm, *colType),
1422                          *rtm.ANY_ATOMIC_TYPE_ONE,
1423                          loc))
1424   {
1425     return true;
1426   }
1427 
1428   return false;
1429 }
1430 
1431 
gflwor_codegen(flwor_expr & flworExpr,int currentClause)1432 PlanIter_t gflwor_codegen(flwor_expr& flworExpr, int currentClause)
1433 {
1434 #define PREV_ITER gflwor_codegen(flworExpr, currentClause - 1)
1435 
1436   const QueryLoc& qloc = flworExpr.get_loc();
1437 
1438   static_context* sctx = flworExpr.get_sctx();
1439 
1440   if (currentClause < 0)
1441   {
1442     return new flwor::TupleSourceIterator(sctx, qloc);
1443   }
1444 
1445   const flwor_clause& c = *(flworExpr.get_clause(currentClause));
1446 
1447   FlworClauseVarMap_t clauseVarMap;
1448 
1449   if (c.get_kind() != flwor_clause::where_clause)
1450   {
1451     ZORBA_ASSERT(!theClauseStack.empty());
1452     ulong stackSize = (ulong)theClauseStack.size();
1453 
1454     clauseVarMap = theClauseStack[stackSize-1];
1455     theClauseStack.resize(stackSize - 1);
1456 
1457     ZORBA_ASSERT(clauseVarMap->theClause == &c);
1458   }
1459 
1460   //
1461   // WHERE
1462   //
1463   if (c.get_kind() == flwor_clause::where_clause)
1464   {
1465     PlanIter_t where = pop_itstack();
1466     PlanIter_t input = PREV_ITER;
1467     return new flwor::WhereIterator(sctx, c.get_loc(), input, where);
1468   }
1469 
1470   //
1471   // FOR
1472   //
1473   else if (c.get_kind() == flwor_clause::for_clause)
1474   {
1475     const for_clause* fc = static_cast<const for_clause *>(&c);
1476 
1477     ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() >= 1);
1478 
1479     var_expr* var = fc->get_var();
1480 
1481     PlanIter_t domainIter = pop_itstack();
1482 
1483     std::vector<PlanIter_t>& varRefs = clauseVarMap->theVarRebinds[0]->theOutputVarRefs;
1484     std::vector<PlanIter_t>* posVarRefs = &no_var_iters;
1485 
1486     if (fc->get_pos_var())
1487     {
1488       ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() == 2);
1489 
1490       posVarRefs = &clauseVarMap->theVarRebinds[1]->theOutputVarRefs;
1491     }
1492 
1493     if (fc->is_allowing_empty())
1494       return new flwor::OuterForIterator(sctx, var->get_loc(), var->get_name(),
1495                                          PREV_ITER, domainIter, varRefs,*posVarRefs);
1496     else
1497       return new flwor::ForIterator(sctx, var->get_loc(), var->get_name(),
1498                                     PREV_ITER, domainIter, varRefs, *posVarRefs);
1499   }
1500 
1501   //
1502   // LET
1503   //
1504   else if (c.get_kind() == flwor_clause::let_clause)
1505   {
1506     const let_clause* lc = static_cast<const let_clause *>(&c);
1507 
1508     ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() == 1);
1509 
1510     var_expr* var = lc->get_var();
1511 
1512     PlanIter_t domainIter = pop_itstack();
1513 
1514     std::vector<PlanIter_t>& varRefs = clauseVarMap->theVarRebinds[0]->theOutputVarRefs;
1515 
1516     return new flwor::LetIterator(sctx,
1517                                   var->get_loc(),
1518                                   var->get_name(),
1519                                   PREV_ITER,
1520                                   domainIter,
1521                                   varRefs,
1522                                   lc->lazyEval(),
1523                                   true);  // materilize
1524   }
1525 
1526   //
1527   // WINDOW
1528   //
1529   else if (c.get_kind() == flwor_clause::window_clause)
1530   {
1531     const window_clause* wc = static_cast<const window_clause *>(&c);
1532 
1533     var_expr* var = wc->get_var();
1534     PlanIter_t domainIter = pop_itstack();
1535 
1536     std::vector<PlanIter_t>& varRefs = clauseVarMap->theVarRebinds[0]->theOutputVarRefs;
1537 
1538     std::auto_ptr<flwor::StartClause> start_clause;
1539     std::auto_ptr<flwor::EndClause> end_clause;
1540     const flwor_wincond* cond;
1541     ulong varPos = 1;
1542 
1543     if (NULL == (cond = wc->get_win_stop()))
1544     {
1545       end_clause.reset(new flwor::EndClause);
1546     }
1547     else
1548     {
1549       wincond_var_iters wcv(cond, clauseVarMap, varPos);
1550 
1551       flwor::WindowVars wvars(*wcv.inCurr, *wcv.inPrev, *wcv.inNext, *wcv.inPos,
1552                               *wcv.outCurr, *wcv.outPrev, *wcv.outNext, *wcv.outPos);
1553 
1554       end_clause.reset(new flwor::EndClause(pop_itstack(), wvars, cond->is_only()));
1555     }
1556 
1557     if (NULL != (cond = wc->get_win_start()))
1558     {
1559       wincond_var_iters wcv(cond, clauseVarMap, varPos);
1560 
1561       flwor::WindowVars wvars(*wcv.inCurr, *wcv.inPrev, *wcv.inNext, *wcv.inPos,
1562                               *wcv.outCurr, *wcv.outPrev, *wcv.outNext, *wcv.outPos);
1563 
1564       start_clause.reset(new flwor::StartClause(pop_itstack(), wvars));
1565     }
1566 
1567     return new flwor::WindowIterator(sctx,
1568                                      var->get_loc(),
1569                                      wc->get_winkind() == window_clause::tumbling_window ? flwor::WindowIterator::TUMBLING : flwor::WindowIterator::SLIDING,
1570                                      PREV_ITER,
1571                                      domainIter,
1572                                      var->get_name(),
1573                                      varRefs,
1574                                      *start_clause,
1575                                      *end_clause,
1576                                      wc->lazyEval());
1577   }
1578 
1579   //
1580   // COUNT
1581   //
1582   else if (c.get_kind() == flwor_clause::count_clause)
1583   {
1584     var_expr* var = static_cast<const count_clause *>(&c)->get_var();
1585 
1586     ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() == 1);
1587 
1588     std::vector<PlanIter_t>& var_iters = clauseVarMap->theVarRebinds[0]->theOutputVarRefs;
1589 
1590     return new flwor::CountIterator(sctx,
1591                                     var->get_loc(),
1592                                     var->get_name(),
1593                                     PREV_ITER,
1594                                     var_iters);
1595   }
1596 
1597   //
1598   // ORDERBY
1599   //
1600   else if (c.get_kind() == flwor_clause::order_clause)
1601   {
1602     ulong numVars = (ulong)clauseVarMap->theVarRebinds.size();
1603     ulong numForVars = 0;
1604     ulong numLetVars = 0;
1605 
1606     std::vector<ForVarIter_t> inputForVars(numVars);
1607     std::vector<LetVarIter_t> inputLetVars(numVars);
1608     std::vector<std::vector<PlanIter_t> > outputForVarsRefs(numVars);
1609     std::vector<std::vector<PlanIter_t> > outputLetVarsRefs(numVars);
1610 
1611     for (ulong i = 0; i < numVars; ++i)
1612     {
1613       VarRebind* varRebind = clauseVarMap->theVarRebinds[i].getp();
1614 
1615       ForVarIterator* forIter = dynamic_cast<ForVarIterator*>
1616                                 (varRebind->theInputVar.getp());
1617 
1618       if (forIter != NULL)
1619       {
1620         inputForVars[numForVars] = forIter;
1621 
1622         outputForVarsRefs[numForVars] = varRebind->theOutputVarRefs;
1623         ++numForVars;
1624       }
1625       else
1626       {
1627         LetVarIterator* letIter = dynamic_cast<LetVarIterator*>
1628                                 (varRebind->theInputVar.getp());
1629         ZORBA_ASSERT(letIter != NULL);
1630 
1631         inputLetVars[numLetVars] = letIter;
1632 
1633         outputLetVarsRefs[numLetVars] = varRebind->theOutputVarRefs;
1634         ++numLetVars;
1635       }
1636     }
1637 
1638     inputForVars.resize(numForVars);
1639     outputForVarsRefs.resize(numForVars);
1640     inputLetVars.resize(numLetVars);
1641     outputLetVarsRefs.resize(numLetVars);
1642 
1643     const orderby_clause* obc = static_cast<const orderby_clause *>(&c);
1644     ulong numColumns = obc->num_columns();
1645     const std::vector<OrderModifier>& modifiers = obc->get_modifiers();
1646 
1647     std::vector<flwor::OrderSpec> orderSpecs(numColumns);
1648 
1649     for (long i = numColumns - 1; i >= 0; --i)
1650     {
1651       bool emptyLeast = modifiers[i].theEmptyLeast;
1652       bool descending = !modifiers[i].theAscending;
1653 
1654       orderSpecs[i] = flwor::OrderSpec(pop_itstack(),
1655                                        emptyLeast,
1656                                        descending,
1657                                        nativeColumnSort(obc->get_column_expr(i)),
1658                                        modifiers[i].theCollation);
1659     }
1660 
1661     return new flwor::OrderByIterator(sctx,
1662                                       c.get_loc(),
1663                                       obc->is_stable(),
1664                                       orderSpecs,
1665                                       PREV_ITER,
1666                                       inputForVars,
1667                                       inputLetVars,
1668                                       outputForVarsRefs,
1669                                       outputLetVarsRefs);
1670   }
1671 
1672   //
1673   // GROUPBY
1674   //
1675   else if (c.get_kind() == flwor_clause::group_clause)
1676   {
1677     std::vector<flwor::GroupingSpec> gspecs;
1678     std::vector<flwor::NonGroupingSpec> ngspecs;
1679 
1680     generate_groupby(clauseVarMap, gspecs, ngspecs);
1681 
1682     return new flwor::GroupByIterator(sctx, c.get_loc(), PREV_ITER, gspecs, ngspecs);
1683   }
1684 
1685   ZORBA_ASSERT (false);
1686   return NULL;
1687 #undef PREV_ITER
1688 }
1689 
1690 
flwor_codegen(const flwor_expr & flworExpr)1691 void flwor_codegen(const flwor_expr& flworExpr)
1692 {
1693   flwor::FLWORIterator* flworIter;
1694   PlanIter_t returnIter;
1695   std::auto_ptr<flwor::OrderByClause> orderClause(NULL);
1696   std::auto_ptr<flwor::GroupByClause> groupClause(NULL);
1697   std::auto_ptr<flwor::MaterializeClause> materializeClause(NULL);
1698   PlanIter_t whereIter;
1699   std::vector<flwor::ForLetClause> forletClauses;
1700 
1701   csize numClauses = flworExpr.num_clauses();
1702 
1703   returnIter = pop_itstack();
1704 
1705   for (int it = numClauses - 1; it >= 0; --it)
1706   {
1707     const flwor_clause& c = *flworExpr.get_clause(it);
1708 
1709     FlworClauseVarMap_t clauseVarMap;
1710 
1711     if (c.get_kind() != flwor_clause::where_clause)
1712     {
1713       ZORBA_ASSERT(!theClauseStack.empty());
1714       csize stackSize = theClauseStack.size();
1715 
1716       clauseVarMap = theClauseStack[stackSize-1];
1717       theClauseStack.resize(stackSize - 1);
1718 
1719       ZORBA_ASSERT(clauseVarMap->theClause == &c);
1720     }
1721 
1722     switch (c.get_kind())
1723     {
1724     //
1725     // MATERIALIZE
1726     //
1727     case flwor_clause::materialize_clause:
1728     {
1729       ulong numVars = (ulong)clauseVarMap->theVarRebinds.size();
1730       ulong numForVars = 0;
1731       ulong numLetVars = 0;
1732 
1733       std::vector<ForVarIter_t> inputForVars(numVars);
1734       std::vector<LetVarIter_t> inputLetVars(numVars);
1735       std::vector<std::vector<PlanIter_t> > outputForVarsRefs(numVars);
1736       std::vector<std::vector<PlanIter_t> > outputLetVarsRefs(numVars);
1737 
1738       for (ulong i = 0; i < numVars; ++i)
1739       {
1740         VarRebind* varRebind = clauseVarMap->theVarRebinds[i];
1741 
1742         ForVarIterator* forIter = dynamic_cast<ForVarIterator*>
1743                                   (varRebind->theInputVar.getp());
1744 
1745         if (forIter != NULL)
1746         {
1747           inputForVars[numForVars] = forIter;
1748 
1749           outputForVarsRefs[numForVars] = varRebind->theOutputVarRefs;
1750           ++numForVars;
1751         }
1752         else
1753         {
1754           LetVarIterator* letIter = dynamic_cast<LetVarIterator*>
1755                                     (varRebind->theInputVar.getp());
1756           ZORBA_ASSERT(letIter != NULL);
1757 
1758           inputLetVars[numLetVars] = letIter;
1759 
1760           outputLetVarsRefs[numLetVars] = varRebind->theOutputVarRefs;
1761           ++numLetVars;
1762         }
1763       }
1764 
1765       inputForVars.resize(numForVars);
1766       outputForVarsRefs.resize(numForVars);
1767       inputLetVars.resize(numLetVars);
1768       outputLetVarsRefs.resize(numLetVars);
1769 
1770       materializeClause.reset(new flwor::MaterializeClause(c.get_loc(),
1771                                                            inputForVars,
1772                                                            inputLetVars,
1773                                                            outputForVarsRefs,
1774                                                            outputLetVarsRefs));
1775 
1776       break;
1777     }
1778 
1779     //
1780     // ORDERBY
1781     //
1782     case flwor_clause::order_clause:
1783     {
1784       const orderby_clause* obc = static_cast<const orderby_clause*>(&c);
1785       unsigned numColumns = obc->num_columns();
1786       const std::vector<OrderModifier>& modifiers = obc->get_modifiers();
1787 
1788       std::vector<flwor::OrderSpec> orderSpecs(numColumns);
1789 
1790       for (int i = numColumns - 1; i >= 0; --i)
1791       {
1792         bool emptyLeast = modifiers[i].theEmptyLeast;
1793         bool descending = !modifiers[i].theAscending;
1794 
1795         orderSpecs[i] = flwor::OrderSpec(pop_itstack(),
1796                                          emptyLeast,
1797                                          descending,
1798                                          nativeColumnSort(obc->get_column_expr(i)),
1799                                          modifiers[i].theCollation);
1800       }
1801 
1802       orderClause.reset(new flwor::OrderByClause(obc->get_loc(),
1803                                                  orderSpecs,
1804                                                  obc->is_stable()));
1805       break;
1806     }
1807 
1808     //
1809     // GROUPBY
1810     //
1811     case flwor_clause::group_clause:
1812     {
1813       std::vector<flwor::GroupingSpec> gspecs;
1814       std::vector<flwor::NonGroupingSpec> ngspecs;
1815 
1816       generate_groupby(clauseVarMap, gspecs, ngspecs);
1817 
1818       groupClause.reset(new flwor::GroupByClause(c.get_loc(), gspecs, ngspecs));
1819 
1820       break;
1821     }
1822 
1823     //
1824     // WHERE
1825     //
1826     case flwor_clause::where_clause:
1827     {
1828       whereIter = pop_itstack();
1829       break;
1830     }
1831 
1832     //
1833     // FOR
1834     //
1835     case flwor_clause::for_clause:
1836     {
1837       const for_clause* fc = static_cast<const for_clause *>(&c);
1838 
1839       ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() >= 1);
1840 
1841       var_expr* var = fc->get_var();
1842 
1843       PlanIter_t domainIter = pop_itstack();
1844 
1845       std::vector<PlanIter_t>& varRefs =
1846       clauseVarMap->theVarRebinds[0]->theOutputVarRefs;
1847 
1848       if (fc->get_pos_var())
1849       {
1850         ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() == 2);
1851 
1852         std::vector<PlanIter_t>& posVarRefs =
1853         clauseVarMap->theVarRebinds[1]->theOutputVarRefs;
1854 
1855         forletClauses.push_back(flwor::ForLetClause(var->get_name(),
1856                                                     varRefs,
1857                                                     posVarRefs,
1858                                                     domainIter));
1859       }
1860       else
1861       {
1862         ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() == 1);
1863 
1864         forletClauses.push_back(flwor::ForLetClause(var->get_name(),
1865                                                     varRefs,
1866                                                     domainIter));
1867       }
1868 
1869       break;
1870     }
1871 
1872     //
1873     // LET
1874     //
1875     case flwor_clause::let_clause:
1876     {
1877       const let_clause* lc = static_cast<const let_clause *>(&c);
1878 
1879       ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() == 1);
1880 
1881       var_expr* var = lc->get_var();
1882 
1883       PlanIter_t domainIter = pop_itstack();
1884 
1885       std::vector<PlanIter_t>& varRefs =
1886       clauseVarMap->theVarRebinds[0]->theOutputVarRefs;
1887 
1888       forletClauses.push_back(flwor::ForLetClause(var->get_name(),
1889                                                   varRefs,
1890                                                   domainIter,
1891                                                   lc->lazyEval(),
1892                                                   true)); // materialize
1893       break;
1894     }
1895 
1896     default:
1897     {
1898       ZORBA_ASSERT(false);
1899     }
1900     }
1901   }
1902 
1903   std::reverse(forletClauses.begin(), forletClauses.end());
1904 
1905   flworIter = new flwor::FLWORIterator(flworExpr.get_sctx(),
1906                                        flworExpr.get_loc(),
1907                                        forletClauses,
1908                                        whereIter,
1909                                        groupClause.release(),
1910                                        orderClause.release(),
1911                                        materializeClause.release(),
1912                                        returnIter);
1913   push_itstack(flworIter);
1914 }
1915 
1916 
generate_groupby(const FlworClauseVarMap * clauseVarMap,std::vector<flwor::GroupingSpec> & gspecs,std::vector<flwor::NonGroupingSpec> & ngspecs)1917 void generate_groupby(
1918     const FlworClauseVarMap* clauseVarMap,
1919     std::vector<flwor::GroupingSpec>& gspecs,
1920     std::vector<flwor::NonGroupingSpec>& ngspecs)
1921 {
1922   const group_clause* gbc = static_cast<const group_clause*>(clauseVarMap->theClause);
1923 
1924   const group_clause::rebind_list_t& gvars = gbc->get_grouping_vars();
1925   const group_clause::rebind_list_t& ngvars = gbc->get_nongrouping_vars();
1926 
1927   const std::vector<std::string>& collations = gbc->get_collations();
1928 
1929   long numVars = (long)(gvars.size() + ngvars.size());
1930   long numGroupVars = (long)gvars.size();
1931   long i = numVars - 1;
1932 
1933   for (; i >= numGroupVars; --i)
1934   {
1935     VarRebind* varRebind = clauseVarMap->theVarRebinds[i].getp();
1936 
1937     const std::vector<PlanIter_t>& varRefs = varRebind->theOutputVarRefs;
1938 
1939     ngspecs.push_back(flwor::NonGroupingSpec(pop_itstack(), varRefs));
1940   }
1941 
1942   for (; i >= 0; --i)
1943   {
1944     VarRebind* varRebind = clauseVarMap->theVarRebinds[i].getp();
1945 
1946     const std::vector<PlanIter_t>& varRefs = varRebind->theOutputVarRefs;
1947 
1948     bool fastComparison = nativeColumnSort(clauseVarMap->theVarExprs[i]);
1949 
1950     gspecs.push_back(flwor::GroupingSpec(pop_itstack(),
1951                                          varRefs,
1952                                          collations[i],
1953                                          fastComparison));
1954   }
1955 }
1956 
1957 
1958 /*******************************************************************************
1959 
1960 ********************************************************************************/
begin_visit(promote_expr & v)1961 bool begin_visit(promote_expr& v)
1962 {
1963   CODEGEN_TRACE_IN("");
1964   return true;
1965 }
1966 
end_visit(promote_expr & v)1967 void end_visit(promote_expr& v)
1968 {
1969   CODEGEN_TRACE_OUT("");
1970   PlanIter_t child = pop_itstack();
1971   // TODO: Currently we use cast. Promotion may be more efficient.
1972   push_itstack(new PromoteIterator(sctx,
1973                                    qloc,
1974                                    child,
1975                                    v.get_target_type(),
1976                                    v.get_err(),
1977                                    v.get_qname()));
1978 }
1979 
1980 
1981 /***************************************************************************//**
1982 
1983 ********************************************************************************/
begin_visit(trycatch_expr & v)1984 bool begin_visit(trycatch_expr& v)
1985 {
1986   CODEGEN_TRACE_IN("");
1987 
1988   for(int i = v.clause_count() - 1; i >= 0; --i)
1989   {
1990     catch_clause* cc = const_cast<catch_clause*>(v[i]);
1991     catch_clause::var_map_t& vars = cc->get_vars();
1992 
1993     for (catch_clause::var_map_t::const_iterator lIter = vars.begin();
1994          lIter != vars.end();
1995          ++lIter)
1996     {
1997       catchvar_iter_map.put((uint64_t)&*(lIter->second), new std::vector<LetVarIter_t>());
1998     }
1999   }
2000   return true;
2001 }
2002 
end_visit(trycatch_expr & v)2003 void end_visit(trycatch_expr& v)
2004 {
2005   CODEGEN_TRACE_OUT("");
2006 
2007   std::vector<LetVarIter_t> *vec = NULL;
2008   std::vector<TryCatchIterator::CatchClause> rev_ccs;
2009 
2010   for(int i = v.clause_count() - 1; i >= 0; --i)
2011   {
2012     catch_clause* cc = const_cast<catch_clause*>(v[i]);
2013     TryCatchIterator::CatchClause rcc;
2014     rcc.node_names = cc->get_nametests();
2015     rcc.catch_expr = pop_itstack();
2016     catch_clause::var_map_t& vars = cc->get_vars();
2017 
2018     for (catch_clause::var_map_t::const_iterator lIter = vars.begin();
2019          lIter != vars.end();
2020          ++lIter)
2021     {
2022       bool bound = catchvar_iter_map.get((uint64_t)&*(lIter->second), vec);
2023       ZORBA_ASSERT(bound);
2024       catch_clause::var_type var_type = (catch_clause::var_type)lIter->first;
2025 
2026       switch (var_type)
2027       {
2028       case catch_clause::err_code:
2029         rcc.theVars[TryCatchIterator::CatchClause::err_code] = *vec;
2030         break;
2031       case catch_clause::err_desc:
2032         rcc.theVars[TryCatchIterator::CatchClause::err_desc] = *vec;
2033         break;
2034       case catch_clause::err_value:
2035         rcc.theVars[TryCatchIterator::CatchClause::err_value] = *vec;
2036         break;
2037       case catch_clause::err_module:
2038         rcc.theVars[TryCatchIterator::CatchClause::err_module] = *vec;
2039         break;
2040       case catch_clause::err_line_no:
2041         rcc.theVars[TryCatchIterator::CatchClause::err_line_no] = *vec;
2042         break;
2043       case catch_clause::err_column_no:
2044         rcc.theVars[TryCatchIterator::CatchClause::err_column_no] = *vec;
2045         break;
2046       case catch_clause::zerr_stack_trace:
2047         rcc.theVars[TryCatchIterator::CatchClause::zerr_stack_trace] = *vec;
2048         break;
2049       default:
2050         ZORBA_ASSERT(false);
2051       }
2052     }
2053 
2054     rev_ccs.push_back(rcc);
2055   }
2056 
2057   std::vector<TryCatchIterator::CatchClause> ccs(rev_ccs.rbegin(), rev_ccs.rend());
2058   PlanIter_t lChild = pop_itstack();
2059 
2060   push_itstack(new TryCatchIterator(sctx, qloc, lChild, ccs));
2061 }
2062 
2063 
2064 /***************************************************************************//**
2065 
2066 ********************************************************************************/
begin_visit(eval_expr & v)2067 bool begin_visit(eval_expr& v)
2068 {
2069   CODEGEN_TRACE_IN("");
2070   return true;
2071 }
2072 
end_visit(eval_expr & v)2073 void end_visit(eval_expr& v)
2074 {
2075   CODEGEN_TRACE_OUT("");
2076 
2077   csize numVars = v.num_vars();
2078 
2079   checked_vector<PlanIter_t> args;
2080   args.reserve(numVars+1);
2081 
2082   std::vector<int> isGlobalVar(numVars);
2083 
2084   for (csize i = numVars; i > 0; --i)
2085   {
2086     isGlobalVar[i-1] = false;
2087 
2088     expr* arg = v.get_arg_expr(i-1);
2089 
2090     if (arg->get_expr_kind() == var_expr_kind)
2091     {
2092       var_expr* varArg = static_cast<var_expr*>(arg);
2093 
2094       if (varArg->get_kind() == var_expr::prolog_var)
2095         isGlobalVar[i-1] = true;
2096     }
2097 
2098     if (!isGlobalVar[i-1])
2099     {
2100       args.push_back(pop_itstack());
2101     }
2102     else
2103     {
2104       pop_itstack();
2105     }
2106   }
2107 
2108   args.push_back(pop_itstack());
2109   reverse(args.begin(), args.end());
2110 
2111   store::NsBindings localBindings;
2112   v.getNSCtx()->getAllBindings(localBindings);
2113 
2114   push_itstack(new EvalIterator(sctx,
2115                                 qloc,
2116                                 args,
2117                                 v.get_var_names(),
2118                                 v.get_var_types(),
2119                                 isGlobalVar,
2120                                 v.get_inner_scripting_kind(),
2121                                 localBindings,
2122                                 v.getNodeCopy(),
2123                                 false));
2124 }
2125 
2126 #ifdef ZORBA_WITH_DEBUGGER
begin_visit(debugger_expr & v)2127 bool begin_visit(debugger_expr& v)
2128 {
2129   CODEGEN_TRACE_IN("");
2130 
2131   // already create the debugger iterator here
2132   // because it's used for connecting all debugger
2133   // iterators in the tree (see end_visit below)
2134   std::vector<PlanIter_t> aTmpVec;
2135   DebugIterator* lIterator = new DebugIterator(sctx, qloc, aTmpVec);
2136   lIterator->setVarDeclaration(v.isVarDeclaration());
2137   theDebuggerStack.push(lIterator);
2138   return true;
2139 }
2140 
end_visit(debugger_expr & v)2141 void end_visit(debugger_expr& v)
2142 {
2143   CODEGEN_TRACE_OUT("");
2144 
2145   // generate an eval iterator and populate it with the in-scope variables
2146 
2147   std::vector<PlanIter_t> argvEvalIter;
2148 
2149   csize numVars = v.var_count();
2150   std::vector<store::Item_t> varNames(numVars);
2151   std::vector<xqtref_t> varTypes(numVars);
2152   std::vector<int> isGlobalVar(numVars);
2153 
2154   //create the eval iterator children
2155   for (csize i = 0; i < numVars; i++)
2156   {
2157     varNames[i] = v.get_var(i)->get_name();
2158     varTypes[i] = v.get_var(i)->get_type();
2159     isGlobalVar[i] = (v.get_var(i)->get_kind() == var_expr::prolog_var);
2160 
2161     argvEvalIter.push_back(pop_itstack());
2162   }
2163 
2164   argvEvalIter.push_back(new DebuggerSingletonIterator(sctx,
2165                                                        qloc,
2166                                                        theCCB->theDebuggerCommons));
2167 
2168   // now reverse them (first the expression, then the variables)
2169   reverse(argvEvalIter.begin(), argvEvalIter.end());
2170 
2171   // get the debugger iterator from the debugger stack
2172   std::auto_ptr<DebugIterator> lDebugIterator(theDebuggerStack.top());
2173   theDebuggerStack.pop();
2174 
2175   // set the children of the debugger iterator
2176   // child 0: the iterator of the wrapped expression
2177   // child 1: the eval iterator
2178 
2179   // child 0
2180   std::vector<PlanIter_t> argv;
2181   argv.push_back(pop_itstack());
2182 
2183   // child 1
2184   store::NsBindings localBindings;
2185   if (v.getNSCtx())
2186   {
2187     v.getNSCtx()->getAllBindings(localBindings);
2188   }
2189 
2190   argv.push_back(new EvalIterator(sctx,
2191                                   qloc,
2192                                   argvEvalIter,
2193                                   varNames,
2194                                   varTypes,
2195                                   isGlobalVar,
2196                                   SEQUENTIAL_FUNC_EXPR,
2197                                   localBindings,
2198                                   true,
2199                                   true));
2200 
2201   lDebugIterator->setChildren(&argv);
2202   lDebugIterator->setVariables(varNames, varTypes);
2203 
2204   // link all debugger iterators in the tree
2205   if (!theDebuggerStack.empty())
2206   {
2207     theDebuggerStack.top()->addChild(lDebugIterator.get());
2208     lDebugIterator->setParent(theDebuggerStack.top());
2209   }
2210 
2211   push_itstack(lDebugIterator.release());
2212 }
2213 #endif
2214 
2215 
begin_visit(if_expr & v)2216 bool begin_visit(if_expr& v)
2217 {
2218   CODEGEN_TRACE_IN("");
2219   return true;
2220 }
2221 
2222 
end_visit(if_expr & v)2223 void end_visit(if_expr& v)
2224 {
2225   CODEGEN_TRACE_OUT("");
2226   PlanIter_t iterElse = pop_itstack();
2227   PlanIter_t iterThen = pop_itstack();
2228   PlanIter_t iterCond = pop_itstack();
2229 
2230   PlanIter_t iterIfThenElse =
2231   new IfThenElseIterator(sctx, qloc, iterCond, iterThen, iterElse);
2232 
2233   push_itstack(&*iterIfThenElse);
2234 }
2235 
2236 
begin_visit(exit_expr & v)2237 bool begin_visit(exit_expr& v)
2238 {
2239   CODEGEN_TRACE_IN("");
2240   return true;
2241 }
2242 
end_visit(exit_expr & v)2243 void end_visit(exit_expr& v)
2244 {
2245   CODEGEN_TRACE_OUT("");
2246   push_itstack(new ExitIterator(sctx, qloc, pop_itstack()));
2247 }
2248 
2249 
begin_visit(exit_catcher_expr & v)2250 bool begin_visit(exit_catcher_expr& v)
2251 {
2252   CODEGEN_TRACE_IN("");
2253   return true;
2254 }
2255 
end_visit(exit_catcher_expr & v)2256 void end_visit(exit_catcher_expr& v)
2257 {
2258   CODEGEN_TRACE_OUT("");
2259   push_itstack(new ExitCatcherIterator(sctx, qloc, pop_itstack()));
2260 }
2261 
2262 
begin_visit(flowctl_expr & v)2263 bool begin_visit(flowctl_expr& v)
2264 {
2265   CODEGEN_TRACE_IN("");
2266   return true;
2267 }
2268 
end_visit(flowctl_expr & v)2269 void end_visit(flowctl_expr& v)
2270 {
2271   CODEGEN_TRACE_OUT("");
2272   enum FlowCtlException::action a;
2273   switch (v.get_action())
2274   {
2275   case flowctl_expr::BREAK:
2276     a = FlowCtlException::BREAK;
2277     break;
2278   case flowctl_expr::CONTINUE:
2279     a = FlowCtlException::CONTINUE;
2280     break;
2281   default:
2282     ZORBA_FATAL(false, "");
2283   }
2284 
2285   push_itstack(new FlowCtlIterator(sctx, qloc, a));
2286 }
2287 
2288 
begin_visit(while_expr & v)2289 bool begin_visit(while_expr& v)
2290 {
2291   CODEGEN_TRACE_IN("");
2292   return true;
2293 }
2294 
end_visit(while_expr & v)2295 void end_visit(while_expr& v)
2296 {
2297   CODEGEN_TRACE_OUT("");
2298   push_itstack(new LoopIterator (sctx, qloc, pop_itstack()));
2299 }
2300 
2301 
begin_visit(fo_expr & v)2302 bool begin_visit(fo_expr& v)
2303 {
2304   CODEGEN_TRACE_IN("");
2305 
2306   const function* func = v.get_func();
2307   ZORBA_ASSERT(func != NULL);
2308 
2309   // If the function is an enclosed expression, push it in the constructors
2310   // stack to "hide" the current constructor context, if any. This way, a new
2311   // constructor context can be started if a node constructor exists inside
2312   // the enclosed expr.
2313   if (is_enclosed_expr(&v))
2314     theConstructorsStack.push(&v);
2315 
2316 	return true;
2317 }
2318 
2319 
end_visit(fo_expr & v)2320 void end_visit(fo_expr& v)
2321 {
2322   CODEGEN_TRACE_OUT("");
2323 
2324   function* func = v.get_func();
2325 
2326   std::vector<PlanIter_t> argv;
2327 
2328   argv.resize(v.num_args());
2329   generate(argv.rbegin(), argv.rend(), ztd::stack_to_generator(itstack));
2330 
2331   const QueryLoc& loc = qloc;
2332 
2333   if (v.is_sequential())
2334   {
2335     ulong numArgs = v.num_args();
2336     for (ulong i = 0; i < numArgs; ++i)
2337     {
2338       if (v.get_arg(i)->is_sequential())
2339       {
2340         argv[i] = new MaterializeIterator(sctx, v.get_arg(i)->get_loc(), argv[i]);
2341       }
2342     }
2343   }
2344 
2345   if (func->validate_args(argv))
2346   {
2347     PlanIter_t iter = func->codegen(theCCB, sctx, loc, argv, v);
2348     ZORBA_ASSERT(iter != NULL);
2349     push_itstack(iter);
2350 
2351     if (is_enclosed_expr(&v))
2352     {
2353       expr* e = plan_visitor_ns::pop_stack(theConstructorsStack);
2354       ZORBA_ASSERT(e == &v);
2355 
2356       if (!theEnclosedContextStack.empty())
2357       {
2358         EnclosedExprContext ctx = theEnclosedContextStack.top();
2359 
2360         if (ctx == ATTRIBUTE_CONTENT)
2361           dynamic_cast<EnclosedIterator*>(iter.getp())->setAttrContent();
2362         else if (ctx == TEXT_CONTENT)
2363           dynamic_cast<EnclosedIterator*>(iter.getp())->setTextContent();
2364         else if (ctx == UPDATE_CONTEXT)
2365           dynamic_cast<EnclosedIterator*>(iter.getp())->setInUpdateExpr();
2366       }
2367     }
2368     else if (func->isUdf())
2369     {
2370       // need to computeResultCaching here for iterprint to work
2371       user_function* udf = static_cast<user_function*>(func);
2372       udf->computeResultCaching(theCCB->theXQueryDiagnostics);
2373     }
2374   }
2375   else
2376   {
2377     throw XQUERY_EXCEPTION(err::XPST0017,
2378                            ERROR_PARAMS(func->getName()->getStringValue(),
2379                                         ZED(FunctionUndeclared_3),
2380                                         argv.size()),
2381                            ERROR_LOC(loc));
2382   }
2383 }
2384 
2385 
begin_visit(instanceof_expr & v)2386 bool begin_visit(instanceof_expr& v)
2387 {
2388   CODEGEN_TRACE_IN("");
2389   return true;
2390 }
2391 
2392 
end_visit(instanceof_expr & v)2393 void end_visit(instanceof_expr& v)
2394 {
2395   CODEGEN_TRACE_OUT("");
2396   PlanIter_t p = pop_itstack ();
2397   push_itstack (new InstanceOfIterator (sctx, qloc, p, v.get_target_type ()));
2398 }
2399 
2400 
begin_visit(treat_expr & v)2401 bool begin_visit(treat_expr& v)
2402 {
2403   CODEGEN_TRACE_IN("");
2404   return true;
2405 }
2406 
2407 
end_visit(treat_expr & v)2408 void end_visit(treat_expr& v)
2409 {
2410   CODEGEN_TRACE_OUT("");
2411   PlanIter_t arg;
2412   arg = pop_itstack();
2413   push_itstack(new TreatIterator(sctx, qloc, arg,
2414                                  v.get_target_type(),
2415                                  v.get_check_prime(),
2416                                  v.get_err(),
2417                                  v.get_qname()));
2418 }
2419 
2420 
begin_visit(castable_expr & v)2421 bool begin_visit(castable_expr& v)
2422 {
2423   CODEGEN_TRACE_IN("");
2424   return true;
2425 }
2426 
2427 
end_visit(castable_expr & v)2428 void end_visit(castable_expr& v)
2429 {
2430   CODEGEN_TRACE_OUT("");
2431   PlanIter_t lChild = pop_itstack();
2432   push_itstack(new CastableIterator(sctx, qloc, lChild, v.get_target_type()));
2433 }
2434 
2435 
begin_visit(cast_expr & v)2436 bool begin_visit(cast_expr& v)
2437 {
2438   CODEGEN_TRACE_IN("");
2439   return true;
2440 }
2441 
2442 
end_visit(cast_expr & v)2443 void end_visit(cast_expr& v)
2444 {
2445   CODEGEN_TRACE_OUT("");
2446   PlanIter_t lChild = pop_itstack();
2447   push_itstack(new CastIterator(sctx, qloc, lChild, v.get_target_type()));
2448 }
2449 
2450 
begin_visit(name_cast_expr & v)2451 bool begin_visit(name_cast_expr& v)
2452 {
2453   CODEGEN_TRACE_IN("");
2454 
2455   RootTypeManager& rtm = GENV_TYPESYSTEM;
2456   TypeManager* tm = v.get_type_manager();
2457 
2458   expr* targetExpr = v.get_input();
2459   xqtref_t targetType = targetExpr->get_return_type();
2460 
2461   if (TypeOps::is_subtype(tm, *rtm.UNTYPED_ATOMIC_TYPE_ONE, *targetType, qloc) ||
2462       TypeOps::is_subtype(tm, *targetType, *rtm.UNTYPED_ATOMIC_TYPE_ONE, qloc) ||
2463       TypeOps::is_subtype(tm, *rtm.QNAME_TYPE_ONE, *targetType, qloc) ||
2464       TypeOps::is_subtype(tm, *targetType, *rtm.QNAME_TYPE_ONE, qloc) ||
2465       TypeOps::is_subtype(tm, *rtm.NCNAME_TYPE_ONE, *targetType, qloc) ||
2466       TypeOps::is_subtype(tm, *targetType, *rtm.NCNAME_TYPE_ONE, qloc) ||
2467       TypeOps::is_subtype(tm, *rtm.STRING_TYPE_ONE, *targetType, qloc) ||
2468       TypeOps::is_subtype(tm, *targetType, *rtm.STRING_TYPE_ONE, qloc))
2469     return true;
2470 
2471   throw XQUERY_EXCEPTION(
2472     err::XPTY0004,
2473     ERROR_PARAMS( ZED( BadType_23o ), *targetType ),
2474     ERROR_LOC( qloc )
2475   );
2476 }
2477 
end_visit(name_cast_expr & v)2478 void end_visit(name_cast_expr& v)
2479 {
2480   CODEGEN_TRACE_OUT("");
2481   PlanIter_t child = pop_itstack();
2482   push_itstack(new NameCastIterator(sctx,
2483                                     qloc,
2484                                     child,
2485                                     v.getNSCtx(),
2486                                     v.is_attr_name()));
2487 }
2488 
2489 
begin_visit(validate_expr & v)2490 bool begin_visit(validate_expr& v)
2491 {
2492   CODEGEN_TRACE_IN("");
2493   return true;
2494 }
2495 
end_visit(validate_expr & v)2496 void end_visit(validate_expr& v)
2497 {
2498   CODEGEN_TRACE_OUT("");
2499 
2500 #ifndef ZORBA_NO_XMLSCHEMA
2501   PlanIter_t lChild = pop_itstack();
2502   //store::Item_t typeName = v.get_type_name();
2503   //std::cout << "validate end-visit: type: " << typeName->getLocalName()->c_str() << " @ " << typeName->getNamespace()->c_str() << "\n"; cout.flush();
2504   push_itstack (new ValidateIterator(sctx,
2505                                      qloc,
2506                                      lChild,
2507                                      v.get_valmode(),
2508                                      v.get_typemgr(),
2509                                      const_cast<store::Item*>(v.get_type_name())));
2510 #else
2511   //no schema support
2512   throw XQUERY_EXCEPTION(err::XQST0009, ERROR_LOC(qloc));
2513 #endif
2514 }
2515 
2516 
begin_visit(extension_expr & v)2517 bool begin_visit(extension_expr& v) {
2518   CODEGEN_TRACE_IN("");
2519   return true;
2520 }
2521 
end_visit(extension_expr & v)2522 void end_visit(extension_expr& v)
2523 {
2524   CODEGEN_TRACE_OUT("");
2525 }
2526 
2527 
2528 #ifdef PATH_ITERATOR
2529 
2530 /*******************************************************************************
2531 
2532 ********************************************************************************/
begin_visit(relpath_expr & v)2533 bool begin_visit(relpath_expr& v)
2534 {
2535   CODEGEN_TRACE_IN("");
2536 
2537   //PlanIter_t input = pop_itstack();
2538   //ZORBA_ASSERT(input != NULL);
2539   //PlanIter_t pathIte(new PathIterator(qloc, input));
2540   //push_itstack(pathIte);
2541 
2542   return true;
2543 }
2544 
2545 
end_visit(relpath_expr & v)2546 void end_visit(relpath_expr& v)
2547 {
2548   CODEGEN_TRACE_OUT("");
2549 }
2550 
2551 
2552 /*******************************************************************************
2553 
2554 ********************************************************************************/
begin_visit(axis_step_expr & v)2555 bool begin_visit(axis_step_expr& v)
2556 {
2557   CODEGEN_TRACE_IN("");
2558 
2559   store::ItemFactory& factory = *(GENV.getStore().getItemFactory());
2560   store::Item_t qname;
2561 
2562   PlanIter_t& ite = plan_visitor_ns::peek_stack(itstack);
2563   PathIterator* pathIte = dynamic_cast<PathIterator*>(ite.getp());
2564 
2565   if (pathIte == NULL)
2566   {
2567     PlanIter_t inputStep = pop_itstack();
2568     pathIte = new PathIterator(sctx, qloc, inputStep);
2569     push_itstack(pathIte);
2570   }
2571   //ZORBA_ASSERT(pathIte != NULL);
2572 
2573   match_expr* testExpr = v.getTest();
2574 
2575   NodePredicate* prd = new NodePredicate();
2576 
2577   prd->setTestKind(testExpr->getTestKind());
2578 
2579   if (testExpr->getTestKind() == match_name_test)
2580   {
2581     if (v.getAxis() == axis_kind_attribute)
2582       prd->setNodeKind(store::StoreConsts::attributeNode);
2583     else
2584       prd->setNodeKind(store::StoreConsts::elementNode);
2585 
2586     match_wild_t wildKind = testExpr->getWildKind();
2587     prd->setWildKind(wildKind);
2588 
2589     if (wildKind == match_no_wild)
2590     {
2591       prd->setQName(testExpr->getQName());
2592     }
2593     else if (wildKind == match_prefix_wild)
2594     {
2595       factory.createQName(qname, "", "*", testExpr->getWildName().c_str());
2596 
2597       prd->setQName(qname);
2598     }
2599     else if (wildKind == match_name_wild)
2600     {
2601       prd->setQName(testExpr->getQName());
2602     }
2603   }
2604   else
2605   {
2606     prd->setDocTestKind(testExpr->getDocTestKind());
2607     prd->setNodeKind(testExpr->getNodeKind());
2608     prd->setQName(testExpr->getQName());
2609     store::Item* typeName = testExpr->getTypeName();
2610     if (typeName != NULL)
2611     {
2612       prd->setType(sctx->get_typemanager()->create_named_type(typeName,
2613                                                               TypeConstants::QUANT_ONE,
2614                                                               loc,
2615                                                               XPTY0004));
2616     }
2617     prd->setNilledAllowed(testExpr->getNilledAllowed());
2618   }
2619 
2620   pathIte->addStep(v.getAxis(), prd);
2621 
2622   return true;
2623 }
2624 
2625 
end_visit(axis_step_expr & v)2626 void end_visit(axis_step_expr& v)
2627 {
2628   CODEGEN_TRACE_OUT("");
2629 }
2630 
2631 
begin_visit(match_expr & v)2632 bool begin_visit(match_expr& v)
2633 {
2634   CODEGEN_TRACE_IN("");
2635 
2636   return true;
2637 }
2638 
2639 
end_visit(match_expr & v)2640 void end_visit(match_expr& v)
2641 {
2642   CODEGEN_TRACE_OUT("");
2643 }
2644 
2645 
2646 #else
2647 
2648 /*******************************************************************************
2649 
2650 ********************************************************************************/
begin_visit(relpath_expr & v)2651 bool begin_visit(relpath_expr& v)
2652 {
2653   CODEGEN_TRACE_IN("");
2654   // Done in axis itself
2655   return true;
2656 }
2657 
2658 
end_visit(relpath_expr & v)2659 void end_visit(relpath_expr& v)
2660 {
2661   CODEGEN_TRACE_OUT("");
2662 }
2663 
2664 
2665 /*******************************************************************************
2666 
2667 ********************************************************************************/
begin_visit(axis_step_expr & v)2668 bool begin_visit(axis_step_expr& v)
2669 {
2670   CODEGEN_TRACE_IN("");
2671 
2672   bool result = true;
2673 
2674   PlanIter_t input = pop_itstack();
2675 
2676   ZORBA_ASSERT(input != NULL);
2677 
2678   PlanIter_t axisIte;
2679 
2680   switch (v.getAxis())
2681   {
2682   case axis_kind_self:
2683   {
2684     axisIte = new SelfAxisIterator(sctx, qloc, input);
2685     break;
2686   }
2687   case axis_kind_child:
2688   {
2689     axisIte = new ChildAxisIterator(sctx, qloc, input);
2690     break;
2691   }
2692   case axis_kind_parent:
2693   {
2694     axisIte = new ParentAxisIterator(sctx, qloc, input);
2695     break;
2696   }
2697   case axis_kind_descendant:
2698   {
2699     axisIte = new DescendantAxisIterator(sctx, qloc, input);
2700     break;
2701   }
2702   case axis_kind_descendant_or_self:
2703   {
2704     axisIte = new DescendantSelfAxisIterator(sctx, qloc, input);
2705     break;
2706   }
2707   case axis_kind_ancestor:
2708   {
2709     if (v.use_reverse_order())
2710       axisIte = new AncestorReverseAxisIterator(sctx, qloc, input);
2711     else
2712       axisIte = new AncestorAxisIterator(sctx, qloc, input);
2713     break;
2714   }
2715   case axis_kind_ancestor_or_self:
2716   {
2717     if (v.use_reverse_order())
2718       axisIte = new AncestorSelfReverseAxisIterator(sctx, qloc, input);
2719     else
2720       axisIte = new AncestorSelfAxisIterator(sctx, qloc, input);
2721     break;
2722   }
2723   case axis_kind_following_sibling:
2724   {
2725     axisIte = new RSiblingAxisIterator(sctx, qloc, input);
2726     break;
2727   }
2728   case axis_kind_following:
2729   {
2730     axisIte = new FollowingAxisIterator(sctx, qloc, input);
2731     break;
2732   }
2733   case axis_kind_preceding_sibling:
2734   {
2735     if (v.use_reverse_order())
2736       axisIte = new LSiblingReverseAxisIterator(sctx, qloc, input);
2737     else
2738       axisIte = new LSiblingAxisIterator(sctx, qloc, input);
2739     break;
2740   }
2741   case axis_kind_preceding:
2742   {
2743     if (v.use_reverse_order())
2744       axisIte = new PrecedingReverseAxisIterator(sctx, qloc, input);
2745     else
2746       axisIte = new PrecedingAxisIterator(sctx, qloc, input);
2747     break;
2748   }
2749   case axis_kind_attribute:
2750   {
2751     if (v.getTest()->getTestKind() == match_name_test ||
2752         v.getTest()->getTestKind() == match_attr_test ||
2753         v.getTest()->getTestKind() == match_xs_attr_test ||
2754         v.getTest()->getTestKind() == match_anykind_test)
2755     {
2756       axisIte = new AttributeAxisIterator(sctx, qloc, input);
2757     }
2758     else
2759     {
2760       axisIte = new EmptyIterator(sctx, qloc);
2761       result = false;
2762     }
2763 
2764     break;
2765   }
2766   default:
2767     ZORBA_ASSERT (false && "Unknown axis kind");
2768   }
2769 
2770   push_itstack(axisIte);
2771 
2772   return result;
2773 }
2774 
2775 
end_visit(axis_step_expr & v)2776 void end_visit(axis_step_expr& v)
2777 {
2778   CODEGEN_TRACE_OUT("");
2779 }
2780 
2781 
2782 /*******************************************************************************
2783 
2784 ********************************************************************************/
begin_visit(match_expr & v)2785 bool begin_visit(match_expr& v)
2786 {
2787   CODEGEN_TRACE_IN ("");
2788 
2789   PlanIter_t axisIte = pop_itstack();
2790   AxisIteratorHelper* axisItep = dynamic_cast<AxisIteratorHelper*>(axisIte.getp());
2791   ZORBA_ASSERT(axisItep != NULL);
2792 
2793   store::Item_t qname;
2794 
2795   store::ItemFactory& iFactory = *(GENV.getStore().getItemFactory());
2796 
2797   if (v.getTestKind() == match_name_test)
2798   {
2799     match_wild_t wildKind = v.getWildKind();
2800 
2801     axisItep->setTestKind(match_name_test);
2802 
2803     if (dynamic_cast<AttributeAxisIterator*>(axisIte.getp()) != NULL)
2804       axisItep->setNodeKind(store::StoreConsts::attributeNode);
2805     else
2806       axisItep->setNodeKind(store::StoreConsts::elementNode);
2807 
2808     axisItep->setWildKind(wildKind);
2809 
2810     if (wildKind == match_no_wild)
2811     {
2812       axisItep->setQName(v.getQName());
2813     }
2814     else if (wildKind == match_prefix_wild)
2815     {
2816       iFactory.createQName(qname, "", "wildcard", v.getWildName().c_str());
2817 
2818       axisItep->setQName(qname);
2819     }
2820     else if (wildKind == match_name_wild)
2821     {
2822       axisItep->setQName(v.getQName());
2823     }
2824   }
2825   else
2826   {
2827     axisItep->setTestKind(v.getTestKind());
2828     axisItep->setDocTestKind(v.getDocTestKind());
2829     axisItep->setNodeKind(v.getNodeKind());
2830     axisItep->setQName(v.getQName());
2831     store::Item* typeName = v.getTypeName();
2832     if (typeName != NULL)
2833     {
2834       axisItep->setType(sctx->get_typemanager()->
2835                         create_named_type(typeName,
2836                                           TypeConstants::QUANT_ONE,
2837                                           qloc));
2838     }
2839     axisItep->setNilledAllowed(v.getNilledAllowed());
2840   }
2841 
2842   push_itstack(axisIte);
2843   return true;
2844 }
2845 
2846 
end_visit(match_expr & v)2847 void end_visit(match_expr& v)
2848 {
2849   CODEGEN_TRACE_OUT("");
2850 }
2851 
2852 #endif // PATH_ITER
2853 
2854 
2855 /*******************************************************************************
2856 
2857   Node Constructors
2858 
2859 ********************************************************************************/
2860 
begin_visit(doc_expr & v)2861 bool begin_visit(doc_expr& v)
2862 {
2863   CODEGEN_TRACE_IN("");
2864 
2865   theConstructorsStack.push(&v);
2866   theEnclosedContextStack.push(ELEMENT_CONTENT);
2867 
2868   if (v.copyInputNodes())
2869     theCopyNodesStack.push(true);
2870 
2871   return true;
2872 }
2873 
2874 
end_visit(doc_expr & v)2875 void end_visit(doc_expr& v)
2876 {
2877   CODEGEN_TRACE_OUT("");
2878 
2879   PlanIter_t lContent = pop_itstack();
2880   PlanIter_t lDocIter = new DocumentIterator(sctx,
2881                                              qloc,
2882                                              lContent,
2883                                              !theCopyNodesStack.empty());
2884   push_itstack(lDocIter);
2885 
2886   theEnclosedContextStack.pop();
2887   expr* e = plan_visitor_ns::pop_stack(theConstructorsStack);
2888   ZORBA_ASSERT(e == &v);
2889 
2890   if (v.copyInputNodes())
2891     theCopyNodesStack.pop();
2892 }
2893 
2894 
begin_visit(elem_expr & v)2895 bool begin_visit(elem_expr& v)
2896 {
2897   CODEGEN_TRACE_IN("");
2898 
2899   theConstructorsStack.push(&v);
2900   theEnclosedContextStack.push(ELEMENT_CONTENT);
2901 
2902   if (v.copyInputNodes())
2903     theCopyNodesStack.push(true);
2904 
2905   return true;
2906 }
2907 
2908 
end_visit(elem_expr & v)2909 void end_visit(elem_expr& v)
2910 {
2911   CODEGEN_TRACE_OUT("");
2912 
2913   PlanIter_t lQNameIter = 0;
2914   PlanIter_t lContentIter = 0;
2915   PlanIter_t lAttrsIter = 0;
2916 
2917   if ( v.getContent() != 0 )
2918     lContentIter = pop_itstack();
2919 
2920   if ( v.getAttrs() != 0 )
2921     lAttrsIter = pop_itstack();
2922 
2923   lQNameIter = pop_itstack();
2924 
2925   bool isRoot = false;
2926   theEnclosedContextStack.pop();
2927   expr* e = plan_visitor_ns::pop_stack(theConstructorsStack);
2928   ZORBA_ASSERT(e == &v);
2929 
2930   // Handling of the special case where the QName expression of a direct element
2931   // constructor has in itself a direct constructor. In that case the QName
2932   // expression should have isRoot set to true.
2933   elem_expr* top_elem_expr = NULL;
2934   if (!theConstructorsStack.empty())
2935     top_elem_expr = dynamic_cast<elem_expr*>(theConstructorsStack.top());
2936 
2937   if (theConstructorsStack.empty() ||
2938       is_enclosed_expr(theConstructorsStack.top()) ||
2939       (top_elem_expr != NULL && top_elem_expr->getQNameExpr()->contains_expr(e)))
2940   {
2941     isRoot = true;
2942   }
2943 
2944 	PlanIter_t iter = new ElementIterator(sctx,
2945                                         qloc,
2946                                         lQNameIter,
2947                                         lAttrsIter,
2948                                         lContentIter,
2949                                         v.getNSCtx(),
2950                                         isRoot,
2951                                         !theCopyNodesStack.empty());
2952   push_itstack(iter);
2953 
2954   if (v.copyInputNodes())
2955     theCopyNodesStack.pop();
2956 }
2957 
2958 
begin_visit(attr_expr & v)2959 bool begin_visit(attr_expr& v)
2960 {
2961   CODEGEN_TRACE_IN("");
2962 
2963   theConstructorsStack.push(&v);
2964   theEnclosedContextStack.push(ATTRIBUTE_CONTENT);
2965 
2966 	return true;
2967 }
2968 
2969 
end_visit(attr_expr & v)2970 void end_visit(attr_expr& v)
2971 {
2972   CODEGEN_TRACE_OUT("");
2973 
2974   PlanIter_t valueIter = 0;
2975 
2976   if (v.getValueExpr() != 0)
2977   {
2978     valueIter = pop_itstack();
2979   }
2980   else
2981   {
2982     valueIter = new EmptyIterator(sctx, qloc);
2983   }
2984 
2985   PlanIter_t qnameIter;
2986   store::Item_t qname;
2987   const const_expr* qnameExpr = dynamic_cast<const const_expr*>(v.getQNameExpr());
2988   if (qnameExpr != NULL)
2989   {
2990     qname = qnameExpr->get_val();
2991     (void)pop_itstack();
2992   }
2993   else
2994   {
2995     qnameIter = pop_itstack();
2996   }
2997 
2998   bool isRoot = false;
2999   theEnclosedContextStack.pop();
3000   expr* e = plan_visitor_ns::pop_stack(theConstructorsStack);
3001   ZORBA_ASSERT(e = &v);
3002 
3003   if (theConstructorsStack.empty() || is_enclosed_expr(theConstructorsStack.top()))
3004   {
3005     isRoot = true;
3006   }
3007 
3008   PlanIter_t attrIter = new AttributeIterator(sctx,
3009                                               qloc,
3010                                               qname,
3011                                               qnameIter,
3012                                               valueIter,
3013                                               isRoot);
3014 
3015   push_itstack(attrIter);
3016 }
3017 
3018 
begin_visit(text_expr & v)3019 bool begin_visit(text_expr& v)
3020 {
3021   CODEGEN_TRACE_IN ("");
3022 
3023   theConstructorsStack.push(&v);
3024 
3025   if (v.get_type() == text_expr::text_constructor)
3026     theEnclosedContextStack.push(TEXT_CONTENT);
3027   else
3028     theEnclosedContextStack.push(ATTRIBUTE_CONTENT);
3029 
3030 	return true;
3031 }
3032 
3033 
end_visit(text_expr & v)3034 void end_visit(text_expr& v)
3035 {
3036   CODEGEN_TRACE_OUT("");
3037 
3038   PlanIter_t content = pop_itstack();
3039 
3040   bool isRoot = false;
3041   theEnclosedContextStack.pop();
3042   expr* e = plan_visitor_ns::pop_stack(theConstructorsStack);
3043   ZORBA_ASSERT(e = &v);
3044 
3045   if (theConstructorsStack.empty() || is_enclosed_expr(theConstructorsStack.top()))
3046   {
3047     isRoot = true;
3048   }
3049 
3050   switch (v.get_type())
3051   {
3052   case text_expr::text_constructor:
3053     push_itstack(new TextIterator(sctx, qloc, content, isRoot));
3054     break;
3055 
3056   case text_expr::comment_constructor:
3057     push_itstack(new CommentIterator(sctx, qloc, content, isRoot));
3058     break;
3059 
3060   default:
3061     break;
3062   }
3063 }
3064 
3065 
begin_visit(pi_expr & v)3066 bool begin_visit(pi_expr& v)
3067 {
3068   CODEGEN_TRACE_IN("");
3069 
3070   theConstructorsStack.push(&v);
3071   theEnclosedContextStack.push(ATTRIBUTE_CONTENT);
3072 
3073   return true;
3074 }
3075 
3076 
end_visit(pi_expr & v)3077 void end_visit(pi_expr& v)
3078 {
3079   CODEGEN_TRACE_OUT("");
3080 
3081   bool isRoot = false;
3082   theEnclosedContextStack.pop();
3083   expr* e = plan_visitor_ns::pop_stack(theConstructorsStack);
3084   ZORBA_ASSERT(e = &v);
3085   if (theConstructorsStack.empty() || is_enclosed_expr(theConstructorsStack.top()))
3086   {
3087     isRoot = true;
3088   }
3089 
3090   PlanIter_t content = pop_itstack ();
3091   PlanIter_t target = pop_itstack ();
3092   push_itstack(new PiIterator(sctx, qloc, target, content, isRoot));
3093 }
3094 
3095 
3096 #ifdef ZORBA_WITH_JSON
3097 
3098 /*******************************************************************************
3099 
3100   JSON Constructors
3101 
3102 ********************************************************************************/
begin_visit(json_array_expr & v)3103 bool begin_visit(json_array_expr& v)
3104 {
3105   CODEGEN_TRACE_IN("");
3106   return true;
3107 }
3108 
3109 
end_visit(json_array_expr & v)3110 void end_visit(json_array_expr& v)
3111 {
3112   CODEGEN_TRACE_OUT("");
3113 
3114   std::vector<PlanIter_t> inputs;
3115 
3116   expr* inputExpr = v.get_expr();
3117 
3118   if (inputExpr != NULL)
3119   {
3120     PlanIter_t inputIter = pop_itstack();
3121 
3122     if (dynamic_cast<FnConcatIterator*>(inputIter.getp()) != NULL)
3123     {
3124       inputs = static_cast<FnConcatIterator*>(inputIter.getp())->getChildren();
3125     }
3126     else
3127     {
3128       inputs.push_back(inputIter);
3129     }
3130   }
3131 
3132   bool copyInput = true;
3133 
3134   push_itstack(new JSONArrayIterator(sctx, qloc, inputs, copyInput));
3135 }
3136 
3137 
begin_visit(json_object_expr & v)3138 bool begin_visit(json_object_expr& v)
3139 {
3140   CODEGEN_TRACE_IN("");
3141   return true;
3142 }
3143 
3144 
end_visit(json_object_expr & v)3145 void end_visit(json_object_expr& v)
3146 {
3147   CODEGEN_TRACE_OUT("");
3148 
3149   std::vector<PlanIter_t> inputs;
3150 
3151   expr* inputExpr = v.get_expr();
3152 
3153   if (inputExpr != NULL)
3154   {
3155     PlanIter_t inputIter = pop_itstack();
3156 
3157     if (dynamic_cast<FnConcatIterator*>(inputIter.getp()) != NULL)
3158     {
3159       inputs = static_cast<FnConcatIterator*>(inputIter.getp())->getChildren();
3160     }
3161     else
3162     {
3163       inputs.push_back(inputIter);
3164     }
3165   }
3166 
3167   bool copyInput = true;
3168 
3169   push_itstack(new JSONObjectIterator(sctx,
3170                                       qloc,
3171                                       inputs,
3172                                       copyInput,
3173                                       v.is_accumulating()));
3174 }
3175 
3176 
3177 
begin_visit(json_direct_object_expr & v)3178 bool begin_visit(json_direct_object_expr& v)
3179 {
3180   CODEGEN_TRACE_IN("");
3181   return true;
3182 }
3183 
3184 
end_visit(json_direct_object_expr & v)3185 void end_visit(json_direct_object_expr& v)
3186 {
3187   CODEGEN_TRACE_OUT("");
3188 
3189   csize numPairs = v.num_pairs();
3190 
3191   std::vector<PlanIter_t> names(numPairs);
3192   std::vector<PlanIter_t> values(numPairs);
3193 
3194   for (csize i = numPairs; i > 0; --i)
3195   {
3196     values[i-1] = pop_itstack();
3197   }
3198 
3199   for (csize i = numPairs; i > 0; --i)
3200   {
3201     names[i-1] = pop_itstack();
3202   }
3203 
3204   bool copyInput = true;
3205 
3206   push_itstack(new JSONDirectObjectIterator(sctx, qloc, names, values, copyInput));
3207 }
3208 
3209 
3210 
3211 #endif // ZORBA_WITH_JSON
3212 
3213 
begin_visit(const_expr & v)3214 bool begin_visit(const_expr& v)
3215 {
3216   CODEGEN_TRACE_IN("");
3217   return true;
3218 }
3219 
end_visit(const_expr & v)3220 void end_visit(const_expr& v)
3221 {
3222   CODEGEN_TRACE_OUT("");
3223   PlanIter_t it = new SingletonIterator(sctx, qloc, v.get_val());
3224   push_itstack (it);
3225 }
3226 
3227 
begin_visit(order_expr & v)3228 bool begin_visit(order_expr& v)
3229 {
3230   CODEGEN_TRACE_IN("");
3231   return true;
3232 }
3233 
end_visit(order_expr & v)3234 void end_visit(order_expr& v)
3235 {
3236   CODEGEN_TRACE_OUT("");
3237 }
3238 
3239 
3240 ////////////////////////////////////////////////////////////////////////////////
3241 //                                                                            //
3242 //  Updates (XQUF)                                                            //
3243 //                                                                            //
3244 ////////////////////////////////////////////////////////////////////////////////
3245 
3246 
begin_visit(insert_expr & v)3247 bool begin_visit(insert_expr& v)
3248 {
3249   CODEGEN_TRACE_IN("");
3250 
3251   RootTypeManager& rtm = GENV_TYPESYSTEM;
3252   TypeManager* tm = v.get_type_manager();
3253 
3254   store::UpdateConsts::InsertType kind  = v.getType();
3255 
3256   expr* targetExpr = v.getTargetExpr();
3257   expr* sourceExpr = v.getSourceExpr();
3258   xqtref_t targetType = targetExpr->get_return_type();
3259   xqtref_t sourceType = sourceExpr->get_return_type();
3260 
3261   if (TypeOps::is_equal(tm, *targetType, *rtm.EMPTY_TYPE, qloc))
3262     throw XQUERY_EXCEPTION( err::XUDY0027, ERROR_LOC( qloc ) );
3263 
3264   if (kind == store::UpdateConsts::INTO ||
3265       kind == store::UpdateConsts::AS_FIRST_INTO ||
3266       kind == store::UpdateConsts::AS_LAST_INTO)
3267   {
3268     if (TypeOps::is_subtype(tm, *targetType, *rtm.DOCUMENT_TYPE_STAR, qloc) &&
3269         TypeOps::is_subtype(tm, *sourceType, *rtm.ATTRIBUTE_TYPE_STAR, qloc))
3270     {
3271       throw XQUERY_EXCEPTION(err::XUTY0022, ERROR_LOC(qloc));
3272     }
3273 
3274     if (TypeOps::is_subtype(tm, *targetType, *rtm.ANY_SIMPLE_TYPE, qloc))
3275     {
3276       throw XQUERY_EXCEPTION( err::XUTY0005, ERROR_LOC( qloc ) );
3277     }
3278 
3279     if (TypeOps::is_subtype(tm, *targetType, *rtm.ATTRIBUTE_TYPE_STAR, qloc) ||
3280         TypeOps::is_subtype(tm, *targetType, *rtm.TEXT_TYPE_STAR, qloc) ||
3281         TypeOps::is_subtype(tm, *targetType, *rtm.COMMENT_TYPE_STAR, qloc) ||
3282         TypeOps::is_subtype(tm, *targetType, *rtm.PI_TYPE_STAR, qloc))
3283     {
3284       throw XQUERY_EXCEPTION( err::XUTY0005, ERROR_LOC( qloc ) );
3285     }
3286   }
3287   else
3288   {
3289   }
3290 
3291   theEnclosedContextStack.push(UPDATE_CONTEXT);
3292 
3293   return true;
3294 }
3295 
3296 
end_visit(insert_expr & v)3297 void end_visit(insert_expr& v)
3298 {
3299   CODEGEN_TRACE_OUT("");
3300 
3301   theEnclosedContextStack.pop();
3302 
3303   PlanIter_t lTarget = pop_itstack();
3304   PlanIter_t lSource = pop_itstack();
3305   PlanIter_t lInsert = new InsertIterator(sctx, qloc, v.getType(), lSource, lTarget);
3306   push_itstack(&*lInsert);
3307 }
3308 
3309 
begin_visit(delete_expr & v)3310 bool begin_visit(delete_expr& v)
3311 {
3312   CODEGEN_TRACE_IN("");
3313 
3314   theEnclosedContextStack.push(UPDATE_CONTEXT);
3315 
3316   return true;
3317 }
3318 
3319 
end_visit(delete_expr & v)3320 void end_visit(delete_expr& v)
3321 {
3322   CODEGEN_TRACE_OUT("");
3323 
3324   theEnclosedContextStack.pop();
3325 
3326   PlanIter_t lTarget = pop_itstack();
3327   PlanIter_t lDelete = new DeleteIterator(sctx, qloc, lTarget);
3328   push_itstack(&*lDelete);
3329 }
3330 
3331 
begin_visit(replace_expr & v)3332 bool begin_visit(replace_expr& v)
3333 {
3334   CODEGEN_TRACE_IN("");
3335 
3336   TypeManager* tm = v.get_type_manager();
3337 
3338   expr* targetExpr = v.getTargetExpr();
3339   xqtref_t targetType = targetExpr->get_return_type();
3340 
3341   if (TypeOps::is_equal(tm, *targetType, *GENV_TYPESYSTEM.EMPTY_TYPE, qloc))
3342     throw XQUERY_EXCEPTION( err::XUDY0027, ERROR_LOC( qloc ) );
3343 
3344   theEnclosedContextStack.push(UPDATE_CONTEXT);
3345 
3346   return true;
3347 }
3348 
3349 
end_visit(replace_expr & v)3350 void end_visit(replace_expr& v)
3351 {
3352   CODEGEN_TRACE_OUT("");
3353 
3354   theEnclosedContextStack.pop();
3355 
3356   PlanIter_t lReplacement = pop_itstack();
3357   PlanIter_t lTarget = pop_itstack();
3358   PlanIter_t lReplace = new ReplaceIterator(sctx,
3359                                             qloc,
3360                                             v.getType(),
3361                                             lTarget,
3362                                             lReplacement);
3363   push_itstack(&*lReplace);
3364 }
3365 
3366 
begin_visit(rename_expr & v)3367 bool begin_visit(rename_expr& v)
3368 {
3369   CODEGEN_TRACE_IN("");
3370 
3371   TypeManager* tm = v.get_type_manager();
3372 
3373   expr* targetExpr = v.getTargetExpr();
3374   xqtref_t targetType = targetExpr->get_return_type();
3375 
3376   if (TypeOps::is_equal(tm, *targetType, *GENV_TYPESYSTEM.EMPTY_TYPE, qloc))
3377     throw XQUERY_EXCEPTION( err::XUDY0027, ERROR_LOC( qloc ) );
3378 
3379   theEnclosedContextStack.push(UPDATE_CONTEXT);
3380 
3381   return true;
3382 }
3383 
3384 
end_visit(rename_expr & v)3385 void end_visit(rename_expr& v)
3386 {
3387   CODEGEN_TRACE_OUT("");
3388 
3389   theEnclosedContextStack.pop();
3390 
3391   PlanIter_t lName = pop_itstack();
3392   PlanIter_t lTarget = pop_itstack();
3393   PlanIter_t lRename;
3394 
3395   expr* nameExpr = v.getNameExpr();
3396 
3397   if (nameExpr->get_expr_kind() == name_cast_expr_kind)
3398   {
3399     name_cast_expr* nameCastExpr = static_cast<name_cast_expr*>(nameExpr);
3400 
3401     lRename = new RenameIterator(sctx,
3402                                  qloc,
3403                                  lTarget,
3404                                  lName,
3405                                  nameCastExpr->getNSCtx());
3406   }
3407   else
3408   {
3409     lRename = new RenameIterator(sctx, qloc, lTarget, lName, NULL);
3410   }
3411 
3412   push_itstack(&*lRename);
3413 }
3414 
3415 
begin_visit(transform_expr & v)3416 bool begin_visit(transform_expr& v)
3417 {
3418   CODEGEN_TRACE_IN("");
3419 
3420   TypeManager* tm = v.get_type_manager();
3421 
3422   std::vector<copy_clause*>::const_iterator lIter = v.begin();
3423   std::vector<copy_clause*>::const_iterator lEnd  = v.end();
3424   for (; lIter != lEnd; ++lIter)
3425   {
3426     var_expr* var = (*lIter)->getVar();
3427     expr* sourceExpr = (*lIter)->getExpr();
3428     xqtref_t sourceType = sourceExpr->get_return_type();
3429 
3430     if (TypeOps::is_subtype(tm, *sourceType, *GENV_TYPESYSTEM.ANY_SIMPLE_TYPE, qloc))
3431       throw XQUERY_EXCEPTION(err::XUTY0013, ERROR_LOC(qloc));
3432 
3433     uint64_t k = (uint64_t) &*var;
3434     copy_var_iter_map.put(k, new std::vector<ForVarIter_t>());
3435   }
3436   return true;
3437 }
3438 
end_visit(transform_expr & v)3439 void end_visit(transform_expr& v)
3440 {
3441   CODEGEN_TRACE_OUT("");
3442 
3443   PlanIter_t returnIter = pop_itstack();
3444   PlanIter_t modifyIter = pop_itstack();
3445 
3446   std::vector<CopyClause> lClauses;
3447   std::stack<PlanIter_t> lInputs;
3448   size_t lSize = v.size();
3449   for (size_t i = 0; i < lSize; ++i)
3450   {
3451     lInputs.push(pop_itstack());
3452   }
3453 
3454   // Create a FOR var iterator into which the PUL produced by the modify
3455   // iterator will be bound.
3456   store::Item_t pulVarName;
3457   GENV_ITEMFACTORY->createQName(pulVarName, "", "", "pulHolder");
3458   PlanIter_t pulHolderIter = new ForVarIterator(sctx, modifyIter->loc, pulVarName);
3459 
3460   // Create an ApplyIterator to apply the above PUL
3461   PlanIter_t applyIter = new ApplyIterator(sctx, modifyIter->loc, true, pulHolderIter);
3462 
3463   std::vector<copy_clause*>::const_iterator lIter = v.begin();
3464   std::vector<copy_clause*>::const_iterator lEnd  = v.end();
3465   for(; lIter != lEnd; ++lIter)
3466   {
3467     PlanIter_t lInput = plan_visitor_ns::pop_stack(lInputs);
3468     std::vector<ForVarIter_t>* lVarIters = 0;
3469     var_expr* lVar = (*lIter)->getVar();
3470     ZORBA_ASSERT(copy_var_iter_map.get((uint64_t)lVar, lVarIters));
3471     lClauses.push_back(CopyClause(*lVarIters, lInput));
3472   }
3473 
3474   TransformIterator* transformIter = new TransformIterator(sctx,
3475                                                            qloc,
3476                                                            lClauses,
3477                                                            modifyIter,
3478                                                            pulHolderIter,
3479                                                            applyIter,
3480                                                            returnIter);
3481   push_itstack(transformIter);
3482 }
3483 
3484 
3485 ////////////////////////////////////////////////////////////////////////////////
3486 //                                                                            //
3487 //  Full Text                                                                 //
3488 //                                                                            //
3489 ////////////////////////////////////////////////////////////////////////////////
3490 
3491 #ifndef ZORBA_NO_FULL_TEXT
begin_visit(ftcontains_expr & v)3492 bool begin_visit(ftcontains_expr& v)
3493 {
3494   CODEGEN_TRACE_IN("");
3495   return true;
3496 }
3497 
end_visit(ftcontains_expr & v)3498 void end_visit(ftcontains_expr& v)
3499 {
3500   CODEGEN_TRACE_OUT("");
3501   PlanIter_t ftignore_it = v.get_ignore() ? pop_itstack() : NULL;
3502   PlanIter_t ftrange_it = pop_itstack();
3503 
3504   PlanIter_t ftcontains_it = new FTContainsIterator(
3505     sctx, qloc, ftrange_it, ftignore_it, v.get_ftselection(),
3506     plan_ftnode_visitor_->get_sub_iters()
3507   );
3508 
3509   push_itstack( ftcontains_it );
3510 }
3511 #endif /* ZORBA_NO_FULL_TEXT */
3512 
3513 
result()3514 PlanIter_t result()
3515 {
3516   PlanIter_t res = pop_itstack();
3517 
3518 #ifndef NDEBUG
3519   if (!itstack.empty())
3520   {
3521     std::cout << "\nPlan_visitor stack still contains "
3522               << itstack.size() << " entries: " << std::endl;
3523     while (!itstack.empty())
3524     {
3525       PlanIter_t top = pop_itstack();
3526       XMLIterPrinter vp(std::cout);
3527       print_iter_plan(vp, top);
3528       std::cout << "=============================" << std::endl;
3529     }
3530     ZORBA_ASSERT(0);
3531   }
3532 #endif
3533 
3534   return res;
3535 }
3536 
3537 };
3538 
3539 ///////////////////////////////////////////////////////////////////////////////
3540 
3541 #ifndef ZORBA_NO_FULL_TEXT
3542 
3543 #define V plan_ftnode_visitor
3544 
3545 //
3546 // This member function is defined here to avoid an improper cast.
3547 //
get_expr_visitor()3548 expr_visitor* V::get_expr_visitor()
3549 {
3550   return plan_visitor_;
3551 }
3552 
3553 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftand )
3554 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftextension_selection )
3555 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftmild_not )
3556 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftor )
3557 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftprimary_with_options )
3558 
3559 DEF_FTNODE_VISITOR_BEGIN_VISIT( V, ftrange );
end_visit(ftrange & r)3560 void V::end_visit( ftrange &r ) {
3561   PlanIter_t it2 = plan_visitor_->pop_itstack();
3562   PlanIter_t it1;
3563   if ( *(r.get_expr2()) ) {
3564     it1 = plan_visitor_->pop_itstack();
3565   } else {
3566     it1 = it2;
3567     it2 = NULL;
3568   }
3569   sub_iters_.push_back( it1 );
3570   if ( it2 )
3571     sub_iters_.push_back( it2 );
3572   r.set_plan_iters( it1, it2 );
3573 }
3574 
3575 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftselection )
3576 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftunary_not )
3577 
3578 DEF_FTNODE_VISITOR_BEGIN_VISIT( V, ftweight );
end_visit(ftweight & w)3579 void V::end_visit( ftweight &w ) {
3580   PlanIter_t it = plan_visitor_->pop_itstack();
3581   w.set_weight_iter( it );
3582   sub_iters_.push_back( it );
3583 }
3584 
3585 DEF_FTNODE_VISITOR_BEGIN_VISIT( V, ftwords );
end_visit(ftwords & w)3586 void V::end_visit( ftwords &w ) {
3587   PlanIter_t it = plan_visitor_->pop_itstack();
3588   w.set_plan_iter( it );
3589   sub_iters_.push_back( it );
3590 }
3591 
3592 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftwords_times )
3593 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftcontent_filter )
3594 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftdistance_filter )
3595 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftorder_filter )
3596 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftscope_filter )
3597 
3598 DEF_FTNODE_VISITOR_BEGIN_VISIT( V, ftwindow_filter );
end_visit(ftwindow_filter & f)3599 void V::end_visit( ftwindow_filter &f ) {
3600   PlanIter_t it = plan_visitor_->pop_itstack();
3601   f.set_window_iter( it );
3602   sub_iters_.push_back( it );
3603 }
3604 
DEF_FTNODE_VISITOR_VISIT_MEM_FNS(V,ftcase_option)3605 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftcase_option )
3606 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftdiacritics_option )
3607 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftextension_option )
3608 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftlanguage_option )
3609 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftmatch_options )
3610 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftstem_option )
3611 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftstop_word_option )
3612 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftstop_words )
3613 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftthesaurus_id )
3614 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftthesaurus_option )
3615 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftwild_card_option )
3616 
3617 #undef V
3618 
3619 #endif /* ZORBA_NO_FULL_TEXT */
3620 
3621 /******************************************************************************
3622 
3623 ******************************************************************************/
3624 
3625 PlanIter_t codegen(
3626     const char* descr,
3627     expr* root,
3628     CompilerCB* ccb,
3629     ulong& nextDynamicVarId,
3630     hash64map<std::vector<LetVarIter_t> *>* arg_var_map)
3631 {
3632   plan_visitor c(ccb, nextDynamicVarId, arg_var_map);
3633   root->accept(c);
3634   PlanIter_t result = c.result();
3635 
3636   if (result != NULL &&
3637       descr != NULL &&
3638       Properties::instance()->printIteratorTree())
3639   {
3640     std::ostream& os = (Properties::instance()->iterPlanTest() ?
3641                         std::cout :
3642                         Properties::instance()->debug_out());
3643 
3644     os << "Iterator tree for " << descr << ":\n";
3645     XMLIterPrinter vp(os);
3646     print_iter_plan(vp, result);
3647     os << std::endl;
3648   }
3649 
3650   nextDynamicVarId = c.getNextDynamicVarId();
3651 
3652   return result;
3653 }
3654 
3655 
3656 std::vector<PlanIter_t> plan_visitor::no_var_iters;
3657 
3658 } // namespace zorba
3659 /* vim:set et sw=2 ts=2: */
3660