Markos Zaharioudakis has proposed merging lp:~zorba-coders/zorba/markos-scratch 
into lp:zorba.

Commit message:
Optimized the MarkExpr and EliminateFlworVariables rules of the optimizer

Requested reviews:
  Markos Zaharioudakis (markos-za)

For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/markos-scratch/+merge/130833

Optimized the MarkExpr and EliminateFlworVariables rules of the optimizer
-- 
https://code.launchpad.net/~zorba-coders/zorba/markos-scratch/+merge/130833
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'ChangeLog'
--- ChangeLog	2012-10-20 21:29:37 +0000
+++ ChangeLog	2012-10-22 15:15:32 +0000
@@ -6,6 +6,7 @@
 New Features:
 
 Optimizations:
+  * Optimized the MarkExpr and EliminateFlworVariables rules of the optimizer
 
 Bug Fixes/Other Changes:
   * Fixed mustCopyInputNodes() method of no-copy, and jsoniq functions.

=== modified file 'src/compiler/expression/expr.cpp'
--- src/compiler/expression/expr.cpp	2012-10-10 13:05:50 +0000
+++ src/compiler/expression/expr.cpp	2012-10-22 15:15:32 +0000
@@ -334,6 +334,8 @@
 {
   assert(type->get_quantifier() == TypeConstants::QUANT_ONE ||
          type->get_quantifier() == TypeConstants::QUANT_QUESTION);
+
+  setNonDiscardable(ANNOTATION_TRUE_FIXED);
 }
 
 
@@ -362,6 +364,7 @@
   theCheckPrime(check_prime),
   theQName(qname)
 {
+  setNonDiscardable(ANNOTATION_TRUE_FIXED);
 }
 
 
@@ -385,6 +388,8 @@
   assert(TypeOps::is_subtype(sctx->get_typemanager(),
                              *type,
                              *GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_STAR));
+
+  setNonDiscardable(ANNOTATION_TRUE_FIXED);
 }
 
 
@@ -494,6 +499,9 @@
   theCopyInputNodes(copyNodes)
 {
   compute_scripting_kind();
+
+  setUnfoldable(ANNOTATION_TRUE_FIXED);
+  setConstructsNodes(ANNOTATION_TRUE_FIXED);
 }
 
 
@@ -530,7 +538,12 @@
 {
   compute_scripting_kind();
 
+  // Node constructors are unfoldable because if a node constructor is inside
+  // a loop, then it will create a different xml tree every time it is invoked,
+  // even if the constructor itself is "constant" (i.e. does not reference any
+  // varialbes)
   setUnfoldable(ANNOTATION_TRUE_FIXED);
+  setConstructsNodes(ANNOTATION_TRUE_FIXED);
 }
 
 
@@ -553,6 +566,7 @@
   compute_scripting_kind();
 
   setUnfoldable(ANNOTATION_TRUE_FIXED);
+  setConstructsNodes(ANNOTATION_TRUE_FIXED);
 }
 
 
@@ -600,6 +614,7 @@
   compute_scripting_kind();
 
   setUnfoldable(ANNOTATION_TRUE_FIXED);
+  setConstructsNodes(ANNOTATION_TRUE_FIXED);
 }
 
 
@@ -658,6 +673,7 @@
   compute_scripting_kind();
 
   setUnfoldable(ANNOTATION_TRUE_FIXED);
+  setConstructsNodes(ANNOTATION_TRUE_FIXED);
 }
 
 
@@ -690,6 +706,7 @@
   compute_scripting_kind();
 
   setUnfoldable(ANNOTATION_TRUE_FIXED);
+  setConstructsNodes(ANNOTATION_TRUE_FIXED);
 }
 
 

=== modified file 'src/compiler/expression/expr_base.cpp'
--- src/compiler/expression/expr_base.cpp	2012-10-20 21:29:37 +0000
+++ src/compiler/expression/expr_base.cpp	2012-10-22 15:15:32 +0000
@@ -122,6 +122,19 @@
 /*******************************************************************************
 
 ********************************************************************************/
