← Back to team overview

zorba-coders team mailing list archive

[Merge] lp:~zorba-coders/zorba/gen-flwor-opt into lp:zorba

 

Markos Zaharioudakis has proposed merging lp:~zorba-coders/zorba/gen-flwor-opt into lp:zorba.

Commit message:
Implemented hoisting optimization for general FLWOR.

Requested reviews:
  Markos Zaharioudakis (markos-za)

For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/gen-flwor-opt/+merge/163850

Implemented hoisting optimization for general FLWOR.
-- 
https://code.launchpad.net/~zorba-coders/zorba/gen-flwor-opt/+merge/163850
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'src/compiler/api/compiler_api_impl.cpp'
--- src/compiler/api/compiler_api_impl.cpp	2013-02-07 17:24:36 +0000
+++ src/compiler/api/compiler_api_impl.cpp	2013-05-15 07:29:31 +0000
@@ -17,7 +17,7 @@
 
 #include "compiler/api/compiler_api_impl.h"
 #include "compiler/api/compilercb.h"
-#include "compiler/rewriter/rewriters/default_optimizer.h"
+#include "compiler/rewriter/framework/default_optimizer.h"
 
 
 namespace zorba {

=== modified file 'src/compiler/expression/flwor_expr.cpp'
--- src/compiler/expression/flwor_expr.cpp	2013-05-04 20:20:05 +0000
+++ src/compiler/expression/flwor_expr.cpp	2013-05-15 07:29:31 +0000
@@ -944,28 +944,6 @@
 
 
 /*******************************************************************************
-  For simple flwor only.
-********************************************************************************/
-csize flwor_expr::num_forlet_clauses()
-{
-  csize num = 0;
-  csize numClauses = num_clauses();
-  for (csize i = 0; i < numClauses; ++i)
-  {
-    const flwor_clause* c = theClauses[i];
-
-    if (c->get_kind() == flwor_clause::for_clause ||
-        c->get_kind() == flwor_clause::let_clause)
-    {
-      ++num;
-    }
-  }
-
-  return num;
-}
-
-
-/*******************************************************************************
 
 ********************************************************************************/
 bool flwor_expr::defines_var(const var_expr* v) const

=== modified file 'src/compiler/expression/flwor_expr.h'
--- src/compiler/expression/flwor_expr.h	2013-05-09 18:50:15 +0000
+++ src/compiler/expression/flwor_expr.h	2013-05-15 07:29:31 +0000
@@ -726,7 +726,6 @@
   void set_where(expr* e);
   groupby_clause* get_group_clause() const;
   orderby_clause* get_order_clause() const;
-  csize num_forlet_clauses();
 
   void accept(expr_visitor&);
 

=== modified file 'src/compiler/rewriter/CMakeLists.txt'
--- src/compiler/rewriter/CMakeLists.txt	2013-02-07 17:24:36 +0000
+++ src/compiler/rewriter/CMakeLists.txt	2013-05-15 07:29:31 +0000
@@ -14,6 +14,5 @@
 SET(REWRITER_SRCS)
 
 ADD_SRC_SUBFOLDER(REWRITER_SRCS framework REWRITER_FRAMEWORK_SRCS)
-ADD_SRC_SUBFOLDER(REWRITER_SRCS rewriters REWRITER_REWRITERS_SRCS)
 ADD_SRC_SUBFOLDER(REWRITER_SRCS rules REWRITER_RULES_SRCS)
 ADD_SRC_SUBFOLDER(REWRITER_SRCS tools REWRITER_TOOLS_SRCS)

=== modified file 'src/compiler/rewriter/framework/CMakeLists.txt'
--- src/compiler/rewriter/framework/CMakeLists.txt	2013-02-07 17:24:36 +0000
+++ src/compiler/rewriter/framework/CMakeLists.txt	2013-05-15 07:29:31 +0000
@@ -14,4 +14,5 @@
 SET(REWRITER_FRAMEWORK_SRCS
     rule_driver.cpp
     rewriter_context.cpp
-    sequential_rewriter.cpp)
+    sequential_rewriter.cpp
+    default_optimizer.cpp)

=== modified file 'src/compiler/rewriter/framework/rule_driver.cpp'
--- src/compiler/rewriter/framework/rule_driver.cpp	2013-02-07 17:24:36 +0000
+++ src/compiler/rewriter/framework/rule_driver.cpp	2013-05-15 07:29:31 +0000
@@ -52,12 +52,12 @@
 {
   bool totalModified = false;
   bool modified = false;
-  rules_t::const_iterator end = m_rules.end();
+  rules_t::const_iterator end = theRules.end();
   do
   {
     modified = false;
 
-    for (rules_t::iterator i = m_rules.begin(); i != end; ++i)
+    for (rules_t::iterator i = theRules.begin(); i != end; ++i)
     {
       bool rule_modified = false;
       expr* newRoot = (*i)->apply(rCtx, &*rCtx.getRoot(), rule_modified);

=== modified file 'src/compiler/rewriter/framework/rule_driver.h'
--- src/compiler/rewriter/framework/rule_driver.h	2013-02-07 17:24:36 +0000
+++ src/compiler/rewriter/framework/rule_driver.h	2013-05-15 07:29:31 +0000
@@ -31,6 +31,12 @@
 typedef rchandle<RewriteRule> rule_ptr_t;
 
 
+/*******************************************************************************
+  A RuleMajorDriver whose rule set contains a single rule.
+********************************************************************************/
+#define ADD_RULE( rule ) theRules.push_back(rule_ptr_t(new rule))
+
+
 /***************************************************************************//**
   Represents a class of rules that are applied "together". This means that the
   rules that are registered with a RuleMajorDriver R are applied one after the
@@ -46,7 +52,7 @@
   typedef std::vector<rule_ptr_t> rules_t;
 
 protected:
-  rules_t m_rules;
+  rules_t theRules;
 
 public:
   RuleMajorDriver();
@@ -65,7 +71,7 @@
 public:
   SingletonRuleMajorDriverBase(rule_ptr_t rule)
   { 
-    m_rules.push_back(rule);
+    theRules.push_back(rule);
   }
 };
 

=== modified file 'src/compiler/rewriter/framework/sequential_rewriter.cpp'
--- src/compiler/rewriter/framework/sequential_rewriter.cpp	2013-02-07 17:24:36 +0000
+++ src/compiler/rewriter/framework/sequential_rewriter.cpp	2013-05-15 07:29:31 +0000
@@ -35,9 +35,9 @@
 {
   bool modified = false;
 
-  rewriters_t::const_iterator end = m_childRewriters.end();
+  rewriters_t::const_iterator end = theChildRewriters.end();
 
-  for(rewriters_t::const_iterator i = m_childRewriters.begin(); i != end; ++i)
+  for (rewriters_t::const_iterator i = theChildRewriters.begin(); i != end; ++i)
   {
     bool mod = (*i)->rewrite(rCtx);
 

=== modified file 'src/compiler/rewriter/framework/sequential_rewriter.h'
--- src/compiler/rewriter/framework/sequential_rewriter.h	2013-02-07 17:24:36 +0000
+++ src/compiler/rewriter/framework/sequential_rewriter.h	2013-05-15 07:29:31 +0000
@@ -33,10 +33,11 @@
 {
 protected:
   typedef rchandle<Rewriter> rewriter_ptr_t;
+
   typedef std::vector<rewriter_ptr_t> rewriters_t;
 
 protected:
-  rewriters_t m_childRewriters;
+  rewriters_t theChildRewriters;
 
 public:
   virtual bool rewrite(RewriterContext& rCtx);
@@ -47,6 +48,18 @@
   ~SequentialRewriter();
 };
 
+
+
+#define ADD_DRIVER(d) \
+theChildRewriters.push_back(new d)
+
+#define ADD_SINGLETON_DRIVER(rule) \
+theChildRewriters.push_back(new SingletonRuleMajorDriver<rule>)
+
+#define ADD_ONCE_DRIVER(rule) \
+theChildRewriters.push_back(new RuleOnceDriver<rule>)
+
+
 }
 
 #endif /* ZORBA_SEQUENTIAL_REWRITER_H */

=== removed directory 'src/compiler/rewriter/rewriters'
=== removed file 'src/compiler/rewriter/rewriters/CMakeLists.txt'
--- src/compiler/rewriter/rewriters/CMakeLists.txt	2013-02-07 17:24:36 +0000
+++ src/compiler/rewriter/rewriters/CMakeLists.txt	1970-01-01 00:00:00 +0000
@@ -1,16 +0,0 @@
-# Copyright 2006-2008 The FLWOR Foundation.
-# 
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-# 
-# http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-SET(REWRITER_REWRITERS_SRCS
-    default_optimizer.cpp)
-

=== removed file 'src/compiler/rewriter/rewriters/common_rewriter.h'
--- src/compiler/rewriter/rewriters/common_rewriter.h	2013-02-07 17:24:36 +0000
+++ src/compiler/rewriter/rewriters/common_rewriter.h	1970-01-01 00:00:00 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright 2006-2008 The FLWOR Foundation.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-#ifndef ZORBA_COMMON_REWRITER
-#define ZORBA_COMMON_REWRITER
-
-#define ADD_DRIVER( d ) \
-m_childRewriters.push_back(rewriter_ptr_t (new d))
-
-#define ADD_SINGLETON_DRIVER(rule) \
-m_childRewriters.push_back(rewriter_ptr_t(new SingletonRuleMajorDriver<rule>))
-
-#define ADD_ONCE_DRIVER(rule) \
-m_childRewriters.push_back(rewriter_ptr_t(new RuleOnceDriver<rule>))
-
-#define ADD_RULE( rule ) \
-m_rules.push_back (rule_ptr_t (new rule))
-
-#endif /* ZORBA_COMMON_REWRITER */
-/* vim:set et sw=2 ts=2: */

=== removed file 'src/compiler/rewriter/rewriters/default_optimizer.cpp'
--- src/compiler/rewriter/rewriters/default_optimizer.cpp	2013-02-26 03:15:17 +0000
+++ src/compiler/rewriter/rewriters/default_optimizer.cpp	1970-01-01 00:00:00 +0000
@@ -1,275 +0,0 @@
-/*
- * Copyright 2006-2008 The FLWOR Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "stdafx.h"
-
-#include "compiler/rewriter/framework/rule_driver.h"
-#include "compiler/rewriter/rules/ruleset.h"
-#include "compiler/rewriter/rules/fold_rules.h"
-#include "compiler/rewriter/rules/index_matching_rule.h"
-#include "compiler/rewriter/rules/index_join_rule.h"
-#include "compiler/rewriter/rewriters/common_rewriter.h"
-#include "compiler/rewriter/rewriters/default_optimizer.h"
-#include "compiler/rewriter/tools/expr_tools.h"
-
-#include "compiler/xqddf/value_index.h"
-
-#include "compiler/api/compilercb.h"
-
-#include "functions/udf.h"
-
-#include "system/properties.h"
-
-#include "context/static_context.h"
-
-
-
-namespace zorba
-{
-
-
-DefaultOptimizer::DefaultOptimizer()
-{
-}
-
-
-DefaultOptimizer::~DefaultOptimizer()
-{
-}
-
-
-bool DefaultOptimizer::rewrite(RewriterContext& rCtx)
-{
-  bool modified = false;
-
-  SingletonRuleMajorDriver<EliminateTypeEnforcingOperations> driverTypeRules;
-  SingletonRuleMajorDriver<EliminateExtraneousPathSteps> driverPathSimplify;
-  RuleOnceDriver<EliminateUnusedLetVars> driverEliminateVars;
-  RuleOnceDriver<MarkProducerNodeProps> driverMarkProducerNodeProps;
-  RuleOnceDriver<MarkConsumerNodeProps> driverMarkConsumerNodeProps;
-  RuleOnceDriver<EliminateNodeOps> driverEliminateNodeOps;
-  SingletonRuleMajorDriver<SpecializeOperations> driverSpecializeOperations;
-
-  SingletonRuleMajorDriver<MarkFreeVars> driverMarkFreeVars;
-  FoldRules driverFoldRules;
-
-  // InlineFunctions
-
-  if (Properties::instance()->inlineUdf())
-  {
-    SingletonRuleMajorDriver<InlineFunctions> driverInlineFunctions;
-    if (driverInlineFunctions.rewrite(rCtx))
-      modified = true;
-  }
-
-  // PathSimplification
-  if (driverPathSimplify.rewrite(rCtx))
-    modified = true;
-
-  if (rCtx.theUDF != NULL)
-  {
-    RuleOnceDriver<MarkExprs> driverMarkLocalExprs;
-    driverMarkLocalExprs.getRule()->setLocal(true);
-    driverMarkLocalExprs.rewrite(rCtx);
-  }
-
- repeat1:
-
-  // TypeRules
-  if (driverTypeRules.rewrite(rCtx))
-    modified = true;
-
-  // FoldRules
-  driverFoldRules.rewrite(rCtx);
-
-  //
-  bool local_modified = false;
-  rCtx.theRoot->compute_return_type(true, &local_modified);
-  if (local_modified)
-  {
-    //std::cout << "TYPES MODIFIED 1 !!!" << std::endl << std::endl;
-    goto repeat1;
-  }
-
-  /*
- repeat2:
-
-  //
-  driverMarkFreeVars.rewrite(rCtx);
-  //
-  driverEliminateVars.rewrite(rCtx);
-
-  //  Recompute static types
-  local_modified = false;
-  rCtx.theRoot->compute_return_type(true, &local_modified);
-  if (local_modified)
-  {
-    //std::cout << "TYPES MODIFIED 2 !!!" << std::endl << std::endl;
-    goto repeat2;
-  }
-  */
-
-  //
-  driverMarkProducerNodeProps.rewrite(rCtx);
-  driverEliminateNodeOps.rewrite(rCtx);
-
-  //
-  driverMarkConsumerNodeProps.rewrite(rCtx);
-  driverEliminateNodeOps.rewrite(rCtx);
-
- repeat4:
-
-  // SpecializeOps
-  driverSpecializeOperations.rewrite(rCtx);
-
-  // FoldRules
-  driverFoldRules.rewrite(rCtx);
-
-  // TypeRules
-  driverTypeRules.rewrite(rCtx);
-
-  // Recompute static types
-  local_modified = false;
-  rCtx.theRoot->compute_return_type(true, &local_modified);
-  if (local_modified)
-  {
-    //std::cout << "TYPES MODIFIED 4 !!!" << std::endl << std::endl;
-    goto repeat4;
-  }
-
-  // Loop Hoisting
-  if (Properties::instance()->loopHoisting())
-  {
-    HoistRule rule;
-    bool local_modified = false;
-
-    expr* e = rule.apply(rCtx, rCtx.getRoot(), local_modified);
-
-    if (e != rCtx.getRoot())
-      rCtx.setRoot(e);
-
-    // Mark exprs again time because hoisting may have created new exprs.
-    if (local_modified)
-    {
-      modified = true;
-
-      if (Properties::instance()->printIntermediateOpt())
-      {
-        std::cout << "After hoisting : " << std::endl;
-        rCtx.getRoot()->put(std::cout) << std::endl;
-      }
-
-      RuleOnceDriver<MarkExprs> driverMarkExpr;
-      driverMarkExpr.rewrite(rCtx);
-    }
-  }
-
-  // index matching
-  if (Properties::instance()->useIndexes())
-  {
-    static_context* sctx = rCtx.theRoot->get_sctx();
-
-    std::vector<IndexDecl*> indexDecls;
-    sctx->get_index_decls(indexDecls);
-
-    if (!indexDecls.empty())
-    {
-      MarkFreeVars freeVarsRule;
-      bool modified;
-      freeVarsRule.apply(rCtx, rCtx.theRoot, modified);
-    }
-
-    std::vector<IndexDecl*>::const_iterator ite = indexDecls.begin();
-    std::vector<IndexDecl*>::const_iterator end = indexDecls.end();
-    for (; ite != end; ++ite)
-    {
-      bool local_modified = false;
-
-      //store::Index* idx = GENV_STORE.getIndex((*ite)->getName());
-
-      //if (idx != NULL)
-      if (!(*ite)->isTemp())
-      {
-        IndexMatchingRule rule(*ite);
-
-        expr* e = rule.apply(rCtx, rCtx.getRoot(), local_modified);
-
-        if (e != rCtx.getRoot())
-          rCtx.setRoot(e);
-      }
-
-      if (local_modified)
-      {
-        if (Properties::instance()->printIntermediateOpt())
-        {
-          std::cout << "After index matching : " << std::endl;
-          rCtx.getRoot()->put(std::cout) << std::endl;
-        }
-
-        modified = true;
-      }
-    }
-  }
-
-  // Index Joins
-  if (Properties::instance()->inferJoins())
-  {
-    bool local_modified = false;
-
-    IndexJoinRule rule(&rCtx);
-
-    do
-    {
-      local_modified = false;
-
-      expr* e = rule.apply(rCtx, rCtx.getRoot(), local_modified);
-
-      if (e != rCtx.getRoot())
-        rCtx.setRoot(e);
-
-      if (local_modified)
-      {
-        modified = true;
-
-        if (Properties::instance()->printIntermediateOpt())
-        {
-          std::cout << "After index join : " << std::endl;
-          rCtx.getRoot()->put(std::cout) << std::endl;
-        }
-
-        // Mark exprs again because index joins may have created new exprs.
-        RuleOnceDriver<MarkExprs> driverMarkExpr;
-        driverMarkExpr.rewrite(rCtx);
-      }
-    }
-    while (local_modified);
-  }
-
-  // Mark node copy property
-  if (Properties::instance()->noCopyOptim())
-  {
-    if (rCtx.theUDF == NULL)
-    {
-      RuleOnceDriver<MarkNodeCopyProps> driverMarkNodeCopyProps;
-      driverMarkNodeCopyProps.rewrite(rCtx);
-    }
-  }
-
-  return modified;
-}
-
-
-}
-/* vim:set et sw=2 ts=2: */

