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

Requested reviews:
  Markos Zaharioudakis (markos-za)

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

Fixed bug #981405
-- 
https://code.launchpad.net/~zorba-coders/zorba/markos-scratch/+merge/103263
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'ChangeLog'
--- ChangeLog	2012-04-23 23:05:17 +0000
+++ ChangeLog	2012-04-24 12:07:24 +0000
@@ -32,8 +32,13 @@
   * Fixed bug #906494 (default compile with D_FILE_OFFSET_BITS=64)
   * Fixed bug #912586, #912593 and #912722 (assertion failures with lax validation)
   * Fixed bug #921458 (file:read-text-lines() blocking)
+<<<<<<< TREE
   * Fixed bug #947627 (throw XQST0099 if more than one declarations of context item
 	               type in same module)
+=======
+  * Fixed bug #981405 (do not hoist expr containing try-catch variables out of the
+          associated try-catch expression)
+>>>>>>> MERGE-SOURCE
   * Fixed bug #980526 (no-copy rule bug due to global var being set in "distant" udf)
   * Fixed bug #949910 (has-children may be invoked on all nodes). Internally, zorba::store::Item::getChildren() now returns NULL on node classes without offspring (instead of raising an error).
   * Fixed Bug #933490: Error ItemFactoryImpl::createBase64Binary with istream

=== modified file 'src/compiler/expression/expr.h'
--- src/compiler/expression/expr.h	2012-04-23 10:46:38 +0000
+++ src/compiler/expression/expr.h	2012-04-24 12:07:24 +0000
@@ -1010,7 +1010,7 @@
   
   csize clause_count() const { return theCatchClauses.size(); }
   
-  catch_clause_t const& operator[](csize i) const { return theCatchClauses[i]; }
+  const catch_clause_t& operator[](csize i) const { return theCatchClauses[i]; }
 
   void compute_scripting_kind();
 

=== modified file 'src/compiler/rewriter/rules/hoist_rules.cpp'
--- src/compiler/rewriter/rules/hoist_rules.cpp	2012-04-23 23:05:17 +0000
+++ src/compiler/rewriter/rules/hoist_rules.cpp	2012-04-24 12:07:24 +0000
@@ -43,14 +43,14 @@
     expr*,
     const VarIdMap&,
     const ExprVarsMap&,
-    struct flwor_holder*);
+    struct PathHolder*);
 
 static expr_t try_hoisting(
     RewriterContext&,
     expr*,
     const VarIdMap&,
     const ExprVarsMap&,
-    struct flwor_holder*);
+    struct PathHolder*);
 
 static bool non_hoistable (const expr*);
 
@@ -67,15 +67,17 @@
 
 
 /*******************************************************************************
-  Used to implement a stack of flwor exprs.
+  Used to implement a stack of "intersting" exprs that appear in the path from
+  the root expr to the current expr. Currently, "intersting" exprs are flwor
+  and try-catch exprs.
 ********************************************************************************/