+expr::expr() 
+  :
+  theCCB(NULL),
+  theSctx(NULL),
+  theUDF(NULL),
+  theFlags1(0)
+{
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
 expr::expr(
     CompilerCB* ccb,
     static_context* sctx,
@@ -142,6 +155,8 @@
   // This is the default. The constructors for certain exprs set different values.
   setNonDiscardable(ANNOTATION_FALSE);
   setUnfoldable(ANNOTATION_FALSE);
+  setConstructsNodes(ANNOTATION_FALSE);
+  setDereferencesNodes(ANNOTATION_FALSE);
 }
 
 

=== modified file 'src/compiler/expression/expr_base.h'
--- src/compiler/expression/expr_base.h	2012-10-20 21:29:37 +0000
+++ src/compiler/expression/expr_base.h	2012-10-22 15:15:32 +0000
@@ -17,6 +17,8 @@
 #ifndef ZORBA_COMPILER_EXPR_BASE
 #define ZORBA_COMPILER_EXPR_BASE
 
+#include <map>
+
 #include <zorba/config.h>
 
 #include "common/shared_types.h"
@@ -27,7 +29,7 @@
 
 #include "functions/function_consts.h"
 
-#include "types/typeimpl.h"
+//#include "types/typeimpl.h"
 
 #include "context/static_context_consts.h"
 
@@ -135,7 +137,7 @@
 
   typedef substitution_t::iterator subst_iter_t;
 
-  typedef std::set<const var_expr *> FreeVars;
+  typedef std::set<var_expr *> FreeVars;
 
   typedef enum
   {
@@ -205,7 +207,7 @@
 protected:
   expr(CompilerCB*, static_context*, user_function*, const QueryLoc&, expr_kind_t);
 
-  expr() : theCCB(NULL), theSctx(NULL), theUDF(NULL), theFlags1(0) {}
+  expr();
 
 public:
   virtual ~expr();

=== modified file 'src/compiler/expression/expr_iter.cpp'
--- src/compiler/expression/expr_iter.cpp	2012-10-08 12:09:36 +0000
+++ src/compiler/expression/expr_iter.cpp	2012-10-22 15:15:32 +0000
@@ -40,7 +40,7 @@
 
 #define EXPR_ITER_BEGIN() switch (theState) { case 0:
 
-#define EXPR_ITER_END()   theCurrentChild = expr::iter_done; }
+#define EXPR_ITER_END()   theIsDone = true; }
 
 #define EXPR_ITER_NEXT(subExprHandle)                               \
 do                                                                  \
@@ -48,10 +48,7 @@
   theState = __LINE__;                                              \
   theCurrentChild = reinterpret_cast<expr**>(&(subExprHandle));     \
                                                                     \
-  if ((subExprHandle) != NULL)                                      \
-  {                                                                 \
-    return;                                                         \
-  }                                                                 \
+  return;                                                           \
                                                                     \
 case __LINE__:;                                                     \
                                                                     \
@@ -64,10 +61,7 @@
   theState = __LINE__;                                              \
   theCurrentChild = (subExprHandleP);                               \
                                                                     \
-  if (*(subExprHandleP) != NULL)                                    \
-  {                                                                 \
-    return;                                                         \
-  }                                                                 \
+  return;                                                           \
                                                                     \
 case __LINE__:;                                                     \
                                                                     \
@@ -79,7 +73,8 @@
   :
   theExpr(e),
   theCurrentChild(NULL),
-  theState(0)
+  theState(0),
+  theIsDone(false)
 {
 #ifndef ZORBA_NO_FULL_TEXT
   if (e->get_expr_kind() == ft_expr_kind)
@@ -210,12 +205,14 @@
 
   case relpath_expr_kind:
   {
-    relpath_expr* pathExpr = static_cast<relpath_expr*>(theExpr);
-
     EXPR_ITER_BEGIN();
 
-    theArgsIter = pathExpr->theSteps.begin();
-    theArgsEnd = pathExpr->theSteps.end();
+    {
+      relpath_expr* pathExpr = static_cast<relpath_expr*>(theExpr);
+      theArgsIter = pathExpr->theSteps.begin();
+      theArgsEnd = pathExpr->theSteps.end();
+    }
+
     for (; theArgsIter != theArgsEnd; ++theArgsIter)
     {
       EXPR_ITER_NEXT(*theArgsIter);
@@ -239,15 +236,13 @@
 
   case match_expr_kind:
   {
-    EXPR_ITER_BEGIN();
-    EXPR_ITER_END();
+    theIsDone = true;
     break;
   }
 
   case var_expr_kind:
   {
-    EXPR_ITER_BEGIN();
-    EXPR_ITER_END();
+    theIsDone = true;
     break;
   }
 
@@ -265,8 +260,7 @@
 
   case const_expr_kind:
   {
-    EXPR_ITER_BEGIN();
-    EXPR_ITER_END();
+    theIsDone = true;
     break;
   }
 
@@ -323,7 +317,8 @@
 
     EXPR_ITER_BEGIN();
 
-    EXPR_ITER_NEXT(docExpr->theContent);
+    if (docExpr->theContent)
+      EXPR_ITER_NEXT(docExpr->theContent);
 
     EXPR_ITER_END();
     break;
@@ -336,8 +331,12 @@
     EXPR_ITER_BEGIN();
 
     EXPR_ITER_NEXT(elemExpr->theQNameExpr);
-    EXPR_ITER_NEXT(elemExpr->theAttrs);
-    EXPR_ITER_NEXT(elemExpr->theContent);
+
+    if (elemExpr->theAttrs)
+      EXPR_ITER_NEXT(elemExpr->theAttrs);
+
+    if (elemExpr->theContent)
+      EXPR_ITER_NEXT(elemExpr->theContent);
 
     EXPR_ITER_END();
     break;
@@ -350,7 +349,9 @@
     EXPR_ITER_BEGIN();
 
     EXPR_ITER_NEXT(attrExpr->theQNameExpr);
-    EXPR_ITER_NEXT(attrExpr->theValueExpr);
+
+    if (attrExpr->theValueExpr)
+      EXPR_ITER_NEXT(attrExpr->theValueExpr);
 
     EXPR_ITER_END();
     break;
@@ -388,7 +389,8 @@
 
     EXPR_ITER_BEGIN();
 
-    EXPR_ITER_NEXT(e->theContentExpr);
+    if (e->theContentExpr)
+        EXPR_ITER_NEXT(e->theContentExpr);
 
     EXPR_ITER_END();
     break;
@@ -400,7 +402,8 @@
 
     EXPR_ITER_BEGIN();
 
-    EXPR_ITER_NEXT(e->theContentExpr);
+    if (e->theContentExpr)
+        EXPR_ITER_NEXT(e->theContentExpr);
 
     EXPR_ITER_END();
     break;
@@ -638,8 +641,12 @@
   case var_decl_expr_kind:
   {
     var_decl_expr* varDeclExpr = static_cast<var_decl_expr*>(theExpr);
+
     EXPR_ITER_BEGIN();
-    EXPR_ITER_NEXT(varDeclExpr->theInitExpr);
+
+    if (varDeclExpr->theInitExpr)
+      EXPR_ITER_NEXT(varDeclExpr->theInitExpr);
+
     EXPR_ITER_END();
     break;
   }
@@ -655,8 +662,7 @@
 
   case flowctl_expr_kind:
   {
-    EXPR_ITER_BEGIN();
-    EXPR_ITER_END();
+    theIsDone = true;
     break;
   }
 
@@ -709,10 +715,12 @@
     theFTSelectionExprsEnd = theFTSelectionExprs.end();
     for (; theFTSelectionExprsIter != theFTSelectionExprsEnd; ++theFTSelectionExprsIter)
     {
-      EXPR_ITER_NEXT2(*theFTSelectionExprsIter);
+      if (**theFTSelectionExprsIter)
+        EXPR_ITER_NEXT2(*theFTSelectionExprsIter);
     }
 
-    EXPR_ITER_NEXT(ftExpr->ftignore_);
+    if (ftExpr->ftignore_)
+      EXPR_ITER_NEXT(ftExpr->ftignore_);
 
     EXPR_ITER_END();
     break;

=== modified file 'src/compiler/expression/expr_iter.h'
--- src/compiler/expression/expr_iter.h	2012-09-19 21:16:15 +0000
+++ src/compiler/expression/expr_iter.h	2012-10-22 15:15:32 +0000
@@ -37,9 +37,10 @@
 
   expr                                ** theCurrentChild;
   int                                    theState;
+  bool                                   theIsDone;
 
-  std::vector<expr*>::iterator          theArgsIter;
-  std::vector<expr*>::iterator          theArgsEnd;
+  std::vector<expr*>::iterator           theArgsIter;
+  std::vector<expr*>::iterator           theArgsEnd;
 
   flwor_expr::clause_list_t::iterator    theClausesIter;
   flwor_expr::clause_list_t::iterator    theClausesBegin;
@@ -68,7 +69,7 @@
 
   expr** operator*() const { return (theCurrentChild); }
 
-  bool done() const { return theCurrentChild == expr::iter_done; }
+  bool done() const { return theIsDone; }
 
 private:
   // comparisson forbidden; use done()

=== modified file 'src/compiler/expression/flwor_expr.cpp'
--- src/compiler/expression/flwor_expr.cpp	2012-10-10 13:05:50 +0000
+++ src/compiler/expression/flwor_expr.cpp	2012-10-22 15:15:32 +0000
@@ -1093,53 +1093,97 @@
 }
 
 
-/*******************************************************************************
-  Put in the given vector the var_exprs for the variables defined by this flwor
-  expr.
-********************************************************************************/
-void flwor_expr::get_vars_defined(std::vector<var_expr*>& varExprs) const
+/*****************************************************************************
+  Returns a set containing all the variables defined by the clauses of this
+  flwor expr.
+******************************************************************************/
+void flwor_expr::get_vars(expr::FreeVars& vars) const
 {
-  csize numClauses = theClauses.size();
+  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)
-    {
-      const for_clause* fc = static_cast<const for_clause *>(c);
-
-      varExprs.push_back(fc->get_var());
-
-      if (fc->get_pos_var())
-        varExprs.push_back(fc->get_pos_var());
-    }
-    else if (c->get_kind() == flwor_clause::let_clause)
-    {
-      const let_clause* lc = static_cast<const let_clause *>(c);
-
-      varExprs.push_back(lc->get_var());
-    }
-    else if (c->get_kind() == flwor_clause::window_clause)
-    {
-      const window_clause* wc = static_cast<const window_clause *>(c);
-
-      varExprs.push_back(wc->get_var());
-
-      const flwor_wincond* startCond = wc->get_win_start();
-      const flwor_wincond* stopCond = wc->get_win_stop();
-      const flwor_wincond::vars& startVars = startCond->get_out_vars();
-      const flwor_wincond::vars& stopVars = stopCond->get_out_vars();
-
-      if (startVars.posvar) varExprs.push_back(startVars.posvar);
-      if (startVars.curr) varExprs.push_back(startVars.curr);
-      if (startVars.prev) varExprs.push_back(startVars.prev);
-      if (startVars.next) varExprs.push_back(startVars.next);
-
-      if (stopVars.posvar) varExprs.push_back(stopVars.posvar);
-      if (stopVars.curr) varExprs.push_back(stopVars.curr);
-      if (stopVars.prev) varExprs.push_back(stopVars.prev);
-      if (stopVars.next) varExprs.push_back(stopVars.next);
+    const flwor_clause& c = *get_clause(i);
+
+    switch (c.get_kind())
+    {
+    case flwor_clause::for_clause:
+    {
+      const for_clause* fc = static_cast<const for_clause *>(&c);
+
+      vars.insert(fc->get_var());
+
+      if (fc->get_pos_var() != NULL)
+        vars.insert(fc->get_pos_var());
+
+      break;
+    }
+    case flwor_clause::let_clause:
+    {
+      const let_clause* lc = static_cast<const let_clause *>(&c);
+      vars.insert(lc->get_var());
+      break;
+    }
+    case flwor_clause::window_clause:
+    {
+      const window_clause* wc = static_cast<const window_clause *>(&c);
+
+      vars.insert(wc->get_var());
+
+      if (wc->get_win_start() != NULL)
+      {
+        const flwor_wincond* cond = wc->get_win_start();
+        const flwor_wincond::vars& condvars = cond->get_out_vars();
+
+        if (condvars.posvar != NULL) vars.insert(condvars.posvar);
+        if (condvars.curr != NULL) vars.insert(condvars.curr);
+        if (condvars.prev != NULL) vars.insert(condvars.prev);
+        if (condvars.next != NULL) vars.insert(condvars.next);
+      }
+
+      if (wc->get_win_stop() != NULL)
+      {
+        const flwor_wincond* cond = wc->get_win_stop();
+        const flwor_wincond::vars& condvars = cond->get_out_vars();
+
+        if (condvars.posvar != NULL) vars.insert(condvars.posvar);
+        if (condvars.curr != NULL) vars.insert(condvars.curr);
+        if (condvars.prev != NULL) vars.insert(condvars.prev);
+        if (condvars.next != NULL) vars.insert(condvars.next);
+      }
+
+      break;
+    }
+    case flwor_clause::group_clause:
+    {
+      const group_clause* gc = static_cast<const group_clause *>(&c);
+
+      flwor_clause::rebind_list_t::const_iterator ite = gc->beginGroupVars();
+      flwor_clause::rebind_list_t::const_iterator end = gc->endGroupVars();
+
+      for (; ite != end; ++ite)
+      {
+        vars.insert((*ite).second);
+      }
+
+      ite = gc->beginNonGroupVars();
+      end = gc->endNonGroupVars();
+
+      for (; ite != end; ++ite)
+      {
+        vars.insert((*ite).second);
+      }
+
+      break;
+    }
+    case flwor_clause::count_clause:
+    {
+      const count_clause* cc = static_cast<const count_clause *>(&c);
+      vars.insert(cc->get_var());
+      break;
+    }
+    default:
+      break;
     }
   }
 }

=== modified file 'src/compiler/expression/flwor_expr.h'
--- src/compiler/expression/flwor_expr.h	2012-10-16 13:08:12 +0000
+++ src/compiler/expression/flwor_expr.h	2012-10-22 15:15:32 +0000
@@ -722,7 +722,7 @@
 
   long defines_variable(const var_expr* v) const;
 
-  void get_vars_defined(std::vector<var_expr*>& varExprs) const;
+  void get_vars(expr::FreeVars& vars) const;
 
   // The following 5 methods are for the simple flwor only. They should be
   // removed eventually.

=== modified file 'src/compiler/expression/update_exprs.cpp'
--- src/compiler/expression/update_exprs.cpp	2012-10-09 14:06:08 +0000
+++ src/compiler/expression/update_exprs.cpp	2012-10-22 15:15:32 +0000
@@ -52,6 +52,8 @@
   theSourceExpr(sourceExpr)
 {
   compute_scripting_kind();
+
+  setUnfoldable(ANNOTATION_TRUE_FIXED);
 }
 
 

=== modified file 'src/compiler/rewriter/rules/flwor_rules.cpp'
--- src/compiler/rewriter/rules/flwor_rules.cpp	2012-10-20 21:29:37 +0000
+++ src/compiler/rewriter/rules/flwor_rules.cpp	2012-10-22 15:15:32 +0000
@@ -40,13 +40,14 @@
 namespace zorba
 {
 
-static void 
-collect_flw_vars(const flwor_expr&, expr::FreeVars&);
-
 static bool is_trivial_expr(const expr*);
 
 static bool 
-safe_to_fold_single_use(var_expr*, TypeConstants::quantifier_t, const flwor_expr&);
+safe_to_fold_single_use(
+    var_expr*,
+    TypeConstants::quantifier_t,
+    const flwor_expr&,
+    const std::vector<const expr*>&);
 
 static bool 
 var_in_try_or_loop(const var_expr*, const expr*, bool, bool, bool&);
@@ -89,12 +90,12 @@
 class SubstVars : public PrePostRewriteRule
 {
 protected:
-  const var_expr     * theVarExpr;
+  var_expr           * theVarExpr;
   expr               * theSubstExpr;
   std::vector<expr*>   thePath;
 
 public:
-  SubstVars(const var_expr* var, expr* subst)
+  SubstVars(var_expr* var, expr* subst)
     :
     PrePostRewriteRule(RewriteRule::SubstVars, "SubstVars"),
     theVarExpr(var),
@@ -146,7 +147,7 @@
 expr* subst_vars(
     const RewriterContext& rCtx0,
     expr* root,
-    const var_expr* var,
+    var_expr* var,
     expr* subst)
 {
   RewriterContext rCtx(rCtx0.getCompilerCB(),
@@ -242,7 +243,7 @@
         const expr::FreeVars& whereVars = whereExpr->getFreeVars();
 
         if (myVars.empty())
-          collect_flw_vars(flwor, myVars);
+          flwor.get_vars(myVars);
 
         expr::FreeVars diff;
         std::set_intersection(myVars.begin(),
@@ -252,7 +253,7 @@
                               std::inserter(diff, diff.begin()));
         if (diff.empty())
         {
-          flwor.remove_where_clause();
+          flwor.remove_clause(i);
 
           if_expr* ifExpr = rCtx.theEM->
           create_if_expr(sctx,
@@ -294,7 +295,7 @@
       for(; ite != end; ++ite)
       {
         var_expr* var = ite->second;
-        int uses = expr_tools::count_variable_uses(&flwor, var, 2);
+        int uses = expr_tools::count_variable_uses(&flwor, var, 1, NULL);
 
         if (uses == 0 && !ite->first->isNonDiscardable())
         {
@@ -313,10 +314,10 @@
       var_expr* var = fc->get_var();
       TypeConstants::quantifier_t domainQuant = domainType->get_quantifier();
       ulong domainCount = domainType->max_card();
-      const var_expr* pvar = fc->get_pos_var();
+      var_expr* pvar = fc->get_pos_var();
 
       if (pvar != NULL &&
-          expr_tools::count_variable_uses(&flwor, pvar, 1) == 0)
+          expr_tools::count_variable_uses(&flwor, pvar, 1, NULL) == 0)
       {
         fc->set_pos_var(NULL);
         pvar = NULL;
@@ -367,7 +368,8 @@
           }
         }
 
-        int uses = expr_tools::count_variable_uses(&flwor, var, 2);
+        std::vector<const expr*> refpath(16);
+        int uses = expr_tools::count_variable_uses(&flwor, var, 2, &refpath);
 
         if (uses > 1 &&
             is_trivial_expr(domainExpr) &&
@@ -381,7 +383,7 @@
                  (domainQuant == TypeConstants::QUANT_ONE || i == numClauses -1) &&
                  ((is_trivial_expr(domainExpr) &&
                    domainQuant == TypeConstants::QUANT_ONE) ||
-                  safe_to_fold_single_use(var, domainQuant, flwor)))
+                  safe_to_fold_single_use(var, domainQuant, flwor, refpath)))
         {
           subst_vars(rCtx, node, var, domainExpr);
           substitute = true;
@@ -416,7 +418,8 @@
       if (domainExpr->is_sequential())
         continue;
 
-      int uses = expr_tools::count_variable_uses(&flwor, var, 2);
+      std::vector<const expr*> refpath(16);
+      int uses = expr_tools::count_variable_uses(&flwor, var, 2, &refpath);
 
       if (uses > 1 && is_trivial_expr(domainExpr))
       {
@@ -425,7 +428,7 @@
       }
       else if (uses == 1 &&
                (is_trivial_expr(domainExpr) ||
-                safe_to_fold_single_use(var, TypeConstants::QUANT_ONE, flwor)))
+                safe_to_fold_single_use(var, TypeConstants::QUANT_ONE, flwor, refpath)))
       {
         subst_vars(rCtx, node, var, domainExpr);
         substitute = true;
@@ -606,100 +609,6 @@
 }
 
 
-/*****************************************************************************
-  Returns a set containing all the variables defined by the clauses of a flwor
-  expr.
-******************************************************************************/
-static void collect_flw_vars(const flwor_expr& flwor, expr::FreeVars& vars)
-{
-  for (csize i = 0; i < flwor.num_clauses(); ++i)
-  {
-    const flwor_clause& c = *flwor.get_clause(i);
-
-    switch (c.get_kind())
-    {
-    case flwor_clause::for_clause:
-    {
-      const for_clause* fc = static_cast<const for_clause *>(&c);
-
-      vars.insert(fc->get_var());
-
-      if (fc->get_pos_var() != NULL)
-        vars.insert(fc->get_pos_var());
-
-      break;
-    }
-    case flwor_clause::let_clause:
-    {
-      const let_clause* lc = static_cast<const let_clause *>(&c);
-      vars.insert(lc->get_var());
-      break;
-    }
-    case flwor_clause::window_clause:
-    {
-      const window_clause* wc = static_cast<const window_clause *>(&c);
-
-      vars.insert(wc->get_var());
-
-      if (wc->get_win_start() != NULL)
-      {
-        const flwor_wincond* cond = wc->get_win_start();
-        const flwor_wincond::vars& condvars = cond->get_out_vars();
-
-        if (condvars.posvar != NULL) vars.insert(condvars.posvar);
-        if (condvars.curr != NULL) vars.insert(condvars.curr);
-        if (condvars.prev != NULL) vars.insert(condvars.prev);
-        if (condvars.next != NULL) vars.insert(condvars.next);
-      }
-
-      if (wc->get_win_stop() != NULL)
-      {
-        const flwor_wincond* cond = wc->get_win_stop();
-        const flwor_wincond::vars& condvars = cond->get_out_vars();
-
-        if (condvars.posvar != NULL) vars.insert(condvars.posvar);
-        if (condvars.curr != NULL) vars.insert(condvars.curr);
-        if (condvars.prev != NULL) vars.insert(condvars.prev);
-        if (condvars.next != NULL) vars.insert(condvars.next);
-      }
-
-      break;
-    }
-    case flwor_clause::group_clause:
-    {
-      const group_clause* gc = static_cast<const group_clause *>(&c);
-
-      flwor_clause::rebind_list_t::const_iterator ite = gc->beginGroupVars();
-      flwor_clause::rebind_list_t::const_iterator end = gc->endGroupVars();
-
-      for (; ite != end; ++ite)
-      {
-        vars.insert((*ite).second);
-      }
-
-      ite = gc->beginNonGroupVars();
-      end = gc->endNonGroupVars();
-
-      for (; ite != end; ++ite)
-      {
-        vars.insert((*ite).second);
-      }
-
-      break;
-    }
-    case flwor_clause::count_clause:
-    {
-      const count_clause* cc = static_cast<const count_clause *>(&c);
-      vars.insert(cc->get_var());
-      break;
-    }
-    default:
-      break;
-    }
-  }
-}
-
-
 /******************************************************************************
 
 ******************************************************************************/
@@ -749,7 +658,8 @@
 static bool safe_to_fold_single_use(
     var_expr* var,
     TypeConstants::quantifier_t varQuant,
-    const flwor_expr& flwor)
+    const flwor_expr& flwor,
+    const std::vector<const expr*>& refpath)
 {
   TypeManager* tm = var->get_type_manager();
 
@@ -758,9 +668,6 @@
 
   bool declared = false;
   expr* referencingExpr = NULL;
-
-  //bool hasNodeConstr = var->get_domain_expr()->contains_node_construction();
-
   csize numClauses = flwor.num_clauses();
 
   for (csize i = 0; i < numClauses && referencingExpr == NULL; ++i)
@@ -789,7 +696,7 @@
         return false;
 
       // If X is referenced in the current FOR clause .....
-      if (expr_tools::count_variable_uses(domExpr, var, 1) == 1)
+      if (std::find(refpath.begin(), refpath.end(), domExpr) != refpath.end())
       {
         referencingExpr = domExpr;
         break;
@@ -815,7 +722,7 @@
 
       assert(varQuant == TypeConstants::QUANT_ONE);
 
-      if (expr_tools::count_variable_uses(clause->get_expr(), var, 1) == 1)
+      if (std::find(refpath.begin(), refpath.end(), clause->get_expr()) != refpath.end())
       {
         referencingExpr = clause->get_expr();
         break;
@@ -837,7 +744,7 @@
 
       for (; ite != end; ++ite)
       {
-        if (expr_tools::count_variable_uses(*ite, var, 1) == 1)
+        if (std::find(refpath.begin(), refpath.end(), *ite) != refpath.end())
         {
           referencingExpr = *ite;
           break;
@@ -861,7 +768,7 @@
       for (; ite != end; ++ite)
       {
         expr* inputExpr = ite->first;
-        if (expr_tools::count_variable_uses(inputExpr, var, 1) == 1)
+        if (std::find(refpath.begin(), refpath.end(), inputExpr) != refpath.end())
         {
           referencingExpr = inputExpr;
           break;
@@ -874,7 +781,7 @@
       for (; ite != end; ++ite)
       {
         expr* inputExpr = ite->first;
-        if (expr_tools::count_variable_uses(inputExpr, var, 1) == 1)
+        if (std::find(refpath.begin(), refpath.end(), inputExpr) != refpath.end())
         {
           referencingExpr = inputExpr;
           break;
@@ -900,7 +807,7 @@
       if (domExpr->is_sequential())
         return false;
 
-      if (expr_tools::count_variable_uses(domExpr, var, 1) == 1)
+      if (std::find(refpath.begin(), refpath.end(), domExpr) != refpath.end())
       {
         referencingExpr = domExpr;
         break;
@@ -909,13 +816,13 @@
       if (domExpr->get_return_type()->max_card() > 1)
         return false;
 
-      if (expr_tools::count_variable_uses(startExpr, var, 1) == 1)
+      if (std::find(refpath.begin(), refpath.end(), startExpr) != refpath.end())
       {
         referencingExpr = domExpr;
         break;
       }
 
-      if (expr_tools::count_variable_uses(stopExpr, var, 1) == 1)
+      if (std::find(refpath.begin(), refpath.end(), stopExpr) != refpath.end())
       {
         referencingExpr = domExpr;
         break;
@@ -945,7 +852,7 @@
     if (retExpr->is_sequential())
       return false;
 
-    if (expr_tools::count_variable_uses(retExpr, var, 1) == 1)
+    if (std::find(refpath.begin(), refpath.end(), retExpr) != refpath.end())
     {
       if (varQuant != TypeConstants::QUANT_ONE)
       {
@@ -1435,7 +1342,7 @@
           expr* arg = andExpr->get_arg(i);
 
           if (is_positional_pred(flwor, clausePos, arg, posVar, posExpr, compKind) &&
-              expr_tools::count_variable_uses(flwor, posVar, 2) <= 1)
+              expr_tools::count_variable_uses(flwor, posVar, 2, NULL) <= 1)
           {
             rewrite_positional_pred(rCtx, flwor, posVar, posExpr, compKind);
 
@@ -1457,7 +1364,7 @@
       else
       {
         if (is_positional_pred(flwor, clausePos, whereExpr, posVar, posExpr, compKind) &&
-            expr_tools::count_variable_uses(flwor, posVar, 2) <= 1)
+            expr_tools::count_variable_uses(flwor, posVar, 2, NULL) <= 1)
         {
           rewrite_positional_pred(rCtx, flwor, posVar, posExpr, compKind);
 

=== modified file 'src/compiler/rewriter/rules/fold_rules.cpp'
--- src/compiler/rewriter/rules/fold_rules.cpp	2012-10-20 21:29:37 +0000
+++ src/compiler/rewriter/rules/fold_rules.cpp	2012-10-22 15:15:32 +0000
@@ -236,194 +236,75 @@
     iter.next();
   }
 
-  // Certain exprs are nondiscardable independently from their children.
-  if (saveNonDiscardable != ANNOTATION_TRUE_FIXED)
-  {
-    if (node->is_sequential())
-    {
-      curNonDiscardable = ANNOTATION_TRUE_FIXED;
-    }
-    else
-    {
-      switch (node->get_expr_kind())
-      {
-      case fo_expr_kind:
-      {
-        fo_expr* fo = static_cast<fo_expr *>(node);
-        function* f = fo->get_func();
-
-        bool isErrorFunc = (dynamic_cast<const fn_error*>(f) != NULL);
-
-        if (f->getKind() == FunctionConsts::FN_TRACE_2 ||
-            isErrorFunc)
+  if (node->is_sequential())
+  {
+    curNonDiscardable = ANNOTATION_TRUE_FIXED;
+    curUnfoldable = ANNOTATION_TRUE_FIXED;
+  }
+  else
+  {
+    switch (node->get_expr_kind())
+    {
+    case fo_expr_kind:
+    {
+      fo_expr* fo = static_cast<fo_expr *>(node);
+      function* f = fo->get_func();
+        
+      if (!f->isUdf())
+      {
+        if (FunctionConsts::FN_ERROR_0 <= f->getKind() &&
+            f->getKind() <= FunctionConsts::FN_TRACE_2)
         {
           curNonDiscardable = ANNOTATION_TRUE_FIXED;
-        }
-
-        break;
-      }
-
-      case cast_expr_kind:
-      case treat_expr_kind:
-      case promote_expr_kind:
-      {
-        curNonDiscardable = ANNOTATION_TRUE_FIXED;
-        break;
-      }
-
-      default:
-      {
-        break;
-      }
-      }
-    }
-  }
-
-  // Certain exprs are unfoldable independently from their children
-  if (saveUnfoldable != ANNOTATION_TRUE_FIXED)
-  {
-    if (node->is_sequential())
-    {
-      curUnfoldable = ANNOTATION_TRUE_FIXED;
-    }
-    else
-    {
-      switch (node->get_expr_kind())
-      {
-      case fo_expr_kind:
-      {
-        fo_expr* fo = static_cast<fo_expr *>(node);
-        function* f = fo->get_func();
-
-        if (f->isUdf() && theIsLocal)
-        {
-          curUnfoldable = saveUnfoldable;
-        }
-        else
-        {
-          bool isErrorFunc = (dynamic_cast<const fn_error*>(f) != NULL);
-
-          // Do not fold functions that always require access to the dynamic context,
-          // or may need to access the implicit timezone (which is also in the dynamic
-          // constext).
-          if (isErrorFunc ||
-              f->accessesDynCtx() ||
-              maybe_needs_implicit_timezone(fo) ||
-              !f->isDeterministic())
-          {
-            curUnfoldable = ANNOTATION_TRUE_FIXED;
-          }
-        }
-
-        break;
-      }
-
-      case var_expr_kind:
-      {
-        var_expr::var_kind varKind = static_cast<var_expr *>(node)->get_kind();
-
-        if (varKind == var_expr::prolog_var || varKind == var_expr::local_var)
           curUnfoldable = ANNOTATION_TRUE_FIXED;
-
-        break;
-      }
-
-      // Node constructors are unfoldable because if a node constructor is inside
-      // a loop, then it will create a different xml tree every time it is invoked,
-      // even if the constructor itself is "constant" (i.e. does not reference any
-      // varialbes)
-      case elem_expr_kind:
-      case attr_expr_kind:
-      case text_expr_kind:
-      case pi_expr_kind:
-      case doc_expr_kind:
-      {
-        curUnfoldable = ANNOTATION_TRUE_FIXED;
-        break;
-      }
-
-      case delete_expr_kind:
-      case insert_expr_kind:
-      case rename_expr_kind:
-      case replace_expr_kind:
-      {
-        curUnfoldable = ANNOTATION_TRUE_FIXED;
-        break;
-      }
-
-      default:
-      {
-        break;
-      }
-      }
-    }
-  }
-
-  if (saveDereferencesNodes != ANNOTATION_TRUE_FIXED)
-  {
-    switch (node->get_expr_kind())
-    {
-    case fo_expr_kind:
-    {
-      fo_expr* fo = static_cast<fo_expr *>(node);
-      function* f = fo->get_func();
-
-      if (!f->isUdf())
-      {
-        if (f->getKind() == FunctionConsts::FN_ZORBA_REF_NODE_BY_REFERENCE_1)
+        }
+        else if (f->getKind() == FunctionConsts::FN_ZORBA_REF_NODE_BY_REFERENCE_1)
+        {
           curDereferencesNodes = ANNOTATION_TRUE;
+        }
+
+        // Do not fold functions that always require access to the dynamic context,
+        // or may need to access the implicit timezone (which is also in the dynamic
+        // constext).
+        if (saveUnfoldable != ANNOTATION_TRUE_FIXED &&
+            (f->accessesDynCtx() ||
+             maybe_needs_implicit_timezone(fo) ||
+             !f->isDeterministic()))
+        {
+          curUnfoldable = ANNOTATION_TRUE_FIXED;
+        }
       }
       else if (theIsLocal)
       {
+        curUnfoldable = saveUnfoldable;
         curDereferencesNodes = saveDereferencesNodes;
-      }
-      else if (static_cast<user_function*>(f)->dereferencesNodes())
-      {
-        curDereferencesNodes = ANNOTATION_TRUE;
-      }
-      
-      break;
-    }
-    
-    default:
-    {
-      break;
-    }
-    }
-  }
-
-  if (saveConstructsNodes != ANNOTATION_TRUE_FIXED)
-  {
-    switch (node->get_expr_kind())
-    {
-    case fo_expr_kind:
-    {
-      fo_expr* fo = static_cast<fo_expr *>(node);
-      function* f = fo->get_func();
-
-      if (f->isUdf() && theIsLocal)
-      {
         curConstructsNodes = saveConstructsNodes;
       }
       else
       {
-        if (f->isUdf() &&
-            static_cast<user_function*>(f)->constructsNodes())
+        if (saveUnfoldable != ANNOTATION_TRUE_FIXED &&
+            (f->accessesDynCtx() || !f->isDeterministic()))
         {
+          curUnfoldable = ANNOTATION_TRUE_FIXED;
+        }
+
+        if (static_cast<user_function*>(f)->dereferencesNodes())
+          curDereferencesNodes = ANNOTATION_TRUE;
+
+        if (static_cast<user_function*>(f)->constructsNodes())
           curConstructsNodes = ANNOTATION_TRUE;
-        }
       }
       
       break;
     }
     
-    case elem_expr_kind:
-    case attr_expr_kind:
-    case text_expr_kind:
-    case pi_expr_kind:
-    case doc_expr_kind:
+    case var_expr_kind:
     {
-      curConstructsNodes = ANNOTATION_TRUE_FIXED;
+      var_expr::var_kind varKind = static_cast<var_expr *>(node)->get_kind();
+        
+      if (varKind == var_expr::prolog_var || varKind == var_expr::local_var)
+        curUnfoldable = ANNOTATION_TRUE_FIXED;
+    
       break;
     }
 
@@ -493,7 +374,7 @@
              fkind == FunctionConsts::FN_MIN_2 ||
              fkind == FunctionConsts::FN_MAX_1 ||
              fkind == FunctionConsts::FN_MAX_2)
-            && TypeOps::maybe_date_time(tm, *TypeOps::prime_type(tm, *type0))) );
+            && TypeOps::maybe_date_time(tm, *type0)) );
 }
 
 

=== modified file 'src/compiler/rewriter/tools/expr_tools.cpp'
--- src/compiler/rewriter/tools/expr_tools.cpp	2012-10-08 12:09:36 +0000
+++ src/compiler/rewriter/tools/expr_tools.cpp	2012-10-22 15:15:32 +0000
@@ -48,10 +48,11 @@
 /*******************************************************************************
 
 ********************************************************************************/
-bool count_variable_uses_rec(
+bool count_var_uses_rec(
     const expr* e,
     const var_expr* var,
     int limit,
+    std::vector<const expr*>* path,
     int& count)
 {
   if (limit > 0 && count >= limit)
@@ -59,6 +60,11 @@
     return false;
   }
 
+  if (path && count == 0)
+  {
+    path->push_back(e);
+  }
+
   if (e == var)
   {
     ++count;
@@ -69,21 +75,29 @@
   {
     const if_expr* ifExpr = static_cast<const if_expr*>(e);
 
+    if (!count_var_uses_rec(ifExpr->get_cond_expr(), var, limit, path, count))
+    {
+      assert(count > 0);
+      return false;
+    }
+
     int thenCount = 0;
+    std::vector<const expr*>* thenPath = (count == 0 ? path : NULL);
+
+    if (!count_var_uses_rec(ifExpr->get_then_expr(), var, limit, thenPath, thenCount))
+    {
+      count = thenCount;
+      assert(count > 0);
+      return false;
+    }
+
     int elseCount = 0;
-
-    if (!count_variable_uses_rec(ifExpr->get_cond_expr(), var, limit, count))
-        return false;
-
-    if (!count_variable_uses_rec(ifExpr->get_then_expr(), var, limit, thenCount))
-    {
-      count = thenCount;
-      return false;
-    }
-
-    if (!count_variable_uses_rec(ifExpr->get_else_expr(), var, limit, elseCount))
+    std::vector<const expr*>* elsePath = (count == 0 ? path : NULL);
+
+    if (!count_var_uses_rec(ifExpr->get_else_expr(), var, limit, elsePath, elseCount))
     {
       count = elseCount;
+      assert(count > 0);
       return false;
     }
 
@@ -94,13 +108,21 @@
     ExprConstIterator iter(e);
     while (!iter.done())
     {
-      if (!count_variable_uses_rec(iter.get_expr(), var, limit, count))
+      if (!count_var_uses_rec(iter.get_expr(), var, limit, path, count))
+      {
+        assert(count > 0);
         return false;
+      }
 
       iter.next();
     }
   }
 
+  if (path && count == 0)
+  {
+    path->pop_back();
+  }
+
   return true;
 }
 
@@ -108,11 +130,15 @@
 /*******************************************************************************
 
 ********************************************************************************/
-int count_variable_uses(const expr* root, const var_expr* var, int limit = 0)
+int count_variable_uses(
+    const expr* root,
+    const var_expr* var,
+    int limit,
+    std::vector<const expr*>* path)
 {
   int count = 0;
 
-  count_variable_uses_rec(root, var, limit, count);
+  count_var_uses_rec(root, var, limit, path, count);
 
   return count;
 }

=== modified file 'src/compiler/rewriter/tools/expr_tools.h'
--- src/compiler/rewriter/tools/expr_tools.h	2012-10-08 12:09:36 +0000
+++ src/compiler/rewriter/tools/expr_tools.h	2012-10-22 15:15:32 +0000
@@ -46,7 +46,11 @@
 namespace expr_tools
 {
 
-int count_variable_uses(const expr* root, const var_expr* var, int limit);
+int count_variable_uses(
+    const expr* root,
+    const var_expr* var,
+    int limit,
+    std::vector<const expr*>* path);
 
 
 /*******************************************************************************

=== modified file 'src/compiler/translator/translator.cpp'
--- src/compiler/translator/translator.cpp	2012-10-10 13:05:50 +0000
+++ src/compiler/translator/translator.cpp	2012-10-22 15:15:32 +0000
@@ -9926,12 +9926,12 @@
     var_expr* posVar = dotClause->get_pos_var();
     var_expr* dotVar = dotClause->get_var();
 
-    if (expr_tools::count_variable_uses(predExpr, posVar, 1) == 0 &&
-        expr_tools::count_variable_uses(predExpr, dotVar, 1) == 0)
+    if (expr_tools::count_variable_uses(predExpr, posVar, 1, NULL) == 0 &&
+        expr_tools::count_variable_uses(predExpr, dotVar, 1, NULL) == 0)
     {
       flworExpr->remove_clause(2);
 
-      if (expr_tools::count_variable_uses(predExpr, sizeVar, 1) == 0)
+      if (expr_tools::count_variable_uses(predExpr, sizeVar, 1, NULL) == 0)
       {
         expr* sourceExpr = sourceClause->get_expr();
 

=== modified file 'src/compiler/xqddf/value_index.cpp'
--- src/compiler/xqddf/value_index.cpp	2012-10-10 13:05:50 +0000
+++ src/compiler/xqddf/value_index.cpp	2012-10-22 15:15:32 +0000
@@ -284,7 +284,7 @@
   if (var)
     dotVar = var->getVar();
 
-  std::vector<var_expr*> varExprs;
+  expr::FreeVars varExprs;
 
   // Check constraints on the domain expr
   analyzeExprInternal(getDomainExpr(),
@@ -365,7 +365,7 @@
     expr* e,
     std::vector<store::Item*>& sourceNames,
     std::vector<expr*>& sourceExprs,
-    std::vector<var_expr*>& varExprs,
+    FreeVars& varExprs,
     expr* dotVar)
 {
   if (e->get_expr_kind() == fo_expr_kind)
@@ -411,12 +411,12 @@
 
     ZORBA_ASSERT(varExpr->get_kind() == var_expr::local_var);
 
-    varExprs.push_back(varExpr);
+    varExprs.insert(varExpr);
   }
   else if (e->get_expr_kind() == flwor_expr_kind ||
            e->get_expr_kind() == gflwor_expr_kind)
   {
-    static_cast<const flwor_expr*>(e)->get_vars_defined(varExprs);
+    static_cast<const flwor_expr*>(e)->get_vars(varExprs);
   }
   else if (e->get_expr_kind() == var_expr_kind)
   {
@@ -427,7 +427,7 @@
     }
 
     if (e != getDomainVariable() &&
-        std::find(varExprs.begin(), varExprs.end(), e) == varExprs.end())
+        varExprs.find(static_cast<var_expr*>(e)) == varExprs.end())
     {
       RAISE_ERROR(zerr::ZDST0031_INDEX_HAS_FREE_VARS,  e->get_loc(),
       ERROR_PARAMS(theName->getStringValue()));

=== modified file 'src/compiler/xqddf/value_index.h'
--- src/compiler/xqddf/value_index.h	2012-09-19 21:16:15 +0000
+++ src/compiler/xqddf/value_index.h	2012-10-22 15:15:32 +0000
@@ -234,6 +234,8 @@
 ********************************************************************************/
 class IndexDecl : public SimpleRCObject
 {
+  typedef std::set<var_expr *> FreeVars;
+
 public:
   typedef enum
   {
@@ -355,7 +357,7 @@
 
   const store::Item* getSourceName(csize i) const { return theSourceNames[i]; }
 
-  expr* getDomainSourceExpr(csize i) const { return theDomainSourceExprs[i]; }
+  const expr* getDomainSourceExpr(csize i) const { return theDomainSourceExprs[i]; }
 
   void analyze(CompilerCB* ccb);
 
@@ -370,9 +372,9 @@
 private:
   void analyzeExprInternal(
         expr* e,
-        std::vector</*const */store::Item*>& sourceNames,
+        std::vector<store::Item*>& sourceNames,
         std::vector<expr*>& sourceExprs,
-        std::vector<var_expr*>& varExprs,
+        FreeVars& varExprs,
         expr* dotVar);
 };
 

=== modified file 'src/runtime/full_text/ft_token_matcher.cpp'
--- src/runtime/full_text/ft_token_matcher.cpp	2012-09-19 21:16:15 +0000
+++ src/runtime/full_text/ft_token_matcher.cpp	2012-10-22 15:15:32 +0000
@@ -23,6 +23,8 @@
 #include "util/cxx_util.h"
 #include "util/stl_util.h"
 
+#include "system/globalenv.h"
+
 #include "ft_stop_words_set.h"
 #include "ft_token_matcher.h"
 #include "ft_util.h"

=== modified file 'src/runtime/full_text/ftcontains_visitor.cpp'
--- src/runtime/full_text/ftcontains_visitor.cpp	2012-09-19 21:16:15 +0000
+++ src/runtime/full_text/ftcontains_visitor.cpp	2012-10-22 15:15:32 +0000
@@ -24,6 +24,9 @@
 #include "compiler/parser/query_loc.h"
 #include "diagnostics/xquery_diagnostics.h"
 #include "store/api/store.h"
+
+#include "system/globalenv.h"
+
 #include "util/cxx_util.h"
 #include "util/indent.h"
 #include "util/stl_util.h"

=== modified file 'src/runtime/full_text/thesauri/wn_thesaurus.cpp'
--- src/runtime/full_text/thesauri/wn_thesaurus.cpp	2012-09-19 21:16:15 +0000
+++ src/runtime/full_text/thesauri/wn_thesaurus.cpp	2012-10-22 15:15:32 +0000
@@ -37,6 +37,8 @@
 #include "diagnostics/xquery_diagnostics.h"
 #include "zorbautils/locale.h"
 
+#include "system/globalenv.h"
+
 #include "decode_base128.h"
 #include "wn_db_segment.h"
 #include "wn_synset.h"

=== modified file 'src/runtime/full_text/thesauri/xqftts_thesaurus.cpp'
--- src/runtime/full_text/thesauri/xqftts_thesaurus.cpp	2012-09-19 21:16:15 +0000
+++ src/runtime/full_text/thesauri/xqftts_thesaurus.cpp	2012-10-22 15:15:32 +0000
@@ -34,6 +34,8 @@
 #include "diagnostics/xquery_diagnostics.h"
 #include "diagnostics/dict.h"
 
+#include "system/globalenv.h"
+
 #include "xqftts_thesaurus.h"
 
 using namespace std;

-- 
Mailing list: https://launchpad.net/~zorba-coders
Post to     : zorba-coders@lists.launchpad.net
Unsubscribe : https://launchpad.net/~zorba-coders
More help   : https://help.launchpad.net/ListHelp

Reply via email to