=== removed file 'src/compiler/rewriter/rewriters/default_optimizer.h'
--- src/compiler/rewriter/rewriters/default_optimizer.h	2013-02-07 17:24:36 +0000
+++ src/compiler/rewriter/rewriters/default_optimizer.h	1970-01-01 00:00:00 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright 2006-2008 The FLWOR Foundation.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-#ifndef ZORBA_DEFAULT_OPTIMIZER_H
-#define ZORBA_DEFAULT_OPTIMIZER_H
-
-#include "common/shared_types.h"
-#include "compiler/rewriter/framework/sequential_rewriter.h"
-#include "compiler/api/compilercb.h"
-
-namespace zorba 
-{
-
-class DefaultOptimizer : public SequentialRewriter 
-{
-public:
-  DefaultOptimizer();
-
-  ~DefaultOptimizer();
-
-  bool rewrite(RewriterContext& rCtx);
-};
-
-
-}
-
-#endif /* ZORBA_DEFAULT_OPTIMIZER_H */
-
-/*
- * Local variables:
- * mode: c++
- * End:
- */
-/* vim:set et sw=2 ts=2: */

=== removed file 'src/compiler/rewriter/rewriters/phase1_rewriter.cpp'
--- src/compiler/rewriter/rewriters/phase1_rewriter.cpp	2013-02-07 17:24:36 +0000
+++ src/compiler/rewriter/rewriters/phase1_rewriter.cpp	1970-01-01 00:00:00 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright 2006-2008 The FLWOR Foundation.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "compiler/rewriter/framework/rule_driver.h"
-#include "compiler/rewriter/rules/ruleset.h"
-#include "compiler/rewriter/rewriters/common_rewriter.h"
-#include "compiler/rewriter/rewriters/phase1_rewriter.h"
-
-namespace zorba {
-
-Phase1Rewriter::Phase1Rewriter()
-{
-  ADD_SINGLETON_DRIVER(ExpandBuildIndex);
-}
-
-Phase1Rewriter::~Phase1Rewriter()
-{
-}
-
-}
-/* vim:set et sw=2 ts=2: */

=== removed file 'src/compiler/rewriter/rewriters/phase1_rewriter.h'
--- src/compiler/rewriter/rewriters/phase1_rewriter.h	2013-02-07 17:24:36 +0000
+++ src/compiler/rewriter/rewriters/phase1_rewriter.h	1970-01-01 00:00:00 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright 2006-2008 The FLWOR Foundation.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-#ifndef ZORBA_PHASE1_REWRITER_H
-#define ZORBA_PHASE1_REWRITER_H
-
-#include "common/shared_types.h"
-#include "compiler/rewriter/framework/sequential_rewriter.h"
-
-namespace zorba {
-
-class Phase1Rewriter : public SequentialRewriter 
-{
-public:
-  Phase1Rewriter();
-  ~Phase1Rewriter();
-};
-
-}
-
-#endif /* ZORBA_PHASE1_REWRITER_H */
-
-
-/*
- * Local variables:
- * mode: c++
- * End:
- */
-/* vim:set et sw=2 ts=2: */

=== modified file 'src/compiler/rewriter/rules/fold_rules.h'
--- src/compiler/rewriter/rules/fold_rules.h	2012-12-14 18:01:41 +0000
+++ src/compiler/rewriter/rules/fold_rules.h	2013-05-15 07:29:31 +0000
@@ -20,7 +20,6 @@
 #include "stdafx.h"
 
 #include "compiler/rewriter/framework/rule_driver.h"
-#include "compiler/rewriter/rewriters/common_rewriter.h"
 #include "compiler/rewriter/rules/ruleset.h"
 
 

=== modified file 'src/compiler/rewriter/rules/hoist_rules.cpp'
--- src/compiler/rewriter/rules/hoist_rules.cpp	2013-03-04 21:00:58 +0000
+++ src/compiler/rewriter/rules/hoist_rules.cpp	2013-05-15 07:29:31 +0000
@@ -22,8 +22,7 @@
 #include "functions/library.h"
 #include "functions/udf.h"
 
-#include "compiler/rewriter/rules/ruleset.h"
-#include "compiler/rewriter/tools/expr_tools.h"
+#include "compiler/rewriter/rules/hoist_rules.h"
 #include "compiler/expression/flwor_expr.h"
 #include "compiler/expression/expr.h"
 #include "compiler/expression/expr_iter.h"
@@ -38,29 +37,11 @@
 namespace zorba
 {
 
-static bool hoist_expressions(
-    RewriterContext&,
-    expr*,
-    const expr_tools::VarIdMap&,
-    const expr_tools::ExprVarsMap&,
-    struct PathHolder*);
-
-static expr* try_hoisting(
-    RewriterContext&,
-    expr*,
-    const expr_tools::VarIdMap&,
-    const expr_tools::ExprVarsMap&,
-    struct PathHolder*);
-
-static bool non_hoistable (const expr*);
+
+static bool non_hoistable(const expr*);
 
 static bool is_already_hoisted(const expr*);
 
-static bool contains_var(
-    var_expr*,
-    const expr_tools::VarIdMap&,
-    const DynamicBitset&);
-
 static bool is_enclosed_expr(const expr*);
 
 static bool containsUpdates(const expr*);
@@ -77,11 +58,7 @@
   expr               * theExpr;
   long                 clauseCount;
 
-  PathHolder()
-    :
-    prev(NULL),
-    theExpr(NULL),
-    clauseCount(0)
+  PathHolder() : prev(NULL), theExpr(NULL), clauseCount(0)
   {
   }
 };
@@ -99,9 +76,10 @@
   assert(node == rCtx.getRoot());
 
   csize numVars = 0;
-  expr_tools::VarIdMap varmap;
+  theVarIdMap.clear();
+  theExprVarsMap.clear();
 
-  expr_tools::index_flwor_vars(node, numVars, varmap, NULL);
+  expr_tools::index_flwor_vars(node, numVars, theVarIdMap, NULL);
 
   /*
   expr_tools::VarIdMap::const_iterator ite = varmap.begin();
@@ -112,12 +90,11 @@
   }
   */
 
-  expr_tools::ExprVarsMap freevarMap;
   DynamicBitset freeset(numVars+1);
-  expr_tools::build_expr_to_vars_map(node, varmap, freeset, freevarMap);
+  expr_tools::build_expr_to_vars_map(node, theVarIdMap, freeset, theExprVarsMap);
 
   PathHolder root;