-struct flwor_holder
+struct PathHolder
 {
-  struct flwor_holder  * prev;
-  rchandle<flwor_expr>   flwor;
-  long                   clauseCount;
+  struct PathHolder  * prev;
+  expr_t               expr;
+  long                 clauseCount;
 
-  flwor_holder() 
+  PathHolder() 
     :
     prev(NULL),
     clauseCount(0)
@@ -104,13 +106,15 @@
   DynamicBitset freeset(numVars);
   expr_tools::build_expr_to_vars_map(node, varmap, freeset, freevarMap);
 
-  struct flwor_holder root;
+  PathHolder root;
   modified = hoist_expressions(rCtx, node, varmap, freevarMap, &root);
 
-  if (modified && root.flwor != NULL)
+  if (modified && root.expr != NULL)
   {
-    root.flwor->set_return_expr(node);
-    return root.flwor.getp();
+    assert(root.expr->get_expr_kind() == flwor_expr_kind);
+
+    static_cast<flwor_expr*>(root.expr.getp())->set_return_expr(node);
+    return root.expr;
   }
 
   return node;
@@ -125,7 +129,7 @@
     expr* e,
     const VarIdMap& varmap,
     const ExprVarsMap& freevarMap,
-    struct flwor_holder* fholder)
+    struct PathHolder* path)
 {
   bool status = false;
 
@@ -133,12 +137,12 @@
   {
     flwor_expr* flwor = static_cast<flwor_expr *>(e);
 
-    struct flwor_holder curr_holder;
-    curr_holder.prev = fholder;
-    curr_holder.flwor = &*flwor;
+    PathHolder curr_holder;
+    curr_holder.prev = path;
+    curr_holder.expr = e;
 
-    ulong numForLetClauses = flwor->num_forlet_clauses();
-    ulong i = 0;
+    csize numForLetClauses = flwor->num_forlet_clauses();
+    csize i = 0;
 
     while (i < numForLetClauses)
     {
@@ -163,7 +167,7 @@
       }
       else if (domainExpr->is_sequential())
       {
-        struct flwor_holder root;
+        PathHolder root;
         bool hoisted = hoist_expressions(rCtx,
                                          domainExpr,
                                          varmap,
@@ -171,10 +175,13 @@
                                          &root);
         if (hoisted)
         {
-          if (root.flwor != NULL)
+          if (root.expr != NULL)
           {
-            root.flwor->set_return_expr(domainExpr);
-            flc->set_expr(root.flwor.getp());
+            assert(root.expr->get_expr_kind() == flwor_expr_kind);
+
+            static_cast<flwor_expr*>(root.expr.getp())->set_return_expr(domainExpr);
+
+            flc->set_expr(root.expr.getp());
           }
 
           status = true;
@@ -229,13 +236,15 @@
     }
     else if (re->is_sequential())
     {
-      struct flwor_holder root;
+      PathHolder root;
       bool nestedModified = hoist_expressions(rCtx, re, varmap, freevarMap, &root);
 
-      if (nestedModified && root.flwor != NULL)
+      if (nestedModified && root.expr != NULL)
       {
-        root.flwor->set_return_expr(re);
-        flwor->set_return_expr(root.flwor.getp());
+        assert(root.expr->get_expr_kind() == flwor_expr_kind);
+
+        static_cast<flwor_expr*>(root.expr.getp())->set_return_expr(re);
+        flwor->set_return_expr(root.expr.getp());
       }
 
       status = nestedModified || status;
@@ -246,6 +255,35 @@
     }
   }
 
+  else if (e->get_expr_kind() == trycatch_expr_kind)
+  {
+    PathHolder pathStep;
+    pathStep.prev = path;
+    pathStep.expr = e;
+
+    ExprIterator iter(e);
+
+    while(!iter.done())
+    {
+      expr* ce = &*(*iter);
+      if (ce)
+      {
+        expr_t unhoistExpr = try_hoisting(rCtx, ce, varmap, freevarMap, &pathStep);
+        if (unhoistExpr != NULL)
+        {
+          *iter = unhoistExpr.getp();
+          status = true;
+        }
+        else
+        {
+          status = hoist_expressions(rCtx, ce, varmap, freevarMap, &pathStep) || status;
+        }
+      }
+
+      iter.next();
+    }
+  }
+
   else if (e->get_expr_kind() == block_expr_kind || e->is_sequential())
   {
     ExprIterator iter(e);
@@ -257,13 +295,15 @@
       // long as they don't reference any local vars.
       expr_t ce = *iter;
 
-      struct flwor_holder root;
+      PathHolder root;
       bool nestedModified = hoist_expressions(rCtx, ce, varmap, freevarMap, &root);
 
-      if (nestedModified && root.flwor != NULL)
+      if (nestedModified && root.expr != NULL)
       {
-        root.flwor->set_return_expr(ce);
-        (*iter) = root.flwor;
+        assert(root.expr->get_expr_kind() == flwor_expr_kind);
+
+        static_cast<flwor_expr*>(root.expr.getp())->set_return_expr(ce);
+        (*iter) = root.expr;
       }
 
       status = nestedModified || status;
@@ -278,6 +318,7 @@
   {
     // do nothing
   }
+
   else
   {
     ExprIterator iter(e);
@@ -287,7 +328,7 @@
       expr* ce = &*(*iter);
       if (ce)
       {
-        expr_t unhoistExpr = try_hoisting(rCtx, ce, varmap, freevarMap, fholder);
+        expr_t unhoistExpr = try_hoisting(rCtx, ce, varmap, freevarMap, path);
         if (unhoistExpr != NULL)
         {
           *iter = unhoistExpr.getp();
@@ -295,7 +336,7 @@
         }
         else
         {
-          status = hoist_expressions(rCtx, ce, varmap, freevarMap, fholder) || status;
+          status = hoist_expressions(rCtx, ce, varmap, freevarMap, path) || status;
         }
       }
 
@@ -317,7 +358,7 @@
     expr* e,
     const VarIdMap& varmap,
     const ExprVarsMap& freevarMap,
-    struct flwor_holder* holder)
+    struct PathHolder* holder)
 {
   if (non_hoistable(e) || e->contains_node_construction())
   {
@@ -330,7 +371,7 @@
   ZORBA_ASSERT(fvme != freevarMap.end());
   const DynamicBitset& varset = fvme->second;
 
-  struct flwor_holder* h = holder;
+  PathHolder* h = holder;
 
   bool inloop = false;
   bool foundReferencedFLWORVar = false;
@@ -341,62 +382,92 @@
   // result, there is nothing to hoist. 
   while (h->prev != NULL)
   {
-    group_clause* gc = h->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();
-      ulong numGroupVars = (ulong)gvars.size();
-
-      for (ulong i = 0; i < numGroupVars; ++i)
-      {
-        if (contains_var(gvars[i].second.getp(), varmap, varset))
-          return NULL;
-      }
-
-      const flwor_clause::rebind_list_t& ngvars = gc->get_nongrouping_vars();
-      ulong numNonGroupVars = (ulong)ngvars.size();
-
-      for (ulong i = 0; i < numNonGroupVars; ++i)
-      {
-        if (contains_var(ngvars[i].second.getp(), 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 
-    // while-loop to see if e can be hoisted w.r.t. the previous (outer) flwor.
-    // If yes, then let V be the inner-most var referenced by e. If there are any
-    // FOR vars after V, e can be hoisted out of any such FOR vars. Otherwise, e
-    // cannot be hoisted.
-    for (i = h->clauseCount - 1; i >= 0; --i)
-    {
-      const forletwin_clause* flc = 
-      static_cast<const forletwin_clause*>(h->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 &&
-                 TypeOps::type_max_cnt(tm, *flc->get_expr()->get_return_type()) >= 2));
-    }
-
-    if (foundSequentialClause || foundReferencedFLWORVar)
-      break;
+    if (h->expr->get_expr_kind() == trycatch_expr_kind)
+    {
+      // Should not hoist an expr out of a try-catch if it contains any try-catch vars
+      trycatch_expr* trycatch = static_cast<trycatch_expr*>(h->expr.getp());
+      csize numClauses = trycatch->clause_count();
+
+      for (csize i = 0; i < numClauses; ++i)
+      {
+        const catch_clause_t& clause = (*trycatch)[i];
+
+        catch_clause::var_map_t& trycatchVars = clause->get_vars();
+
+        catch_clause::var_map_t::const_iterator ite = trycatchVars.begin();
+        catch_clause::var_map_t::const_iterator end = trycatchVars.end();
+        for (; ite != end; ++ite)
+        {
+          const var_expr_t& trycatchVar = (*ite).second;
+
+          if (contains_var(trycatchVar.getp(), varmap, varset))
+            return NULL;
+        } 
+      }
+    }
+    else
+    {
+      assert(h->expr->get_expr_kind() == flwor_expr_kind);
+
+      flwor_expr* flwor = static_cast<flwor_expr*>(h->expr.getp());
+ 
+      group_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.getp(), 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.getp(), 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 
+      // while-loop to see if e can be hoisted w.r.t. the previous (outer) flwor.
+      // If yes, then let V be the inner-most var referenced by e. If there are any
+      // FOR vars after V, e can be hoisted out of any such FOR vars. Otherwise, e
+      // cannot be hoisted.
+      for (i = h->clauseCount - 1; i >= 0; --i)
+      {
+        const forletwin_clause* flc = 
+        static_cast<const forletwin_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 &&
+                   TypeOps::type_max_cnt(tm, *flc->get_expr()->get_return_type()) >= 2));
+      }
+
+      if (foundSequentialClause || foundReferencedFLWORVar)
+        break;
+    }
 
     h = h->prev;
   }
@@ -427,15 +498,17 @@
 
   if (h->prev == NULL)
   {
-    if (h->flwor == NULL)
+    if (h->expr == NULL)
     {
-      h->flwor = new flwor_expr(e->get_sctx(), e->get_loc(), false);
+      h->expr = new flwor_expr(e->get_sctx(), e->get_loc(), false);
     }
-    h->flwor->add_clause(flref);
+    static_cast<flwor_expr*>(h->expr.getp())->add_clause(flref);
   }
   else
   {
-    h->flwor->add_clause(i + 1, flref);
+    assert(h->expr->get_expr_kind() == flwor_expr_kind);
+
+    static_cast<flwor_expr*>(h->expr.getp())->add_clause(i + 1, flref);
     ++h->clauseCount;
   }
 

=== modified file 'src/compiler/rewriter/tools/expr_tools.cpp'
--- src/compiler/rewriter/tools/expr_tools.cpp	2012-04-23 10:46:38 +0000
+++ src/compiler/rewriter/tools/expr_tools.cpp	2012-04-24 12:07:24 +0000
@@ -298,6 +298,31 @@
 
     index_flwor_vars(flwor->get_return_expr(), numVars, varidmap, idvarmap);
   }
+  else if (e->get_expr_kind() == trycatch_expr_kind)
+  {
+    const trycatch_expr* trycatch = static_cast<const trycatch_expr*>(e);
+
+    index_flwor_vars(trycatch->get_try_expr(), numVars, varidmap, idvarmap);
+
+    csize numClauses = trycatch->clause_count();
+
+    for (csize i = 0; i < numClauses; ++i)
+    {
+      const catch_clause_t& clause = (*trycatch)[i];
+      
+      catch_clause::var_map_t& trycatchVars = clause->get_vars();
+      
+      catch_clause::var_map_t::const_iterator ite = trycatchVars.begin();
+      catch_clause::var_map_t::const_iterator end = trycatchVars.end();
+      for (; ite != end; ++ite)
+      {
+        const var_expr_t& trycatchVar = (*ite).second;
+        add_var(trycatchVar.getp(), numVars, varidmap, idvarmap);
+      }
+
+      index_flwor_vars(trycatch->get_catch_expr(i), numVars, varidmap, idvarmap);
+    }
+  }
   else
   {
     ExprConstIterator iter(e);
@@ -378,7 +403,7 @@
     return;
   }
 
-  ulong numVars = freeset.size();
+  csize numVars = freeset.size();
 
   DynamicBitset eFreeset(numVars);
   ExprIterator iter(e);
@@ -443,17 +468,17 @@
         const group_clause* gc = static_cast<const group_clause *>(c);
 
         const flwor_clause::rebind_list_t& gvars = gc->get_grouping_vars();
-        unsigned numGroupVars = (unsigned)gvars.size();
+        csize numGroupVars = gvars.size();
 
-        for (unsigned i = 0; i < numGroupVars; ++i)
+        for (csize i = 0; i < numGroupVars; ++i)
         {
           set_bit(gvars[i].second.getp(), varmap, freeset, false);
         }
 
         const flwor_clause::rebind_list_t& ngvars = gc->get_nongrouping_vars();
-        unsigned numNonGroupVars = (unsigned)ngvars.size();
+        csize numNonGroupVars = ngvars.size();
         
-        for (unsigned i = 0; i < numNonGroupVars; ++i)
+        for (csize i = 0; i < numNonGroupVars; ++i)
         {
           set_bit(ngvars[i].second.getp(), varmap, freeset, false);
         }
@@ -466,6 +491,27 @@
       }
     }
   }