-  modified = hoist_expressions(rCtx, node, varmap, freevarMap, &root);
+  modified = hoistChildren(rCtx, node, &root);
 
   if (modified && root.theExpr != NULL)
   {
@@ -134,16 +111,12 @@
 /*******************************************************************************
   Try to hoist the children of the given expr "e".
 ********************************************************************************/
-static bool hoist_expressions(
-    RewriterContext& rCtx,
-    expr* e,
-    const expr_tools::VarIdMap& varmap,
-    const expr_tools::ExprVarsMap& freevarMap,
-    struct PathHolder* path)
+bool HoistRule::hoistChildren(RewriterContext& rCtx, expr* e, PathHolder* path)
 {
   bool status = false;
 
-  if (e->get_expr_kind() == flwor_expr_kind)
+  if (e->get_expr_kind() == flwor_expr_kind ||
+      e->get_expr_kind() == gflwor_expr_kind)
   {
     flwor_expr* flwor = static_cast<flwor_expr *>(e);
 
@@ -151,85 +124,240 @@
     step.prev = path;
     step.theExpr = e;
 
-    csize numForLetClauses = flwor->num_forlet_clauses();
+    csize numClauses = flwor->num_clauses();
     csize i = 0;
 
-    while (i < numForLetClauses)
+    while (i < numClauses)
     {
-      forletwin_clause* flc = static_cast<forletwin_clause*>(flwor->get_clause(i));
-      expr* domainExpr = flc->get_expr();
-
-      expr* unhoistExpr =
-      try_hoisting(rCtx, domainExpr, varmap, freevarMap, &step);
-
-      if (unhoistExpr != NULL)
-      {
-        flc->set_expr(unhoistExpr);
-        status = true;
-        numForLetClauses = flwor->num_forlet_clauses();
-        // TODO: the expr that was just hoisted here, may contain sub-exprs that
-        // can be hoisted even earlier.
-      }
-      else if (domainExpr->is_sequential())
-      {
-        PathHolder root;
-
-        bool hoisted =
-        hoist_expressions(rCtx, domainExpr, varmap, freevarMap, &root);
-
-        if (hoisted)
-        {
-          if (root.theExpr != NULL)
-          {
-            assert(root.theExpr->get_expr_kind() == flwor_expr_kind);
-
-            static_cast<flwor_expr*>(root.theExpr)->set_return_expr(domainExpr);
-            flc->set_expr(root.theExpr);
-          }
-
-          status = true;
-          assert(numForLetClauses == flwor->num_forlet_clauses());
-        }
-      }
-      else
-      {
-        bool hoisted =
-        hoist_expressions(rCtx, domainExpr, varmap, freevarMap, &step);
-
-        if (hoisted)
-        {
-          status = true;
-          numForLetClauses = flwor->num_forlet_clauses();
-        }
+      flwor_clause* c = flwor->get_clause(i);
+
+      switch (c->get_kind())
+      {
+      case flwor_clause::for_clause:
+      case flwor_clause::let_clause:
+      case flwor_clause::window_clause:
+      {
+        forletwin_clause* flwc = static_cast<forletwin_clause*>(c);
+        expr* domainExpr = flwc->get_expr();
+
+        expr* unhoistExpr = hoistExpr(rCtx, domainExpr, &step);
+
+        if (unhoistExpr != NULL)
+        {
+          flwc->set_expr(unhoistExpr);
+          status = true;
+          numClauses = flwor->num_clauses();
+          // TODO: the expr that was just hoisted here, may contain sub-exprs that
+          // can be hoisted even earlier.
+        }
+        else if (domainExpr->is_sequential())
+        {
+          PathHolder root;
+
+          bool hoisted = hoistChildren(rCtx, domainExpr, &root);
+
+          if (hoisted)
+          {
+            if (root.theExpr != NULL)
+            {
+              assert(root.theExpr->get_expr_kind() == flwor_expr_kind);
+              
+              static_cast<flwor_expr*>(root.theExpr)->set_return_expr(domainExpr);
+              flwc->set_expr(root.theExpr);
+            }
+            
+            status = true;
+            assert(numClauses == flwor->num_clauses());
+          }
+        }
+        else if (hoistChildren(rCtx, domainExpr, &step))
+        {
+          status = true;
+          numClauses = flwor->num_clauses();
+        }
+
+        if (c->get_kind() == flwor_clause::window_clause)
+        {
+          window_clause* wc = static_cast<window_clause*>(c);
+          flwor_wincond* startCond = wc->get_win_start();
+          flwor_wincond* stopCond = wc->get_win_stop();
+
+          if (startCond)
+          {
+            expr* condExpr = startCond->get_expr();
+
+            ZORBA_ASSERT(!condExpr->is_sequential());
+
+            ++step.clauseCount;
+
+            expr* unhoistExpr = hoistExpr(rCtx, condExpr, &step);
+
+            if (unhoistExpr != NULL)
+            {
+              startCond->set_expr(unhoistExpr);
+              status = true;
+              numClauses = flwor->num_clauses();
+            }
+            else if (hoistChildren(rCtx, condExpr, &step))
+            {
+              status = true;
+              numClauses = flwor->num_clauses();
+            }
+
+            --step.clauseCount;
+          }
+
+          if (stopCond)
+          {
+            expr* condExpr = stopCond->get_expr();
+
+            ZORBA_ASSERT(!condExpr->is_sequential());
+
+            ++step.clauseCount;
+
+            expr* unhoistExpr = hoistExpr(rCtx, condExpr, &step);
+
+            if (unhoistExpr != NULL)
+            {
+              stopCond->set_expr(unhoistExpr);
+              status = true;
+              numClauses = flwor->num_clauses();
+            }
+            else if (hoistChildren(rCtx, condExpr, &step))
+            {
+              status = true;
+              numClauses = flwor->num_clauses();
+            }
+
+            --step.clauseCount;
+          }
+        }
+
+        break;
+      }
+      case flwor_clause::where_clause:
+      {
+        where_clause* wc = static_cast<where_clause*>(c);
+        expr* we = wc->get_expr();
+
+        ZORBA_ASSERT(!we->is_sequential());
+
+        expr* unhoistExpr = hoistExpr(rCtx, we, &step);
+
+        if (unhoistExpr != NULL)
+        {
+          wc->set_expr(unhoistExpr);
+          status = true;
+          numClauses = flwor->num_clauses();
+        }
+        else if (hoistChildren(rCtx, we, &step))
+        {
+          status = true;
+          numClauses = flwor->num_clauses();
+        }
+
+        break;
+      }
+      case flwor_clause::orderby_clause:
+      {
+        orderby_clause* oc = static_cast<orderby_clause*>(c);
+
+        std::vector<expr*>::const_iterator ite = oc->begin();
+        std::vector<expr*>::const_iterator end = oc->end();
+        for (; ite != end; ++ite)
+        {
+          expr* oe = *ite;
+          
+          ZORBA_ASSERT(!oe->is_sequential());
+
+          expr* unhoistExpr = hoistExpr(rCtx, oe, &step);
+
+          if (unhoistExpr != NULL)
+          {
+            oc->set_column_expr(ite - oc->begin(), unhoistExpr);
+            status = true;
+            numClauses = flwor->num_clauses();
+          }
+          else if (hoistChildren(rCtx, oe, &step))
+          {
+            status = true;
+            numClauses = flwor->num_clauses();
+          }
+        }
+
+        break;
+      }
+      case flwor_clause::groupby_clause:
+      {
+        groupby_clause* gc = static_cast<groupby_clause*>(c);
+
+        var_rebind_list_t::iterator ite = gc->beginGroupVars();
+        var_rebind_list_t::iterator end = gc->endGroupVars();
+        for (; ite != end; ++ite)
+        {
+          expr* ge = (*ite).first;
+          
+          ZORBA_ASSERT(!ge->is_sequential());
+
+          expr* unhoistExpr = hoistExpr(rCtx, ge, &step);
+
+          if (unhoistExpr != NULL)
+          {
+            (*ite).first = unhoistExpr;
+            status = true;
+            numClauses = flwor->num_clauses();
+          }
+          else if (hoistChildren(rCtx, ge, &step))
+          {
+            status = true;
+            numClauses = flwor->num_clauses();
+          }
+        }
+
+        ite = gc->beginNonGroupVars();
+        end = gc->endNonGroupVars();
+        for (; ite != end; ++ite)
+        {
+          expr* ge = (*ite).first;
+          
+          ZORBA_ASSERT(!ge->is_sequential());
+
+          expr* unhoistExpr = hoistExpr(rCtx, ge, &step);
+
+          if (unhoistExpr != NULL)
+          {
+            (*ite).first = unhoistExpr;
+            status = true;
+            numClauses = flwor->num_clauses();
+          }
+          else if (hoistChildren(rCtx, ge, &step))
+          {
+            status = true;
+            numClauses = flwor->num_clauses();
+          }
+        }
+
+        break;
+      }
+      case flwor_clause::count_clause:
+      {
+        break;
+      }
+      case flwor_clause::materialize_clause:
+      {
+        break;
+      }
+      default:
+        ZORBA_ASSERT(false);
       }
 
       i = ++(step.clauseCount);
 
-      assert(numForLetClauses == flwor->num_forlet_clauses());
-    }
-
-    expr* we = flwor->get_where();
-    if (we != NULL)
-    {
-      ZORBA_ASSERT(!we->is_sequential());
-
-      expr* unhoistExpr = try_hoisting(rCtx, we, varmap, freevarMap, &step);
-
-      if (unhoistExpr != NULL)
-      {
-        flwor->set_where(unhoistExpr);
-        status = true;
-      }
-      else
-      {
-        status = hoist_expressions(rCtx, we, varmap, freevarMap, &step) || status;
-      }
-    }
-
-    // TODO: hoist orderby exprs
+      assert(numClauses == flwor->num_clauses());
+    }
 
     expr* re = flwor->get_return_expr();
-    expr* unhoistExpr = try_hoisting(rCtx, re, varmap, freevarMap, &step);
+    expr* unhoistExpr = hoistExpr(rCtx, re, &step);
 
     if (unhoistExpr != NULL)
     {
@@ -239,7 +367,7 @@
     else if (re->is_sequential())
     {
       PathHolder root;
-      bool nestedModified = hoist_expressions(rCtx, re, varmap, freevarMap, &root);
+      bool nestedModified = hoistChildren(rCtx, re, &root);
 
       if (nestedModified && root.theExpr != NULL)
       {
@@ -253,36 +381,7 @@
     }
     else
     {
-      status = hoist_expressions(rCtx, re, varmap, freevarMap, &step) || status;
-    }
-  }
-
-  else if (e->get_expr_kind() == trycatch_expr_kind)
-  {
-    PathHolder step;
-    step.prev = path;
-    step.theExpr = e;
-
-    ExprIterator iter(e);
-
-    while(!iter.done())
-    {
-      expr* ce = **iter;
-      if (ce)
-      {
-        expr* unhoistExpr = try_hoisting(rCtx, ce, varmap, freevarMap, &step);
-        if (unhoistExpr != NULL)
-        {
-          **iter = unhoistExpr;
-          status = true;
-        }
-        else
-        {
-          status = hoist_expressions(rCtx, ce, varmap, freevarMap, &step) || status;
-        }
-      }
-
-      iter.next();
+      status = hoistChildren(rCtx, re, &step) || status;
     }
   }
 
@@ -298,7 +397,7 @@
       expr* ce = **iter;
 
       PathHolder root;
-      bool nestedModified = hoist_expressions(rCtx, ce, varmap, freevarMap, &root);
+      bool nestedModified = hoistChildren(rCtx, ce, &root);
 
       if (nestedModified && root.theExpr != NULL)
       {
@@ -314,23 +413,30 @@
     }
   }
 
-  else if (e->is_updating() ||
-           e->get_expr_kind() == gflwor_expr_kind ||
-           e->get_expr_kind() == transform_expr_kind)
+  else if (e->is_updating() || e->get_expr_kind() == transform_expr_kind)
   {
     // do nothing
   }
 
   else
   {
+
+    if (e->get_expr_kind() == trycatch_expr_kind)
+    {
+      PathHolder step;
+      step.prev = path;
+      step.theExpr = e;
+      path = &step;
+    }
+
     ExprIterator iter(e);
 
-    while(!iter.done())
+    while (!iter.done())
     {
       expr* ce = **iter;
       if (ce)
       {
-        expr* unhoistExpr = try_hoisting(rCtx, ce, varmap, freevarMap, path);
+        expr* unhoistExpr = hoistExpr(rCtx, ce, path);
         if (unhoistExpr != NULL)
         {
           **iter = unhoistExpr;
@@ -338,7 +444,7 @@
         }
         else
         {
-          status = hoist_expressions(rCtx, ce, varmap, freevarMap, path) || status;
+          status = hoistChildren(rCtx, ce, path) || status;
         }
       }
 
@@ -355,11 +461,9 @@
   flwor expr inside the stack of flwor exprs that is accessible via the "holder"
   param.
 ********************************************************************************/
-static expr* try_hoisting(
+expr* HoistRule::hoistExpr(
     RewriterContext& rCtx,
     expr* e,
-    const expr_tools::VarIdMap& varmap,
-    const expr_tools::ExprVarsMap& freevarMap,
     struct PathHolder* path)
 {
   if (non_hoistable(e) || e->constructsNodes())
@@ -373,8 +477,8 @@
 
   assert(udf == rCtx.theUDF);
 
-  expr_tools::ExprVarsMap::const_iterator fvme = freevarMap.find(e);
-  ZORBA_ASSERT(fvme != freevarMap.end());
+  expr_tools::ExprVarsMap::const_iterator fvme = theExprVarsMap.find(e);
+  ZORBA_ASSERT(fvme != theExprVarsMap.end());
   const DynamicBitset& varset = fvme->second;
 
   PathHolder* step = path;
@@ -407,39 +511,17 @@
         {
           var_expr* trycatchVar = (*ite).second;
 
-          if (contains_var(trycatchVar, varmap, varset))
+          if (contains_var(trycatchVar, varset))
             return NULL;
         }
       }
     }
     else
     {
-      assert(step->theExpr->get_expr_kind() == flwor_expr_kind);
+      assert(step->theExpr->get_expr_kind() == flwor_expr_kind ||
+             step->theExpr->get_expr_kind() == gflwor_expr_kind);
 
       flwor_expr* flwor = static_cast<flwor_expr*>(step->theExpr);
-      groupby_clause* gc = flwor->get_group_clause();
-
-      // If any free variable is a group-by variable, give up.
-      if (gc != NULL)
-      {
-        const flwor_clause::rebind_list_t& gvars = gc->get_grouping_vars();
-        csize numGroupVars = gvars.size();
-
-        for (csize i = 0; i < numGroupVars; ++i)
-        {
-          if (contains_var(gvars[i].second, varmap, varset))
-            return NULL;
-        }
-
-        const flwor_clause::rebind_list_t& ngvars = gc->get_nongrouping_vars();
-        csize numNonGroupVars = ngvars.size();
-
-        for (csize i = 0; i < numNonGroupVars; ++i)
-        {
-          if (contains_var(ngvars[i].second, varmap, varset))
-            return NULL;
-        }
-      }
 
       // Check whether expr e references any variables from the current flwor. If
       // not, then e can be hoisted out of the current flwor and we repeat the
@@ -449,26 +531,151 @@
       // cannot be hoisted.
       for (i = step->clauseCount - 1; i >= 0; --i)
       {
-        const forlet_clause* flc =
-        static_cast<const forlet_clause*>(flwor->get_clause(i));
-
-        if (flc->get_expr()->is_sequential())
-        {
-          foundSequentialClause = true;
-          break;
-        }
-
-        if (contains_var(flc->get_var(), varmap, varset) ||
-            contains_var(flc->get_pos_var(), varmap, varset) ||
-            contains_var(flc->get_score_var(), varmap, varset))
-        {
-          foundReferencedFLWORVar = true;
-          break;
-        }
-
-        inloop = (inloop ||
-                  (flc->get_kind() == flwor_clause::for_clause &&
-                   flc->get_expr()->get_return_type()->max_card() >= 2));
+        flwor_clause* c = flwor->get_clause(i);
+
+        switch (c->get_kind())
+        {
+        case flwor_clause::for_clause:
+        case flwor_clause::let_clause:
+        case flwor_clause::window_clause:
+        {
+          forletwin_clause* flwc = static_cast<forletwin_clause*>(c);
+
+          if (flwc->get_expr()->is_sequential())
+          {
+            foundSequentialClause = true;
+            break;
+          }
+
+          if (contains_var(flwc->get_var(), varset) ||
+              contains_var(flwc->get_pos_var(), varset))
+            // contains_var(flc->get_score_var(), varset)
+          {
+            foundReferencedFLWORVar = true;
+            break;
+          }
+
+          if (c->get_kind() == flwor_clause::window_clause)
+          {
+            window_clause* wc = static_cast<window_clause*>(c);
+            flwor_wincond* startCond = wc->get_win_start();
+            flwor_wincond* stopCond = wc->get_win_stop();
+            
+            if (startCond)
+            {
+              const flwor_wincond_vars& vars = startCond->get_out_vars();
+
+              if (contains_var(vars.posvar, varset) ||
+                  contains_var(vars.curr, varset) ||
+                  contains_var(vars.prev, varset) ||
+                  contains_var(vars.next, varset))
+              {
+                foundReferencedFLWORVar = true;
+                break;
+              }
+
+              const flwor_wincond_vars& invars = startCond->get_in_vars();
+
+              if (contains_var(invars.posvar, varset) ||
+                  contains_var(invars.curr, varset) ||
+                  contains_var(invars.prev, varset) ||
+                  contains_var(invars.next, varset))
+              {
+                foundReferencedFLWORVar = true;
+                break;
+              }
+            }
+
+            if (stopCond)
+            {
+              const flwor_wincond_vars& vars = stopCond->get_out_vars();
+
+              if (contains_var(vars.posvar, varset) ||
+                  contains_var(vars.curr, varset) ||
+                  contains_var(vars.prev, varset) ||
+                  contains_var(vars.next, varset))
+              {
+                foundReferencedFLWORVar = true;
+                break;
+              }
+
+              const flwor_wincond_vars& invars = stopCond->get_in_vars();
+
+              if (contains_var(invars.posvar, varset) ||
+                  contains_var(invars.curr, varset) ||
+                  contains_var(invars.prev, varset) ||
+                  contains_var(invars.next, varset))
+              {
+                foundReferencedFLWORVar = true;
+                break;
+              }
+            }
+          }
+
+          if (!inloop)
+            inloop = ((c->get_kind() == flwor_clause::for_clause ||
+                       c->get_kind() == flwor_clause::window_clause) &&
+                      flwc->get_expr()->get_return_type()->max_card() >= 2);
+
+          break;
+        }
+        case flwor_clause::groupby_clause:
+        {
+          groupby_clause* gc = static_cast<groupby_clause*>(c);
+
+          var_rebind_list_t::iterator ite = gc->beginGroupVars();
+          var_rebind_list_t::iterator end = gc->endGroupVars();
+          for (; ite != end; ++ite)
+          {
+            if (contains_var((*ite).second, varset))
+            {
+              foundReferencedFLWORVar = true;
+              break;
+            }
+          }
+
+          if (foundReferencedFLWORVar)
+            break;
+
+          ite = gc->beginNonGroupVars();
+          end = gc->endNonGroupVars();
+          for (; ite != end; ++ite)
+          {
+            if (contains_var((*ite).second, varset))
+            {
+              foundReferencedFLWORVar = true;
+              break;
+            }
+          }
+
+          break;
+        }
+        case flwor_clause::count_clause:
+        {
+          count_clause* cc = static_cast<count_clause*>(c);
+
+          if (contains_var(cc->get_var(), varset))
+          {
+            foundReferencedFLWORVar = true;
+          }
+
+          break;
+        }
+        case flwor_clause::orderby_clause:
+        case flwor_clause::where_clause:
+        {
+          break;
+        }
+        case flwor_clause::materialize_clause:
+        {
+          return NULL;
+        }
+        default:
+          ZORBA_ASSERT(false);
+        }
+
+        if (foundSequentialClause || foundReferencedFLWORVar)
+          break;
       }
 
       if (foundSequentialClause || foundReferencedFLWORVar)
@@ -508,7 +715,8 @@
     }
     static_cast<flwor_expr*>(step->theExpr)->add_clause(flref);
   }
-  else if (step->theExpr->get_expr_kind() == flwor_expr_kind)
+  else if (step->theExpr->get_expr_kind() == flwor_expr_kind ||
+           step->theExpr->get_expr_kind() == gflwor_expr_kind)
   {
     static_cast<flwor_expr*>(step->theExpr)->add_clause(i + 1, flref);
     ++step->clauseCount;
@@ -527,11 +735,10 @@
   }
 
   expr* unhoisted = rCtx.theEM->
-  create_fo_expr(sctx,
-                 udf,
-                 loc,
+  create_fo_expr(sctx, udf, loc,
                  BUILTIN_FUNC(OP_UNHOIST_1),
                  rCtx.theEM->create_wrapper_expr(sctx, udf, loc, letvar));
+
   unhoisted->setAnnotationFlags(e->getAnnotationFlags());
 
   return unhoisted;
@@ -541,23 +748,17 @@
 /*******************************************************************************
   Check if the given var is contained in the given varset.
 ********************************************************************************/
-static bool contains_var(
-    var_expr* v,
-    const expr_tools::VarIdMap& varmap,
-    const DynamicBitset& varset)
+bool HoistRule::contains_var(var_expr* v, const DynamicBitset& varset)
 {
   if (v == NULL)
-  {
-    return false;
-  }
-
-  expr_tools::VarIdMap::const_iterator i = varmap.find(v);
-  if (i == varmap.end())
-  {
-    return false;
-  }
-  int bit = i->second;
-  return varset.get(bit);
+    return false;
+
+  expr_tools::VarIdMap::const_iterator i = theVarIdMap.find(v);
+
+  if (i == theVarIdMap.end())
+    return false;
+
+  return varset.get(i->second);
 }
 
 
@@ -589,8 +790,17 @@
   {
     const fo_expr* fo = static_cast<const fo_expr*>(e);
     const function* f = fo->get_func();
-
-    if (f->getKind() == FunctionConsts::OP_CONCATENATE_N && fo->num_args() == 0)
+    FunctionConsts::FunctionKind fkind = f->getKind();
+
+    if (fkind == FunctionConsts::OP_CONCATENATE_N && fo->num_args() == 0)
+      return true;
+
+    if (fkind == FunctionConsts::STATIC_COLLECTIONS_DML_COLLECTION_1 ||
+        fkind == FunctionConsts::STATIC_COLLECTIONS_DML_COLLECTION_2 ||
+        fkind == FunctionConsts::STATIC_COLLECTIONS_DML_COLLECTION_3 ||
+        fkind == FunctionConsts::DYNAMIC_COLLECTIONS_DML_COLLECTION_1 ||
+        fkind == FunctionConsts::DYNAMIC_COLLECTIONS_DML_COLLECTION_2 ||
+        fkind == FunctionConsts::DYNAMIC_COLLECTIONS_DML_COLLECTION_3)
       return true;
   }
 

=== modified file 'src/compiler/rewriter/rules/ruleset.h'
--- src/compiler/rewriter/rules/ruleset.h	2013-02-08 08:23:51 +0000
+++ src/compiler/rewriter/rules/ruleset.h	2013-05-15 07:29:31 +0000
@@ -223,19 +223,6 @@
 };
 
 
-/*******************************************************************************
-
-********************************************************************************/
-class HoistRule : public RewriteRule
-{
-public:
-  HoistRule() : RewriteRule(RewriteRule::IndexJoin, "Hoist") {}
-
-  expr* apply(RewriterContext& rCtx, expr* node, bool& modified);
-};
-
-
-
 }
 
 #endif /* ZORBA_REWRITE_RULE_H */

=== modified file 'src/system/globalenv.cpp'
--- src/system/globalenv.cpp	2013-05-08 20:14:47 +0000
+++ src/system/globalenv.cpp	2013-05-15 07:29:31 +0000
@@ -30,13 +30,18 @@
 #include "zorbautils/fatal.h"
 
 #include "globalenv.h"
+
 #include "types/root_typemanager.h"
 #include "types/schema/schema.h"
+
 #include "context/root_static_context.h"
 #include "context/default_url_resolvers.h"
 #include "context/dynamic_loader.h"
+
 #include "functions/library.h"
+
 #include "annotations/annotations.h"
+
 #include "compiler/api/compiler_api.h"
 #include "compiler/xqueryx/xqueryx_to_xquery.h"
 

=== modified file 'test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/gflwor_02.iter'
--- test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/gflwor_02.iter	2013-02-21 16:34:45 +0000
+++ test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/gflwor_02.iter	2013-05-15 07:29:31 +0000
@@ -98,35 +98,78 @@
       </FnConcatIterator>
     </ElementIterator>
   </CtxVarDeclareIterator>
-  <CreateInternalIndexIterator name="xs:QName(,,tempIndex0)">
-    <flwor::FLWORIterator>
-      <ForVariable name="$$opt_temp_0">
-        <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,sale)" typename="*" nill allowed="0">
-          <CtxVarIterator varid="5" varname="sales" varkind="global"/>
-        </ChildAxisIterator>
-      </ForVariable>
-      <ReturnClause>
-        <ValueIndexEntryBuilderIterator>
-          <ForVarIterator varname="$$opt_temp_0"/>
-          <FnStringIterator>
-            <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,pid)" typename="*" nill allowed="0">
-              <ForVarIterator varname="$$opt_temp_0"/>
-            </AttributeAxisIterator>
-          </FnStringIterator>
-        </ValueIndexEntryBuilderIterator>
-      </ReturnClause>
-    </flwor::FLWORIterator>
-  </CreateInternalIndexIterator>
   <flwor::TupleStreamIterator>
     <flwor::ForIterator>
       <ForVariable name="s"/>
       <flwor::WhereIterator>
         <flwor::ForIterator>
-          <ForVariable name="p"/>
-          <flwor::TupleSourceIterator/>
-          <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,prod)" typename="*" nill allowed="0">
-            <CtxVarIterator varid="4" varname="products" varkind="global"/>
-          </ChildAxisIterator>
+          <ForVariable name="$$opt_temp_1"/>
+          <flwor::LetIterator>
+            <LetVariable name="$$opt_temp_2" materialize="true"/>
+            <flwor::LetIterator>
+              <LetVariable name="$$opt_temp_3" materialize="true"/>
+              <flwor::ForIterator>
+                <ForVariable name="p"/>
+                <flwor::LetIterator>
+                  <LetVariable name="$$opt_temp_6" materialize="true"/>
+                  <flwor::LetIterator>
+                    <LetVariable name="$$opt_temp_0" materialize="true"/>
+                    <flwor::TupleSourceIterator/>
+                    <HoistIterator>
+                      <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,sale)" typename="*" nill allowed="0">
+                        <CtxVarIterator varid="5" varname="sales" varkind="global"/>
+                      </ChildAxisIterator>
+                    </HoistIterator>
+                  </flwor::LetIterator>
+                  <CreateInternalIndexIterator name="xs:QName(,,tempIndex0)">
+                    <flwor::FLWORIterator>
+                      <ForVariable name="$$opt_temp_4">
+                        <UnhoistIterator>
+                          <LetVarIterator varname="$$opt_temp_0"/>
+                        </UnhoistIterator>
+                      </ForVariable>
+                      <ReturnClause>
+                        <ValueIndexEntryBuilderIterator>
+                          <ForVarIterator varname="$$opt_temp_4"/>
+                          <FnStringIterator>
+                            <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,pid)" typename="*" nill allowed="0">
+                              <ForVarIterator varname="$$opt_temp_4"/>
+                            </AttributeAxisIterator>
+                          </FnStringIterator>
+                        </ValueIndexEntryBuilderIterator>
+                      </ReturnClause>
+                    </flwor::FLWORIterator>
+                  </CreateInternalIndexIterator>
+                </flwor::LetIterator>
+                <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,prod)" typename="*" nill allowed="0">
+                  <CtxVarIterator varid="4" varname="products" varkind="global"/>
+                </ChildAxisIterator>
+              </flwor::ForIterator>
+              <HoistIterator>
+                <PromoteIterator type="xs:anyAtomicType">
+                  <FnDataIterator>
+                    <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,price)" typename="*" nill allowed="0">
+                      <ForVarIterator varname="p"/>
+                    </AttributeAxisIterator>
+                  </FnDataIterator>
+                </PromoteIterator>
+              </HoistIterator>
+            </flwor::LetIterator>
+            <HoistIterator>
+              <FnDataIterator>
+                <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,name)" typename="*" nill allowed="0">
+                  <ForVarIterator varname="p"/>
+                </AttributeAxisIterator>
+              </FnDataIterator>
+            </HoistIterator>
+          </flwor::LetIterator>
+          <HoistIterator>
+            <FnStringIterator>
+              <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,id)" typename="*" nill allowed="0">
+                <ForVarIterator varname="p"/>
+              </AttributeAxisIterator>
+            </FnStringIterator>
+          </HoistIterator>
         </flwor::ForIterator>
         <CompareIterator>
           <CastIterator type="xs:integer">
@@ -141,11 +184,9 @@
       </flwor::WhereIterator>
       <ProbeIndexPointValueIterator>
         <SingletonIterator value="xs:QName(,,tempIndex0)"/>
-        <FnStringIterator>
-          <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,id)" typename="*" nill allowed="0">
-            <ForVarIterator varname="p"/>
-          </AttributeAxisIterator>
-        </FnStringIterator>
+        <UnhoistIterator>
+          <ForVarIterator varname="$$opt_temp_1"/>
+        </UnhoistIterator>
       </ProbeIndexPointValueIterator>
     </flwor::ForIterator>
     <ElementIterator>
@@ -153,23 +194,17 @@
       <FnConcatIterator>
         <AttributeIterator qname="xs:QName(,,prod)">
           <EnclosedIterator attr_cont="true">
-            <FnDataIterator>
-              <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,name)" typename="*" nill allowed="0">
-                <ForVarIterator varname="p"/>
-              </AttributeAxisIterator>
-            </FnDataIterator>
+            <UnhoistIterator>
+              <LetVarIterator varname="$$opt_temp_2"/>
+            </UnhoistIterator>
           </EnclosedIterator>
         </AttributeIterator>
         <AttributeIterator qname="xs:QName(,,amount)">
           <EnclosedIterator attr_cont="true">
             <GenericArithIterator_MultiplyOperation>