+  else if (e->get_expr_kind() == trycatch_expr_kind)
+  {
+    trycatch_expr* trycatch = static_cast<trycatch_expr*>(e);
+
+    csize numClauses = trycatch->clause_count();
+
+    for (csize i = 0; i < numClauses; ++i)
+    {
+      const catch_clause_t& clause = (*trycatch)[i];
+      
+      catch_clause::var_map_t& trycatchVars = clause->get_vars();
+      
+      catch_clause::var_map_t::const_iterator ite = trycatchVars.begin();
+      catch_clause::var_map_t::const_iterator end = trycatchVars.end();
+      for (; ite != end; ++ite)
+      {
+        const var_expr_t& trycatchVar = (*ite).second;
+        set_bit(trycatchVar.getp(), varmap, freeset, false);
+      }
+    }
+  }
 
   freevarMap[e] = freeset;
 }

=== modified file 'src/compiler/translator/translator.cpp'
--- src/compiler/translator/translator.cpp	2012-04-23 23:05:17 +0000
+++ src/compiler/translator/translator.cpp	2012-04-24 12:07:24 +0000
@@ -7238,19 +7238,25 @@
   GENV_ITEMFACTORY->createQName(lStackTrace, ZORBA_ERR_NS, "", "stack-trace");
 
   cc->add_var(catch_clause::err_code,
-      bind_var(loc, lCode.getp(), var_expr::catch_var, theRTM.QNAME_TYPE_ONE) );
+      bind_var(loc, lCode.getp(), var_expr::catch_var, theRTM.QNAME_TYPE_ONE));
+
   cc->add_var(catch_clause::err_desc,
-      bind_var(loc, lDesc.getp(), var_expr::catch_var, theRTM.STRING_TYPE_QUESTION) );
+      bind_var(loc, lDesc.getp(), var_expr::catch_var, theRTM.STRING_TYPE_QUESTION));
+
   cc->add_var(catch_clause::err_value,
-      bind_var(loc, lValue.getp(), var_expr::catch_var, theRTM.ITEM_TYPE_STAR) );
+      bind_var(loc, lValue.getp(), var_expr::catch_var, theRTM.ITEM_TYPE_STAR));
+
   cc->add_var(catch_clause::err_module,
-      bind_var(loc, lModule.getp(), var_expr::catch_var, theRTM.STRING_TYPE_QUESTION) );
+      bind_var(loc, lModule.getp(), var_expr::catch_var, theRTM.STRING_TYPE_QUESTION));
+
   cc->add_var(catch_clause::err_line_no,
-      bind_var(loc, lLineNo.getp(), var_expr::catch_var, theRTM.INTEGER_TYPE_QUESTION) );
+      bind_var(loc, lLineNo.getp(), var_expr::catch_var, theRTM.INTEGER_TYPE_QUESTION));
+
   cc->add_var(catch_clause::err_column_no,
-      bind_var(loc, lColumnNo.getp(), var_expr::catch_var, theRTM.INTEGER_TYPE_QUESTION) );
+      bind_var(loc, lColumnNo.getp(), var_expr::catch_var, theRTM.INTEGER_TYPE_QUESTION));
+
   cc->add_var(catch_clause::zerr_stack_trace,
-      bind_var(loc, lStackTrace.getp(), var_expr::catch_var, theRTM.ITEM_TYPE_QUESTION) );
+      bind_var(loc, lStackTrace.getp(), var_expr::catch_var, theRTM.ITEM_TYPE_QUESTION));
 
   tce->add_clause(cc);
 

=== added file 'test/rbkt/ExpQueryResults/zorba/optim/trycatch_hoist_01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/optim/trycatch_hoist_01.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/optim/trycatch_hoist_01.xml.res	2012-04-24 12:07:24 +0000
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+1 1 2 3 2 1 2 3 3 1 2 3

=== added file 'test/rbkt/Queries/zorba/optim/trycatch_hoist_01.xq'
--- test/rbkt/Queries/zorba/optim/trycatch_hoist_01.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/optim/trycatch_hoist_01.xq	2012-04-24 12:07:24 +0000
@@ -0,0 +1,17 @@
+
+
+import module namespace reflection = "http://www.zorba-xquery.com/modules/reflection";;
+
+import module namespace err = "http://www.w3.org/2005/xqt-errors";;
+
+for $x in (1,2,3)
+let $code := "($x cast as xs:integer, 1, 2, 3)"
+return
+  try 
+  {
+    reflection:eval($code)
+  }
+  catch err:FORG0001
+  {
+    $err:code eq $err:FORG0001
+  } 

-- 
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