-              <PromoteIterator type="xs:anyAtomicType">
-                <FnDataIterator>
-                  <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,price)" typename="*" nill allowed="0">
-                    <ForVarIterator varname="p"/>
-                  </AttributeAxisIterator>
-                </FnDataIterator>
-              </PromoteIterator>
+              <UnhoistIterator>
+                <LetVarIterator varname="$$opt_temp_3"/>
+              </UnhoistIterator>
               <PromoteIterator type="xs:anyAtomicType">
                 <FnDataIterator>
                   <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,qty)" typename="*" nill allowed="0">

=== modified file 'test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/gflwor_03.iter'
--- test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/gflwor_03.iter	2013-02-28 10:59:07 +0000
+++ test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/gflwor_03.iter	2013-05-15 07:29:31 +0000
@@ -94,88 +94,107 @@
       </FnConcatIterator>
     </ElementIterator>
   </CtxVarDeclareIterator>
-  <CreateInternalIndexIterator name="xs:QName(,,tempIndex0)">
-    <flwor::FLWORIterator>
-      <ForVariable name="$$opt_temp_0">
-        <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,loc)" typename="*" nill allowed="0">
-          <CtxVarIterator varid="5" varname="locations" varkind="global"/>
-        </ChildAxisIterator>
-      </ForVariable>
-      <ReturnClause>
-        <ValueIndexEntryBuilderIterator>
-          <ForVarIterator varname="$$opt_temp_0"/>
-          <FnStringIterator>
-            <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,id)" typename="*" nill allowed="0">
-              <ForVarIterator varname="$$opt_temp_0"/>
-            </AttributeAxisIterator>
-          </FnStringIterator>
-        </ValueIndexEntryBuilderIterator>
-      </ReturnClause>
-    </flwor::FLWORIterator>
-  </CreateInternalIndexIterator>
-  <flwor::FLWORIterator>
-    <ForVariable name="s">
-      <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,sale)" typename="*" nill allowed="0">
-        <CtxVarIterator varid="4" varname="sales" varkind="global"/>
-      </ChildAxisIterator>
-    </ForVariable>
-    <GroupByClause>
-      <Spec>
-        <TreatIterator quant="?">
-          <FnDataIterator>
-            <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,locid)" typename="*" nill allowed="0">
-              <ForVarIterator varname="s"/>
-            </AttributeAxisIterator>
-          </FnDataIterator>
-        </TreatIterator>
-        <GroupVariable/>
-      </Spec>
-      <Spec>
-        <ForVarIterator varname="s"/>
-        <NonGroupVariable/>
-      </Spec>
-    </GroupByClause>
-    <ReturnClause>
-      <ElementIterator>
-        <SingletonIterator value="xs:QName(,,sale)"/>
-        <FnConcatIterator>
-          <AttributeIterator qname="xs:QName(,,city)">
-            <EnclosedIterator attr_cont="true">
+  <flwor::TupleStreamIterator>
+    <flwor::ForIterator>
+      <ForVariable name="$$opt_temp_1"/>
+      <flwor::GroupByIterator>
+        <flwor::ForIterator>
+          <ForVariable name="s"/>
+          <flwor::LetIterator>
+            <LetVariable name="$$opt_temp_4" materialize="true"/>
+            <flwor::LetIterator>
+              <LetVariable name="$$opt_temp_0" materialize="true"/>
+              <flwor::TupleSourceIterator/>
+              <HoistIterator>
+                <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,loc)" typename="*" nill allowed="0">
+                  <CtxVarIterator varid="5" varname="locations" varkind="global"/>
+                </ChildAxisIterator>
+              </HoistIterator>
+            </flwor::LetIterator>
+            <CreateInternalIndexIterator name="xs:QName(,,tempIndex0)">
+              <flwor::FLWORIterator>
+                <ForVariable name="$$opt_temp_2">
+                  <UnhoistIterator>
+                    <LetVarIterator varname="$$opt_temp_0"/>
+                  </UnhoistIterator>
+                </ForVariable>
+                <ReturnClause>
+                  <ValueIndexEntryBuilderIterator>
+                    <ForVarIterator varname="$$opt_temp_2"/>
+                    <FnStringIterator>
+                      <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,id)" typename="*" nill allowed="0">
+                        <ForVarIterator varname="$$opt_temp_2"/>
+                      </AttributeAxisIterator>
+                    </FnStringIterator>
+                  </ValueIndexEntryBuilderIterator>
+                </ReturnClause>
+              </flwor::FLWORIterator>
+            </CreateInternalIndexIterator>
+          </flwor::LetIterator>
+          <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,sale)" typename="*" nill allowed="0">
+            <CtxVarIterator varid="4" varname="sales" varkind="global"/>
+          </ChildAxisIterator>
+        </flwor::ForIterator>
+        <Spec>
+          <TreatIterator quant="?">
+            <FnDataIterator>
+              <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,locid)" typename="*" nill allowed="0">
+                <ForVarIterator varname="s"/>
+              </AttributeAxisIterator>
+            </FnDataIterator>
+          </TreatIterator>
+          <GroupVariable/>
+        </Spec>
+        <Spec>
+          <ForVarIterator varname="s"/>
+          <NonGroupVariable/>
+        </Spec>
+      </flwor::GroupByIterator>
+      <HoistIterator>
+        <FnStringIterator>
+          <ForVarIterator varname="loc"/>
+        </FnStringIterator>
+      </HoistIterator>
+    </flwor::ForIterator>
+    <ElementIterator>
+      <SingletonIterator value="xs:QName(,,sale)"/>
+      <FnConcatIterator>
+        <AttributeIterator qname="xs:QName(,,city)">
+          <EnclosedIterator attr_cont="true">
+            <FnDataIterator>
+              <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,city)" typename="*" nill allowed="0">
+                <flwor::FLWORIterator>
+                  <ForVariable name="$$context-item">
+                    <ProbeIndexPointValueIterator>
+                      <SingletonIterator value="xs:QName(,,tempIndex0)"/>
+                      <UnhoistIterator>
+                        <ForVarIterator varname="$$opt_temp_1"/>
+                      </UnhoistIterator>
+                    </ProbeIndexPointValueIterator>
+                  </ForVariable>
+                  <ReturnClause>
+                    <ForVarIterator varname="$$context-item"/>
+                  </ReturnClause>
+                </flwor::FLWORIterator>
+              </AttributeAxisIterator>
+            </FnDataIterator>
+          </EnclosedIterator>
+        </AttributeIterator>
+        <AttributeIterator qname="xs:QName(,,qty)">
+          <EnclosedIterator attr_cont="true">
+            <FnSumIterator>
               <FnDataIterator>
-                <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,city)" typename="*" nill allowed="0">
-                  <flwor::FLWORIterator>
-                    <ForVariable name="$$context-item">
-                      <ProbeIndexPointValueIterator>
-                        <SingletonIterator value="xs:QName(,,tempIndex0)"/>
-                        <FnStringIterator>
-                          <ForVarIterator varname="loc"/>
-                        </FnStringIterator>
-                      </ProbeIndexPointValueIterator>
-                    </ForVariable>
-                    <ReturnClause>
-                      <ForVarIterator varname="$$context-item"/>
-                    </ReturnClause>
-                  </flwor::FLWORIterator>
-                </AttributeAxisIterator>
+                <NodeDistinctIterator allow-atomics="false" check-only="false">
+                  <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,qty)" typename="*" nill allowed="0">
+                    <LetVarIterator varname="s"/>
+                  </AttributeAxisIterator>
+                </NodeDistinctIterator>
               </FnDataIterator>
-            </EnclosedIterator>
-          </AttributeIterator>
-          <AttributeIterator qname="xs:QName(,,qty)">
-            <EnclosedIterator attr_cont="true">
-              <FnSumIterator>
-                <FnDataIterator>
-                  <NodeDistinctIterator allow-atomics="false" check-only="false">
-                    <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,qty)" typename="*" nill allowed="0">
-                      <LetVarIterator varname="s"/>
-                    </AttributeAxisIterator>
-                  </NodeDistinctIterator>
-                </FnDataIterator>
-              </FnSumIterator>
-            </EnclosedIterator>
-          </AttributeIterator>
-        </FnConcatIterator>
-      </ElementIterator>
-    </ReturnClause>
-  </flwor::FLWORIterator>
+            </FnSumIterator>
+          </EnclosedIterator>
+        </AttributeIterator>
+      </FnConcatIterator>
+    </ElementIterator>
+  </flwor::TupleStreamIterator>
 </SequentialIterator>
 

=== modified file 'test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/gflwor_04.iter'
--- test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/gflwor_04.iter	2013-03-04 23:38:24 +0000
+++ test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/gflwor_04.iter	2013-05-15 07:29:31 +0000
@@ -3,65 +3,81 @@
   <flwor::LetIterator>
     <LetVariable name="y" materialize="true"/>
     <flwor::CountIterator>
-      <flwor::ForIterator>
-        <ForVariable name="x"/>
-        <flwor::LetIterator>
-          <LetVariable name="$$opt_temp_2" materialize="true"/>
-          <flwor::ForIterator>
-            <ForVariable name="a"/>
-            <flwor::TupleSourceIterator/>
-            <FnConcatIterator>
-              <SingletonIterator value="xs:integer(1)"/>
-              <SingletonIterator value="xs:integer(2)"/>
-            </FnConcatIterator>
-          </flwor::ForIterator>
-          <CreateInternalIndexIterator name="xs:QName(,,tempIndex0)">
-            <flwor::FLWORIterator>
-              <ForVariable name="$$opt_temp_0">
+      <flwor::LetIterator>
+        <LetVariable name="$$opt_temp_1" materialize="true"/>
+        <flwor::ForIterator>
+          <ForVariable name="x"/>
+          <flwor::LetIterator>
+            <LetVariable name="$$opt_temp_4" materialize="true"/>
+            <flwor::LetIterator>
+              <LetVariable name="$$opt_temp_0" materialize="true"/>
+              <flwor::ForIterator>
+                <ForVariable name="a"/>
+                <flwor::TupleSourceIterator/>
+                <FnConcatIterator>
+                  <SingletonIterator value="xs:integer(1)"/>
+                  <SingletonIterator value="xs:integer(2)"/>
+                </FnConcatIterator>
+              </flwor::ForIterator>
+              <HoistIterator>
                 <UDFunctionCallIterator function="local:foo">
                   <ForVarIterator varname="a"/>
                 </UDFunctionCallIterator>
-              </ForVariable>
-              <ReturnClause>
-                <ValueIndexEntryBuilderIterator>
-                  <ForVarIterator varname="$$opt_temp_0"/>
-                  <ForVarIterator varname="$$opt_temp_0"/>
-                </ValueIndexEntryBuilderIterator>
-              </ReturnClause>
-            </flwor::FLWORIterator>
-          </CreateInternalIndexIterator>
-        </flwor::LetIterator>
-        <FnConcatIterator>
-          <ElementIterator>
-            <SingletonIterator value="xs:QName(,,a)"/>
-            <TextIterator>
-              <SingletonIterator value="xs:string(1)"/>
-            </TextIterator>
-          </ElementIterator>
-          <ElementIterator>
-            <SingletonIterator value="xs:QName(,,a)"/>
-            <TextIterator>
-              <SingletonIterator value="xs:string(2)"/>
-            </TextIterator>
-          </ElementIterator>
-          <ElementIterator>
-            <SingletonIterator value="xs:QName(,,a)"/>
-            <TextIterator>
-              <SingletonIterator value="xs:string(3)"/>
-            </TextIterator>
-          </ElementIterator>
-        </FnConcatIterator>
-      </flwor::ForIterator>
+              </HoistIterator>
+            </flwor::LetIterator>
+            <CreateInternalIndexIterator name="xs:QName(,,tempIndex0)">
+              <flwor::FLWORIterator>
+                <ForVariable name="$$opt_temp_2">
+                  <UnhoistIterator>
+                    <LetVarIterator varname="$$opt_temp_0"/>
+                  </UnhoistIterator>
+                </ForVariable>
+                <ReturnClause>
+                  <ValueIndexEntryBuilderIterator>
+                    <ForVarIterator varname="$$opt_temp_2"/>
+                    <ForVarIterator varname="$$opt_temp_2"/>
+                  </ValueIndexEntryBuilderIterator>
+                </ReturnClause>
+              </flwor::FLWORIterator>
+            </CreateInternalIndexIterator>
+          </flwor::LetIterator>
+          <FnConcatIterator>
+            <ElementIterator>
+              <SingletonIterator value="xs:QName(,,a)"/>
+              <TextIterator>
+                <SingletonIterator value="xs:string(1)"/>
+              </TextIterator>
+            </ElementIterator>
+            <ElementIterator>
+              <SingletonIterator value="xs:QName(,,a)"/>
+              <TextIterator>
+                <SingletonIterator value="xs:string(2)"/>
+              </TextIterator>
+            </ElementIterator>
+            <ElementIterator>
+              <SingletonIterator value="xs:QName(,,a)"/>
+              <TextIterator>
+                <SingletonIterator value="xs:string(3)"/>
+              </TextIterator>
+            </ElementIterator>
+          </FnConcatIterator>
+        </flwor::ForIterator>
+        <HoistIterator>
+          <CastIterator type="xs:integer">
+            <FnDataIterator>
+              <ForVarIterator varname="x"/>
+            </FnDataIterator>
+          </CastIterator>
+        </HoistIterator>
+      </flwor::LetIterator>
     </flwor::CountIterator>
     <flwor::FLWORIterator>
       <ForVariable name="z">
         <ProbeIndexPointValueIterator>
           <SingletonIterator value="xs:QName(,,tempIndex0)"/>
-          <CastIterator type="xs:integer">
-            <FnDataIterator>
-              <ForVarIterator varname="x"/>
-            </FnDataIterator>
-          </CastIterator>
+          <UnhoistIterator>
+            <LetVarIterator varname="$$opt_temp_1"/>
+          </UnhoistIterator>
         </ProbeIndexPointValueIterator>
       </ForVariable>
       <ReturnClause>

=== modified file 'test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/gflwor_05.iter'
--- test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/gflwor_05.iter	2013-02-28 10:59:07 +0000
+++ test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/gflwor_05.iter	2013-05-15 07:29:31 +0000
@@ -1,19 +1,26 @@
 Iterator tree for main query:
 <flwor::FLWORIterator>
-  <LetVariable name="$$opt_temp_2" materialize="true">
+  <LetVariable name="$$opt_temp_0" materialize="true">
+    <HoistIterator>
+      <FnConcatIterator>
+        <SingletonIterator value="xs:integer(1)"/>
+        <SingletonIterator value="xs:integer(2)"/>
+        <SingletonIterator value="xs:integer(3)"/>
+      </FnConcatIterator>
+    </HoistIterator>
+  </LetVariable>
+  <LetVariable name="$$opt_temp_4" materialize="true">
     <CreateInternalIndexIterator name="xs:QName(,,tempIndex0)">
       <flwor::FLWORIterator>
-        <ForVariable name="$$opt_temp_0">
-          <FnConcatIterator>
-            <SingletonIterator value="xs:integer(1)"/>
-            <SingletonIterator value="xs:integer(2)"/>
-            <SingletonIterator value="xs:integer(3)"/>
-          </FnConcatIterator>
+        <ForVariable name="$$opt_temp_2">
+          <UnhoistIterator>
+            <LetVarIterator varname="$$opt_temp_0"/>
+          </UnhoistIterator>
         </ForVariable>
         <ReturnClause>
           <ValueIndexEntryBuilderIterator>
-            <ForVarIterator varname="$$opt_temp_0"/>
-            <ForVarIterator varname="$$opt_temp_0"/>
+            <ForVarIterator varname="$$opt_temp_2"/>
+            <ForVarIterator varname="$$opt_temp_2"/>
           </ValueIndexEntryBuilderIterator>
         </ReturnClause>
       </flwor::FLWORIterator>
@@ -41,6 +48,15 @@
       </ElementIterator>
     </FnConcatIterator>
   </ForVariable>
+  <LetVariable name="$$opt_temp_1" materialize="true">
+    <HoistIterator>
+      <CastIterator type="xs:integer">
+        <FnDataIterator>
+          <ForVarIterator varname="x"/>
+        </FnDataIterator>
+      </CastIterator>
+    </HoistIterator>
+  </LetVariable>
   <LetVariable name="y" materialize="true">
     <flwor::TupleStreamIterator>
       <flwor::ForIterator>
@@ -81,11 +97,9 @@
         </flwor::GroupByIterator>
         <ProbeIndexPointValueIterator>
           <SingletonIterator value="xs:QName(,,tempIndex0)"/>
-          <CastIterator type="xs:integer">
-            <FnDataIterator>
-              <ForVarIterator varname="x"/>
-            </FnDataIterator>
-          </CastIterator>
+          <UnhoistIterator>
+            <LetVarIterator varname="$$opt_temp_1"/>
+          </UnhoistIterator>
         </ProbeIndexPointValueIterator>
       </flwor::ForIterator>
       <ForVarIterator varname="w"/>

=== modified file 'test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/idx11.iter'
--- test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/idx11.iter	2013-02-21 16:34:45 +0000
+++ test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/idx11.iter	2013-05-15 07:29:31 +0000
@@ -7,26 +7,41 @@
 
 Iterator tree for main query:
 <flwor::FLWORIterator>
-  <LetVariable name="$$opt_temp_2" materialize="true">
+  <LetVariable name="$$opt_temp_1" materialize="true">
+    <HoistIterator>
+      <FnConcatIterator>
+        <SingletonIterator value="xs:integer(1)"/>
+        <SingletonIterator value="xs:integer(2)"/>
+        <SingletonIterator value="xs:integer(2)"/>
+        <SingletonIterator value="xs:integer(3)"/>
+      </FnConcatIterator>
+    </HoistIterator>
+  </LetVariable>
+  <LetVariable name="$$opt_temp_5" materialize="true">
     <CreateInternalIndexIterator name="xs:QName(,,tempIndex0)">
       <flwor::FLWORIterator>
-        <ForVariable name="$$opt_temp_0">
-          <FnConcatIterator>
-            <SingletonIterator value="xs:integer(1)"/>
-            <SingletonIterator value="xs:integer(2)"/>
-            <SingletonIterator value="xs:integer(2)"/>
-            <SingletonIterator value="xs:integer(3)"/>
-          </FnConcatIterator>
+        <ForVariable name="$$opt_temp_3">
+          <UnhoistIterator>
+            <LetVarIterator varname="$$opt_temp_1"/>
+          </UnhoistIterator>
         </ForVariable>
         <ReturnClause>
           <ValueIndexEntryBuilderIterator>
-            <ForVarIterator varname="$$opt_temp_0"/>
-            <ForVarIterator varname="$$opt_temp_0"/>
+            <ForVarIterator varname="$$opt_temp_3"/>
+            <ForVarIterator varname="$$opt_temp_3"/>
           </ValueIndexEntryBuilderIterator>
         </ReturnClause>
       </flwor::FLWORIterator>
     </CreateInternalIndexIterator>
   </LetVariable>
+  <LetVariable name="$$opt_temp_0" materialize="true">
+    <HoistIterator>
+      <FnConcatIterator>
+        <SingletonIterator value="xs:integer(1)"/>
+        <SingletonIterator value="xs:integer(2)"/>
+      </FnConcatIterator>
+    </HoistIterator>
+  </LetVariable>
   <ForVariable name="x">
     <FnConcatIterator>
       <SingletonIterator value="xs:integer(1)"/>
@@ -35,11 +50,17 @@
     </FnConcatIterator>
   </ForVariable>
   <LetVariable name="y" materialize="true">
-    <FnConcatIterator>
-      <SingletonIterator value="xs:integer(1)"/>
-      <SingletonIterator value="xs:integer(2)"/>
-    </FnConcatIterator>
+    <UnhoistIterator>
+      <LetVarIterator varname="$$opt_temp_0"/>
+    </UnhoistIterator>
   </LetVariable>
+  <ForVariable name="$$opt_temp_2">
+    <HoistIterator>
+      <FnCountIterator>
+        <LetVarIterator varname="y"/>
+      </FnCountIterator>
+    </HoistIterator>
+  </ForVariable>
   <ForVariable name="$$context-item">
     <ProbeIndexPointValueIterator>
       <SingletonIterator value="xs:QName(,,tempIndex0)"/>
@@ -49,9 +70,9 @@
   <WhereClause>
     <TypedValueCompareIterator_INTEGER>
       <ForVarIterator varname="$$context-item"/>
-      <FnCountIterator>
-        <LetVarIterator varname="y"/>
-      </FnCountIterator>
+      <UnhoistIterator>
+        <ForVarIterator varname="$$opt_temp_2"/>
+      </UnhoistIterator>
     </TypedValueCompareIterator_INTEGER>
   </WhereClause>
   <ReturnClause>

=== modified file 'test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/idx9.iter'
--- test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/idx9.iter	2013-02-21 16:34:45 +0000
+++ test/rbkt/ExpCompilerResults/IterPlan/zorba/hashjoins/idx9.iter	2013-05-15 07:29:31 +0000
@@ -31,21 +31,21 @@
           <flwor::ForIterator>
             <ForVariable name="$$context-item"/>
             <flwor::LetIterator>
-              <LetVariable name="$$opt_temp_2" materialize="true"/>
+              <LetVariable name="$$opt_temp_3" materialize="true"/>
               <flwor::TupleSourceIterator/>
               <CreateInternalIndexIterator name="xs:QName(,,tempIndex0)">
                 <flwor::FLWORIterator>
-                  <ForVariable name="$$opt_temp_0">
+                  <ForVariable name="$$opt_temp_1">
                     <ZorbaCollectionIterator>
                       <SingletonIterator value="xs:QName(http://foo.com,foo,game)"/>
                     </ZorbaCollectionIterator>
                   </ForVariable>
                   <ReturnClause>
                     <GeneralIndexEntryBuilderIterator>
-                      <ForVarIterator varname="$$opt_temp_0"/>
+                      <ForVarIterator varname="$$opt_temp_1"/>
                       <FnDataIterator>
                         <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,gid)" typename="*" nill allowed="0">
-                          <ForVarIterator varname="$$opt_temp_0"/>
+                          <ForVarIterator varname="$$opt_temp_1"/>
                         </AttributeAxisIterator>
                       </FnDataIterator>
                     </GeneralIndexEntryBuilderIterator>
@@ -70,11 +70,15 @@
           <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,result)" typename="*" nill allowed="0">
             <ProbeIndexPointGeneralIterator>
               <SingletonIterator value="xs:QName(,,tempIndex0)"/>
-              <FnDataIterator>
-                <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,gid)" typename="*" nill allowed="0">
-                  <ForVarIterator varname="$$context-item"/>
-                </AttributeAxisIterator>
-              </FnDataIterator>
+              <UnhoistIterator>
+                <HoistIterator>
+                  <FnDataIterator>
+                    <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,gid)" typename="*" nill allowed="0">
+                      <ForVarIterator varname="$$context-item"/>
+                    </AttributeAxisIterator>
+                  </FnDataIterator>
+                </HoistIterator>
+              </UnhoistIterator>
             </ProbeIndexPointGeneralIterator>
           </ChildAxisIterator>
         </FnBooleanIterator>

=== modified file 'test/rbkt/ExpCompilerResults/IterPlan/zorba/index/match_veq_04.iter'
--- test/rbkt/ExpCompilerResults/IterPlan/zorba/index/match_veq_04.iter	2013-02-18 01:12:45 +0000
+++ test/rbkt/ExpCompilerResults/IterPlan/zorba/index/match_veq_04.iter	2013-05-15 07:29:31 +0000
@@ -186,16 +186,23 @@
         <LetVariable name="id" materialize="true">
           <CtxVarIterator varid="5" varname="external_id" varkind="global"/>
         </LetVariable>
+        <LetVariable name="$$opt_temp_0" materialize="true">
+          <HoistIterator>
+            <PromoteIterator type="xs:anyAtomicType">
+              <FnDataIterator>
+                <LetVarIterator varname="id"/>
+              </FnDataIterator>
+            </PromoteIterator>
+          </HoistIterator>
+        </LetVariable>
         <LetVariable name="session" materialize="true">
           <flwor::FLWORIterator>
             <ForVariable name="$$context-item">
               <ProbeIndexPointValueIterator>
                 <SingletonIterator value="xs:QName(www.sessions.com,sessions,session-index)"/>
-                <PromoteIterator type="xs:anyAtomicType">
-                  <FnDataIterator>
-                    <LetVarIterator varname="id"/>
-                  </FnDataIterator>
-                </PromoteIterator>
+                <UnhoistIterator>
+                  <LetVarIterator varname="$$opt_temp_0"/>
+                </UnhoistIterator>
               </ProbeIndexPointValueIterator>
             </ForVariable>
             <ReturnClause>

=== modified file 'test/rbkt/ExpCompilerResults/IterPlan/zorba/index/match_veq_05.iter'
--- test/rbkt/ExpCompilerResults/IterPlan/zorba/index/match_veq_05.iter	2013-02-18 01:12:45 +0000
+++ test/rbkt/ExpCompilerResults/IterPlan/zorba/index/match_veq_05.iter	2013-05-15 07:29:31 +0000
@@ -263,16 +263,23 @@
         <LetVariable name="id" materialize="true">
           <CtxVarIterator varid="5" varname="external_id" varkind="global"/>
         </LetVariable>
+        <LetVariable name="$$opt_temp_0" materialize="true">
+          <HoistIterator>
+            <PromoteIterator type="xs:anyAtomicType">
+              <FnDataIterator>
+                <LetVarIterator varname="id"/>
+              </FnDataIterator>
+            </PromoteIterator>
+          </HoistIterator>
+        </LetVariable>
         <LetVariable name="session" materialize="true">
           <flwor::FLWORIterator>
             <ForVariable name="$$context-item">
               <ProbeIndexPointValueIterator>
                 <SingletonIterator value="xs:QName(www.sessions.com,sessions,session-index)"/>
-                <PromoteIterator type="xs:anyAtomicType">
-                  <FnDataIterator>
-                    <LetVarIterator varname="id"/>
-                  </FnDataIterator>
-                </PromoteIterator>
+                <UnhoistIterator>
+                  <LetVarIterator varname="$$opt_temp_0"/>
+                </UnhoistIterator>
               </ProbeIndexPointValueIterator>
             </ForVariable>
             <WhereClause>

=== modified file 'test/rbkt/ExpCompilerResults/IterPlan/zorba/index/match_veq_06.iter'
--- test/rbkt/ExpCompilerResults/IterPlan/zorba/index/match_veq_06.iter	2013-05-04 20:20:05 +0000
+++ test/rbkt/ExpCompilerResults/IterPlan/zorba/index/match_veq_06.iter	2013-05-15 07:29:31 +0000
@@ -134,13 +134,6 @@
         </FnTokenizeIterator>
       </CtxVarDeclareIterator>
       <flwor::FLWORIterator>
-        <LetVariable name="$$opt_temp_0" materialize="true">
-          <HoistIterator>
-            <ZorbaCollectionIterator>
-              <CtxVarIterator varid="4" varname="data:parents" varkind="global"/>
-            </ZorbaCollectionIterator>
-          </HoistIterator>
-        </LetVariable>
         <ForVariable name="segment">
           <CtxVarIterator varid="2" varname="segments" varkind="local"/>
         </ForVariable>

=== modified file 'test/rbkt/ExpCompilerResults/IterPlan/zorba/index/match_veq_10.iter'
--- test/rbkt/ExpCompilerResults/IterPlan/zorba/index/match_veq_10.iter	2013-02-21 22:41:14 +0000
+++ test/rbkt/ExpCompilerResults/IterPlan/zorba/index/match_veq_10.iter	2013-05-15 07:29:31 +0000
@@ -48,37 +48,45 @@
   </ApplyIterator>
   <flwor::TupleStreamIterator>
     <flwor::OrderByIterator>
-      <OrderByForVariable inputVar="id : "/>
       <OrderByForVariable inputVar="count : "/>
+      <OrderByLetVariable inputVar="$$opt_temp_0 : "/>
       <OrderBySpec>
         <ForVarIterator varname="count"/>
       </OrderBySpec>
       <flwor::ForIterator>
         <ForVariable name="count"/>
-        <flwor::GroupByIterator>
-          <flwor::ForIterator>
-            <ForVariable name="answers"/>
-            <flwor::TupleSourceIterator/>
-            <ZorbaCollectionIterator>
-              <SingletonIterator value="xs:QName(http://28.io/collections,db28,answers)"/>
-            </ZorbaCollectionIterator>
-          </flwor::ForIterator>
-          <Spec>
-            <TreatIterator quant="?">
-              <FnDataIterator>
-                <JSONObjectValueIterator>
-                  <ForVarIterator varname="answers"/>
-                  <SingletonIterator value="xs:string(question_id)"/>
-                </JSONObjectValueIterator>
-              </FnDataIterator>
-            </TreatIterator>
-            <GroupVariable/>
-          </Spec>
-          <Spec>
-            <ForVarIterator varname="answers"/>
-            <NonGroupVariable/>
-          </Spec>
-        </flwor::GroupByIterator>
+        <flwor::LetIterator>
+          <LetVariable name="$$opt_temp_0" materialize="true"/>
+          <flwor::GroupByIterator>
+            <flwor::ForIterator>
+              <ForVariable name="answers"/>
+              <flwor::TupleSourceIterator/>
+              <ZorbaCollectionIterator>
+                <SingletonIterator value="xs:QName(http://28.io/collections,db28,answers)"/>
+              </ZorbaCollectionIterator>
+            </flwor::ForIterator>
+            <Spec>
+              <TreatIterator quant="?">
+                <FnDataIterator>
+                  <JSONObjectValueIterator>
+                    <ForVarIterator varname="answers"/>
+                    <SingletonIterator value="xs:string(question_id)"/>
+                  </JSONObjectValueIterator>
+                </FnDataIterator>
+              </TreatIterator>
+              <GroupVariable/>
+            </Spec>
+            <Spec>
+              <ForVarIterator varname="answers"/>
+              <NonGroupVariable/>
+            </Spec>
+          </flwor::GroupByIterator>
+          <HoistIterator>
+            <CastIterator type="xs:string">
+              <ForVarIterator varname="id"/>
+            </CastIterator>
+          </HoistIterator>
+        </flwor::LetIterator>
         <FnCountIterator>
           <LetVarIterator varname="answers"/>
         </FnCountIterator>
@@ -92,12 +100,12 @@
           <ForVariable name="$$context-item">
             <ProbeIndexRangeValueIterator>
               <SingletonIterator value="xs:QName(http://28.io/collections,db28,question-id-idx)"/>
-              <CastIterator type="xs:string">
-                <ForVarIterator varname="id"/>
-              </CastIterator>
-              <CastIterator type="xs:string">
-                <ForVarIterator varname="id"/>
-              </CastIterator>
+              <UnhoistIterator>
+                <LetVarIterator varname="$$opt_temp_0"/>
+              </UnhoistIterator>
+              <UnhoistIterator>
+                <LetVarIterator varname="$$opt_temp_0"/>
+              </UnhoistIterator>
               <SingletonIterator value="xs:boolean(true)"/>
               <SingletonIterator value="xs:boolean(true)"/>
               <SingletonIterator value="xs:boolean(true)"/>

=== modified file 'test/rbkt/ExpCompilerResults/IterPlan/zorba/no-copy/q4.iter'
--- test/rbkt/ExpCompilerResults/IterPlan/zorba/no-copy/q4.iter	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpCompilerResults/IterPlan/zorba/no-copy/q4.iter	2013-05-15 07:29:31 +0000
@@ -31,6 +31,13 @@
         </ChildAxisIterator>
       </ChildAxisIterator>
     </ForVariable>
+    <LetVariable name="$$opt_temp_0" materialize="true">
+      <HoistIterator>
+        <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,bidder)" typename="*" nill allowed="0">
+          <ForVarIterator varname="b"/>
+        </ChildAxisIterator>
+      </HoistIterator>
+    </LetVariable>
     <WhereClause>
       <FnExistsIterator>
         <flwor::TupleStreamIterator>
@@ -63,9 +70,9 @@
                       <SingletonIterator value="xs:string(person20)"/>
                     </CompareIterator>
                   </flwor::WhereIterator>
-                  <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,bidder)" typename="*" nill allowed="0">
-                    <ForVarIterator varname="b"/>
-                  </ChildAxisIterator>
+                  <UnhoistIterator>
+                    <LetVarIterator varname="$$opt_temp_0"/>
+                  </UnhoistIterator>
                 </flwor::ForIterator>
                 <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,personref)" typename="*" nill allowed="0">
                   <ForVarIterator varname="$$context-item"/>

=== modified file 'test/rbkt/ExpCompilerResults/IterPlan/zorba/optim/var_inline_05.iter'
--- test/rbkt/ExpCompilerResults/IterPlan/zorba/optim/var_inline_05.iter	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpCompilerResults/IterPlan/zorba/optim/var_inline_05.iter	2013-05-15 07:29:31 +0000
@@ -23,6 +23,35 @@
           <ForVarIterator varname="e"/>
           <ForVarIterator varname="s"/>
         </SpecificNumArithIterator_SubtractOperation_INTEGER>
+        <UnhoistIterator>
+          <LetVarIterator varname="$$opt_temp_0"/>
+        </UnhoistIterator>
+      </TypedValueCompareIterator_INTEGER>
+    </FnBooleanIterator>
+    <flwor::LetIterator>
+      <LetVariable name="$$opt_temp_0" materialize="true"/>
+      <flwor::ForIterator>
+        <ForVariable name="x"/>
+        <flwor::TupleSourceIterator/>
+        <ElementIterator copyInputNodes="false">
+          <SingletonIterator value="xs:QName(,,a)"/>
+          <FnConcatIterator>
+            <ElementIterator copyInputNodes="false">
+              <SingletonIterator value="xs:QName(,,b)"/>
+              <TextIterator>
+                <SingletonIterator value="xs:string(1)"/>
+              </TextIterator>
+            </ElementIterator>
+            <ElementIterator copyInputNodes="false">
+              <SingletonIterator value="xs:QName(,,b)"/>
+              <TextIterator>
+                <SingletonIterator value="xs:string(2)"/>
+              </TextIterator>
+            </ElementIterator>
+          </FnConcatIterator>
+        </ElementIterator>
+      </flwor::ForIterator>
+      <HoistIterator>
         <CastIterator type="xs:integer">
           <FnDataIterator>
             <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,b)" typename="*" nill allowed="0" target_position="1">
@@ -30,29 +59,8 @@
             </ChildAxisIterator>
           </FnDataIterator>
         </CastIterator>
-      </TypedValueCompareIterator_INTEGER>
-    </FnBooleanIterator>
-    <flwor::ForIterator>
-      <ForVariable name="x"/>
-      <flwor::TupleSourceIterator/>
-      <ElementIterator copyInputNodes="false">
-        <SingletonIterator value="xs:QName(,,a)"/>
-        <FnConcatIterator>
-          <ElementIterator copyInputNodes="false">
-            <SingletonIterator value="xs:QName(,,b)"/>
-            <TextIterator>
-              <SingletonIterator value="xs:string(1)"/>
-            </TextIterator>
-          </ElementIterator>
-          <ElementIterator copyInputNodes="false">
-            <SingletonIterator value="xs:QName(,,b)"/>
-            <TextIterator>
-              <SingletonIterator value="xs:string(2)"/>
-            </TextIterator>
-          </ElementIterator>
-        </FnConcatIterator>
-      </ElementIterator>
-    </flwor::ForIterator>
+      </HoistIterator>
+    </flwor::LetIterator>
   </flwor::WindowIterator>
   <ElementIterator>
     <SingletonIterator value="xs:QName(,,window)"/>

=== modified file 'test/rbkt/ExpCompilerResults/IterPlan/zorba/xmark/q4.iter'
--- test/rbkt/ExpCompilerResults/IterPlan/zorba/xmark/q4.iter	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpCompilerResults/IterPlan/zorba/xmark/q4.iter	2013-05-15 07:29:31 +0000
@@ -31,6 +31,13 @@
         </ChildAxisIterator>
       </ChildAxisIterator>
     </ForVariable>
+    <LetVariable name="$$opt_temp_0" materialize="true">
+      <HoistIterator>
+        <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,bidder)" typename="*" nill allowed="0">
+          <ForVarIterator varname="b"/>
+        </ChildAxisIterator>
+      </HoistIterator>
+    </LetVariable>
     <WhereClause>
       <FnExistsIterator>
         <flwor::TupleStreamIterator>
@@ -63,9 +70,9 @@
                       <SingletonIterator value="xs:string(person20)"/>
                     </CompareIterator>
                   </flwor::WhereIterator>
-                  <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,bidder)" typename="*" nill allowed="0">
-                    <ForVarIterator varname="b"/>
-                  </ChildAxisIterator>
+                  <UnhoistIterator>
+                    <LetVarIterator varname="$$opt_temp_0"/>
+                  </UnhoistIterator>
                 </flwor::ForIterator>
                 <ChildAxisIterator test kind="match_name_test" qname="xs:QName(,,personref)" typename="*" nill allowed="0">
                   <ForVarIterator varname="$$context-item"/>

=== modified file 'test/rbkt/Queries/zorba/hashjoins/gflwor_04.xq'
--- test/rbkt/Queries/zorba/hashjoins/gflwor_04.xq	2013-02-21 16:34:45 +0000
+++ test/rbkt/Queries/zorba/hashjoins/gflwor_04.xq	2013-05-15 07:29:31 +0000
@@ -24,78 +24,87 @@
 
 (:
 
-flwor_expr (0x812cda0)
+Expression tree after optimization for main query
+flwor_expr (0x8c202b8)
 [
-  FOR (0x812bad8) a (0x812ba54)
-  [
-    concatenate/2 (0x812b9f4) [ 1, 2 ]
-  ]
-  FOR (0x812c028) x (0x812bfa4)
-  [
-    concatenate/3 (0x812bf44) [
-      elem_expr (0x812bee0) [
-        const_expr (0x812be8c) [  xs:QName(,,a) ]
-        text_expr (0x812be34) [ const_expr (0x812bde0) [  xs:string(1) ] ]
-      ]
-      elem_expr (0x812bd7c) [
-        const_expr (0x812bd28) [  xs:QName(,,a) ]
-        text_expr (0x812bcd0) [ const_expr (0x812bc7c) [  xs:string(2) ] ]
-      ]
-      elem_expr (0x812bc18) [
-        const_expr (0x812bbc4) [  xs:QName(,,a) ]
-        text_expr (0x812bb6c) [ const_expr (0x812bb18) [  xs:string(3) ] ]
-      ]
-    ]
-  ]
-  COUNT  (0x812c0ec) w (0x812c068)
-  LET (0x812c864) y (0x812c7e0)
-  [
-    flwor_expr (0x812c77c)
+  FOR (0x8c1f0c4) a (0x8c1f044)
+  [
+    concatenate#2 (0x8c1efe8) [ xs:integer(1)  xs:integer(2) ]
+  ]
+  LET (0x8c20474) $$opt_temp_0 (0x8c20398)
+  [
+    hoist#1 (0x8c20418) [ local:foo#1(0x8c1f710) [ vref(0x8c1f6c0) [ a (0x8c1f044) ] ] ]
+  ]
+  LET (0x8c20ccc) $$opt_temp_4 (0x8c20c4c)
+  [
+    create-internal-index#2 (0x8c20bf0) [
+      const_expr (0x8c2085c) [  xs:QName(,,tempIndex0) ]
+      flwor_expr (0x8c20b90)
+      [
+        FOR (0x8c20a58) $$opt_temp_2 (0x8c20958) AT $$opt_temp_3 (0x8c209d8)
+        [
+          unhoist#1 (0x8c208ac) [ vref (0x8c20908) [ $$opt_temp_0 (0x8c20398) ] ]
+        ]
+        RETURN (0x8c20b90)
+        [
+          value-index-entry-builder#2 (0x8c20b34) [
+            vref (0x8c20ae4) [ $$opt_temp_2 (0x8c20958) ]
+            vref (0x8c20a94) [ $$opt_temp_2 (0x8c20958) ]
+          ]
+        ]
+      ]
+    ]
+  ]
+  FOR (0x8c1f5d8) x (0x8c1f558)
+  [
+    concatenate#3 (0x8c1f4fc) [ <a>1</a>, <a>2</a>, <a>3</a> ]
+  ]
+  LET (0x8c20638) $$opt_temp_1 (0x8c2055c)
+  [
+    hoist#1 (0x8c205dc) [
+      cast_expr xs:integer? (0x8c1f98c) [
+        data#1 (0x8c1f930) [ vref (0x8c1f8e0) [ x (0x8c1f558) ] ]
+      ]
+    ]
+  ]
+  COUNT  (0x8c1f694) w (0x8c1f614)
+  LET (0x8c1fdb8) y (0x8c1fd38)
+  [
+    flwor_expr (0x8c1fcd8)
     [
-      FOR (0x812c314) z (0x812c290)
-      [
-        local:foo/1 (0x812c170) [ vref (0x812c11c) [ a (0x812ba54) ] ]
-      ]
-      WHERE (0x812c77c)
-      [
-        boolean/1 (0x812c698) [
-          value-equal-integer/2 (0x812c4b8) [
-            cast_expr xs:integer? (0x812c408) [
-              data/1 (0x812c3a8) [ vref (0x812c354) [ x (0x812bfa4) ] ]
-            ]
-            vref (0x812c464) [ z (0x812c290) ]
-          ]
+      FOR (0x8c1f8a4) z (0x8c1f824)
+      [
+        probe-index-point-value#2 (0x8c20d08) [
+          const_expr (0x8c2085c) [  xs:QName(,,tempIndex0) ]
+          unhoist#1 (0x8c206c4) [ vref (0x8c20674) [ $$opt_temp_1 (0x8c2055c) ] ]
         ]
       ]
-      RETURN (0x812c77c)
+      RETURN (0x8c1fcd8)
       [
-        vref (0x812c728) [ z (0x812c290) ]
+        vref (0x8c1fc88) [ z (0x8c1f824) ]
       ]
     ]
   ]
-  RETURN (0x812cda0)
+  RETURN (0x8c202b8)
   [
-    concatenate/2 (0x812cd40) [
-      elem_expr (0x812ccdc) [
-        copy nodes = 0
-        const_expr (0x812cc88) [  xs:QName(,,res) ]
-        enclosed-expr/1 (0x812cc28) [
-          concatenate/4 (0x812cbc8) [
-            vref (0x812cb74) [ x (0x812bfa4) ]
-            vref (0x812cb20) [ w (0x812c068) ]
-            count/1 (0x812cac0) [
-              vref (0x812ca6c) [ y (0x812c7e0) ]
-            ]
-            sum_integer/1 (0x812c94c) [
-              vref (0x812c8f8) [ y (0x812c7e0) ]
-            ]
+    concatenate#2 (0x8c2025c) [
+      elem_expr (0x8c201fc) [
+        copy nodes = 1
+        const_expr (0x8c201ac) [  xs:QName(,,res) ]
+        enclosed-expr#1 (0x8c20150) [
+          concatenate#4 (0x8c200f4) [
+            vref (0x8c200a4) [ x (0x8c1f558) ]
+            vref (0x8c20054) [ w (0x8c1f614) ]
+            count#1 (0x8c1fff8) [ vref (0x8c1ffa8) [ y (0x8c1fd38) ] ]
+            sum_integer#1 (0x8c1fe94) [ vref (0x8c1fe44) [ y (0x8c1fd38) ] ]
           ]
         ]
       ]
-      const_expr (0x812c8a4) [  xs:string(
+      const_expr (0x8c1fdf4) [  xs:string(
 ) ]
     ]
   ]
 ]
 
+
 :)


Follow ups