← Back to team overview

zorba-coders team mailing list archive

[Merge] lp:~zorba-coders/zorba/bug-1003023 into lp:zorba

 

Markos Zaharioudakis has proposed merging lp:~zorba-coders/zorba/bug-1003023 into lp:zorba.

Requested reviews:
  Markos Zaharioudakis (markos-za)

For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/bug-1003023/+merge/108180

Fixed bug #1003023$ (optimizer problems due to common subexpression after var folding into if-then-else)
-- 
https://code.launchpad.net/~zorba-coders/zorba/bug-1003023/+merge/108180
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'ChangeLog'
--- ChangeLog	2012-05-30 00:37:00 +0000
+++ ChangeLog	2012-05-31 15:09:37 +0000
@@ -1,5 +1,10 @@
 Zorba - The XQuery Processor
 
+version 2.x
+
+  * Fixed bug #1003023$ (optimizer problems due to common subexpression after
+    var folding into if-then-else)
+	
 version 2.5
 
 New Features:

=== modified file 'src/compiler/rewriter/rules/flwor_rules.cpp'
--- src/compiler/rewriter/rules/flwor_rules.cpp	2012-05-03 12:31:51 +0000
+++ src/compiler/rewriter/rules/flwor_rules.cpp	2012-05-31 15:09:37 +0000
@@ -212,6 +212,13 @@
                           std::inserter(diff, diff.begin()));
     if (diff.empty())
     {
+      expr::FreeVars::iterator ite = whereVars.begin();
+      expr::FreeVars::iterator end = whereVars.end();
+      for (; ite != end; ++ite)
+      {
+        std::cout << "where var " << *ite << std::endl;
+      }
+
       expr_t oldWhere = whereExpr;
       flwor.remove_where_clause();
 
@@ -368,7 +375,8 @@
         let_clause_t save = lc;
         MODIFY(flwor.remove_clause(i));
         const QueryLoc& loc = var->get_loc();
-        var_expr_t fvar = new var_expr(sctx, loc, var_expr::for_var, var->get_name()); 
+        var_expr_t fvar = new var_expr(sctx, loc, var_expr::for_var, var->get_name());
+        fvar->getFreeVars().insert(fvar);
         for_clause_t fc = new for_clause(sctx, loc, fvar, domainExpr);
         flwor.add_clause(i, fc);
 

=== modified file 'src/compiler/rewriter/rules/fold_rules.cpp'
--- src/compiler/rewriter/rules/fold_rules.cpp	2012-05-03 12:31:51 +0000
+++ src/compiler/rewriter/rules/fold_rules.cpp	2012-05-31 15:09:37 +0000
@@ -430,7 +430,7 @@
 
   if (node->get_expr_kind() == var_expr_kind)
   {
-    var_expr_t v = dynamic_cast<var_expr *>(node);
+    var_expr_t v = static_cast<var_expr *>(node);
     freevars.insert(v);
   }
   else

=== modified file 'src/compiler/rewriter/rules/hoist_rules.cpp'
--- src/compiler/rewriter/rules/hoist_rules.cpp	2012-05-03 12:31:51 +0000
+++ src/compiler/rewriter/rules/hoist_rules.cpp	2012-05-31 15:09:37 +0000
@@ -590,8 +590,10 @@
 {
   if (e->get_expr_kind() == fo_expr_kind)
   {
-    return static_cast<const fo_expr *>(e)->get_func()->getKind() ==
-           FunctionConsts::OP_UNHOIST_1;
+    function* f = static_cast<const fo_expr *>(e)->get_func();
+
+    return (f->getKind() == FunctionConsts::OP_UNHOIST_1 ||
+            f->getKind() == FunctionConsts::OP_HOIST_1);
   }
   return false;
 }

=== added file 'test/rbkt/ExpCompilerResults/IterPlan/zorba/optim/hoist01.iter'
--- test/rbkt/ExpCompilerResults/IterPlan/zorba/optim/hoist01.iter	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpCompilerResults/IterPlan/zorba/optim/hoist01.iter	2012-05-31 15:09:37 +0000
@@ -0,0 +1,85 @@
+Iterator tree for const-folded expr:
+<SingletonIterator value="xs:boolean(true)"/>
+
+Iterator tree for const-folded expr:
+<OrIterator>
+  <SingletonIterator value="xs:boolean(false)"/>
+  <SingletonIterator value="xs:boolean(false)"/>
+  <SingletonIterator value="xs:boolean(false)"/>
+</OrIterator>
+
+Iterator tree for const-folded expr:
+<HoistIterator>
+  <FnBooleanIterator>
+    <IfThenElseIterator>
+      <FnBooleanIterator>
+        <FnConcatIterator/>
+      </FnBooleanIterator>
+      <FnConcatIterator/>
+      <FnConcatIterator/>
+    </IfThenElseIterator>
+  </FnBooleanIterator>
+</HoistIterator>
+
+Iterator tree for const-folded expr:
+<UnhoistIterator>
+  <SingletonIterator value="xs:boolean(false)"/>
+</UnhoistIterator>
+
+Iterator tree for const-folded expr:
+<FnConcatIterator/>
+
+Iterator tree for main query:
+<SequentialIterator>
+  <CtxVarDeclareIterator varid="2" varname="testlib:user">
+    <SingletonIterator value="xs:QName(http://www.test.ch,testlib,user)"/>
+  </CtxVarDeclareIterator>
+  <UDFunctionCallIterator>
+    <SingletonIterator value="xs:integer(0)"/>
+  </UDFunctionCallIterator>
+</SequentialIterator>
+
+Iterator tree for testlib:searchUser:
+<flwor::FLWORIterator>
+  <LetVariable name="filtered" materialize="true">
+    <IfThenElseIterator>
+      <FnBooleanIterator>
+        <LetVarIterator varname="query"/>
+      </FnBooleanIterator>
+      <FunctionTraceIterator>
+        <flwor::FLWORIterator>
+          <ForVariable name="$$dot">
+            <ZorbaCollectionIterator>
+              <PromoteIterator type="xs:QName">
+                <FnDataIterator>
+                  <CtxVarIterator varid="2" varname="testlib:user" varkind="global"/>
+                </FnDataIterator>
+              </PromoteIterator>
+            </ZorbaCollectionIterator>
+          </ForVariable>
+          <WhereClause>
+            <FnBooleanIterator>
+              <CompareIterator>
+                <PromoteIterator type="xs:anyAtomicType">
+                  <FnDataIterator>
+                    <AttributeAxisIterator test kind="match_name_test" qname="xs:QName(,,deleted)" typename="*" nill allowed="0">
+                      <ForVarIterator varname="$$dot"/>
+                    </AttributeAxisIterator>
+                  </FnDataIterator>
+                </PromoteIterator>
+                <SingletonIterator value="xs:boolean(true)"/>
+              </CompareIterator>
+            </FnBooleanIterator>
+          </WhereClause>
+          <ReturnClause>
+            <ForVarIterator varname="$$dot"/>
+          </ReturnClause>
+        </flwor::FLWORIterator>
+      </FunctionTraceIterator>
+      <FnConcatIterator/>
+    </IfThenElseIterator>
+  </LetVariable>
+  <ReturnClause>
+    <FnConcatIterator/>
+  </ReturnClause>
+</flwor::FLWORIterator>

=== added file 'test/rbkt/ExpQueryResults/zorba/optim/hoist01.xml.res'
=== added file 'test/rbkt/Queries/zorba/optim/hoist01.xq'
--- test/rbkt/Queries/zorba/optim/hoist01.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/optim/hoist01.xq	2012-05-31 15:09:37 +0000
@@ -0,0 +1,6 @@
+
+import module namespace vdbsearch = "http://www.test.ch"; at "hoist01.xqlib";
+
+
+vdbsearch:searchUser(0)
+

=== added file 'test/rbkt/Queries/zorba/optim/hoist01.xqlib'
--- test/rbkt/Queries/zorba/optim/hoist01.xqlib	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/optim/hoist01.xqlib	2012-05-31 15:09:37 +0000
@@ -0,0 +1,490 @@
+module namespace testlib = "http://www.test.ch";;
+
+import module namespace db = "http://www.zorba-xquery.com/modules/store/static/collections/dml";;
+
+declare variable $testlib:user := xs:QName("testlib:user");
+
+
+declare collection testlib:user;
+declare collection testlib:groupmember;
+
+
+declare function testlib:users() 
+{
+  db:collection($testlib:user)[not(@deleted eq true())]
+};
+
+
+declare function testlib:searchUser($query)
+{
+  let $searchbase := testlib:users()
+
+  let $filtered1 :=
+      let $country := ()
+      for $user in $searchbase
+      where ((if ($country) then () else ()))
+      return $user
+
+  let $filtered := 
+      if ($query) 
+      then $filtered1
+      else 
+        let $loginBefore := $query eq "before"
+        for $user in $filtered1
+        return $user  
+
+  return
+  ()
+};
+
+
+(:
+
+Optimizing UDF testlib:searchUser
+After MergeFLWOR :
+flwor_expr (0x830a830) 
+[
+  LET (0x83032d8) query (0x8306358)
+  [
+    var kind=ARG (0x830a898) name=query
+  ]
+  LET (0x82f9db0) filtered (0x82f98c0)
+  [
+    if_expr (0x82f9cf0) 
+    [
+      boolean/1 (0x82f9d50) [ var_ref (0x83048e8) [ query (0x8306358) ] ]
+      THEN
+        wrapper_expr (0x8304940) [
+---------------------------------------------------------------
+          flwor_expr (0x82f9670) 
+          [
+            LET (0x8304c78) country (0x8304868)
+            [
+              concatenate/0 (0x83046e8) [ ]
+            ]
+            LET (0x8306628) $$opt1 (0x82fd0d8)
+            [
+              hoist (0x82fd158) [ 
+                boolean/1 (0x8305118) [
+                  if_expr (0x8305058) [
+                    boolean/1 (0x83050b8) [ var_ref (0x8304f40) [ country (0x8304868) ]]
+                    THEN concatenate/0 (0x8304f98) []
+                    ELSE concatenate/0 (0x8304ff8) [ ]
+                  ]
+                ]
+              ]
+            ]
+            FOR (0x8304ef8) user (0x8304e20)
+            [
+              wrapper_expr (0x8304cc0) [
+                function_trace_expr (0x82fc000) [
+                  flwor_expr (0x82fc598) 
+                  [
+                    FOR (0x8306690) $$dot (0x82f5510)
+                    [
+                      collection/1 (0x830a188) [
+                        promote_expr xs:QName (0x83035b0) [
+                          data/1 (0x83067d8) [
+                            var_ref (0x82f97c8) [ testlib:user (0x830a420) ]
+                          ]
+                        ]
+                      ]
+                    ]
+                    WHERE
+                      not/1 (0x82f5068) [
+                        value-equal/2 (0x82fc810) [
+                          promote_expr xs:anyAtomicType? (0x82fc208) [
+                            data/1 (0x83037b0) [
+                              relpath_expr (0x8303810) [
+                                var_ref (0x82f45c0) [ $$dot (0x82f5510) ] /@deleted
+                              ]
+                            ]
+                          ]
+                          const_expr (0x82fc278) [ xs:boolean [ xs:boolean(true) ] ]
+                        ]
+                      ]
+                    RETURN var_ref (0x8303240) [ $$dot (0x82f5510) ]
+                  ]
+                ]
+              ]
+            ]
+            WHERE unhoist (0x82fca58) [ varref () [ $$opt1 (0x82fd0d8) ] ]
+            RETURN var_ref (0x82f9618) [ user (0x8304e20) ]
+          ]
+-----------------------------------------------------------------------
+        ]
+      ELSE
+        flwor_expr (0x82fa288) 
+        [
+          LET (0x82f9c50) loginBefore (0x82f9840)
+          [
+            value-equal/2 (0x8304a98) [
+              promote_expr xs:anyAtomicType? (0x8304b68) [
+                data/1 (0x8304af8) [
+                  var_ref (0x8304998) [ query (0x8306358) ]
+                ]
+              ]
+              const_expr (0x8304a08) [ xs:string [ xs:string(before) ] ]
+            ]
+          ]
+          FOR (0x8304810) user (0x82f9e20)
+          [
+            wrapper_expr (0x82f9c98) [
+------------------------------------------------------------------------------
+              flwor_expr (0x82f9670) 
+              [
+                LET (0x8304c78) country (0x8304868)
+                [
+                  concatenate/0 (0x83046e8) [ ]
+                ]
+                LET (0x8306628) $$opt_temp_0 (0x82fd0d8)
+                [
+                  hoist/1 (0x82fd158) [
+                    boolean/1 (0x8305118) [
+                      if_expr (0x8305058) [
+                        boolean/1 (0x83050b8) [ varref(0x8304f40) [ country (0x8304868) ]]
+                        THEN concatenate/0 (0x8304f98) [ ]
+                        ELSE concatenate/0 (0x8304ff8) [ ]
+                      ]
+                    ]
+                  ]
+                ]
+                FOR (0x8304ef8) user (0x8304e20)
+                [
+                  wrapper_expr (0x8304cc0) [
+                    function_trace_expr (0x82fc000) [
+                      flwor_expr (0x82fc598) [
+                        FOR (0x8306690) $$dot (0x82f5510)
+                        [
+                          collection/1 (0x830a188) [
+                            promote_expr xs:QName (0x83035b0) [
+                              data/1 (0x83067d8) [
+                                var_ref (0x82f97c8) [ testlibuser (0x830a420) ]
+                              ]
+                            ]
+                          ]
+                        ]
+                        WHERE
+                          not/1 (0x82f5068) [
+                            value-equal/2 (0x82fc810) [
+                              promote_expr xs:anyAtomicType? (0x82fc208) [
+                                data/1 (0x83037b0) [
+                                  relpath_expr (0x8303810) [
+                                    var_ref (0x82f45c0) [ $$dot (0x82f5510) ]
+                                      REL STEP attribute::match_expr [name_test(deleted)]
+                                  ]
+                                ]
+                              ]
+                              const_expr (0x82fc278) [ xs:boolean [ xs:boolean(true) ] ]
+                            ]
+                          ]
+                        RETURN var_ref (0x8303240) [ $$dot (0x82f5510) ]
+                      ]
+                    ]
+                  ]
+                ]
+                WHERE
+                  unhoist/1 (0x82fca58) [ varref(0x82fca00) [ $$opt_temp_0 (0x82fd0d8) ]]
+                RETURN
+                  var_ref (0x82f9618) [ user (0x8304e20) ]
+              ]
+            ]
+          ]
+          RETURN
+            var_ref (0x82fa230) [ user (0x82f9e20) ]
+        ]
+    ]
+  ]
+  RETURN
+    concatenate/0 (0x82f9998) [ ]
+]
+
+
+
+
+
+After hoisting : 
+flwor_expr (0x830a830) 
+[
+  LET (0x83032d8) query (0x8306358)
+  [
+    var kind=ARG (0x830a898) name=query
+  ]
+  LET (0x82f9db0) filtered (0x82f98c0)
+  [
+    if_expr (0x82f9cf0) 
+    [
+      boolean/1 (0x82f9d50) [ var_ref (0x83048e8) [ query (0x8306358) ] ]
+      THEN
+        wrapper_expr (0x8304940) [
+----------------------------------------------------------------------
+          flwor_expr (0x82f9670) 
+          [
+            FOR (0x8304c78) $$opt_temp_0 (0x8304868)
+            [
+              hoist/1 (0x82fd158) [
+                boolean/1 (0x8305118) [
+                  if_expr (0x8305058) [
+                    boolean/1 (0x83050b8) [ var_ref (0x8304f40) [ concatenate/0 (0x83046e8) [ ] ] ]
+                    THEN  concatenate/0 (0x8304f98) [ ]
+                    ELSE  concatenate/0 (0x8304ff8) [ ]
+                  ]
+                ]
+              ]
+            ]
+            FOR (0x8304ef8) user (0x8304e20)
+            [
+              wrapper_expr (0x8304cc0) [
+                function_trace_expr (0x82fc000) [
+                  flwor_expr (0x82fc598) 
+                  [
+                    FOR (0x8306690) $$dot (0x82f5510)
+                    [
+                      collection/1 (0x830a188) [
+                        promote_expr xs:QName (0x83035b0) [
+                          data/1 (0x83067d8) [
+                            var_ref (0x82f97c8) [ testlibuser (0x830a420) ]
+                          ]
+                        ]
+                      ]
+                    ]
+                    WHERE
+                      not/1 (0x82f5068) [
+                        value-equal/2 (0x82fc810) [
+                          promote_expr xs:anyAtomicType? (0x82fc208) [
+                            data/1 (0x83037b0) [
+                              relpath_expr (0x8303810) [
+                                var_ref (0x82f45c0) [ $$dot (0x82f5510) ] / @deleted
+                              ]
+                            ]
+                          ]
+                          const_expr (0x82fc278) [ xs:boolean [ xs:boolean(true) ] ]
+                        ]
+                      ]
+                    RETURN var_ref (0x8303240) [ $$dot (0x82f5510) ]
+                  ]
+                ]
+              ]
+            ]
+            WHERE unhoist/1 (0x82fca58) [ varref(0x82fca00) [ $$opt_temp_0 (0x8304868) ] ]
+            RETURN var_ref (0x82f9618) [ user (0x8304e20) ]
+          ]
+----------------------------------------------------------------------------
+        ]
+      ELSE
+        flwor_expr (0x82fa288) 
+        [
+          LET (0x82f9c50) loginBefore (0x82f9840)
+          [
+            value-equal/2 (0x8304a98) [
+              promote_expr xs:anyAtomicType? (0x8304b68) [
+                data/1 (0x8304af8) [
+                  var_ref (0x8304998) [ query (0x8306358) ]
+                ]
+              ]
+              const_expr (0x8304a08) [ xs:string [ xs:string(before) ] ]
+            ]
+          ]
+          FOR (0x8304810) user (0x82f9e20)
+          [
+            wrapper_expr (0x82f9c98) [
+---------------------------------------------------------------------------------
+              flwor_expr (0x82f9670) 
+              [
+                LET (0x8304c78) country (0x8304868)
+                [
+                  concatenate/0 (0x83046e8) [ ]
+                ]
+                LET (0x8306628) $$opt_temp_0 (0x82fd0d8)
+                [
+                  hoist/1 (0x82fd158) [
+                    boolean/1 (0x8305118) [
+                      if_expr (0x8305058) [
+                        boolean/1 (0x83050b8) [ varref(0x8304f40) [ country (0x8304868) ]]
+                        THEN concatenate/0 (0x8304f98) [ ]
+                        ELSE concatenate/0 (0x8304ff8) [ ]
+                      ]
+                    ]
+                  ]
+                ]
+                FOR (0x8304ef8) user (0x8304e20)
+                [
+                  wrapper_expr (0x8304cc0) [
+                    function_trace_expr (0x82fc000) [
+                      flwor_expr (0x82fc598) [
+                        FOR (0x8306690) $$dot (0x82f5510)
+                        [
+                          collection/1 (0x830a188) [
+                            promote_expr xs:QName (0x83035b0) [
+                              data/1 (0x83067d8) [
+                                var_ref (0x82f97c8) [ testlib:user (0x830a420) ]
+                              ]
+                            ]
+                          ]
+                        ]
+                        WHERE
+                          not/1 (0x82f5068) [
+                            value-equal/2 (0x82fc810) [
+                              promote_expr xs:anyAtomicType? (0x82fc208) [
+                                data/1 (0x83037b0) [
+                                  relpath_expr (0x8303810) [
+                                    var_ref (0x82f45c0) [ $$dot (0x82f5510) ]
+                                      REL STEP attribute::match_expr [name_test(deleted)]
+                                  ]
+                                ]
+                              ]
+                              const_expr (0x82fc278) [ xs:boolean [ xs:boolean(true) ] ]
+                            ]
+                          ]
+                        RETURN var_ref (0x8303240) [ $$dot (0x82f5510) ]
+                      ]
+                    ]
+                  ]
+                ]
+                WHERE
+                  unhoist/1 (0x82fca58) [ varref(0x82fca00) [ $$opt_temp_0 (0x82fd0d8) ]]
+                RETURN
+                  var_ref (0x82f9618) [ user (0x8304e20) ]
+              ]
+-------------------------------------------------------------------------
+            ]
+          ]
+          RETURN var_ref (0x82fa230) [ user (0x82f9e20) ]
+        ]
+    ]
+  ]
+  RETURN
+    concatenate/0 (0x82f9998) [ ]
+]
+
+
+
+
+After EliminateUnusedLetVars :
+flwor_expr (0x830a830) 
+[
+  LET (0x83032d8) query (0x8306358)
+  [
+    var kind=ARG (0x830a898) name=query
+  ]
+  LET (0x82f9db0) filtered (0x82f98c0)
+  [
+    if_expr (0x82f9cf0) 
+    [
+      boolean/1 (0x82f9d50) [ var_ref (0x83048e8) [ query (0x8306358) ] ]
+      THEN
+        wrapper_expr (0x8304940) [
+-----------------------------------------------------------------------------
+          flwor_expr (0x82f9670) 
+          [
+            FOR (0x8304ef8) user (0x8304e20)
+            [
+              wrapper_expr (0x8304cc0) [
+                function_trace_expr (0x82fc000) [
+                  flwor_expr (0x82fc598) [
+                    FOR (0x8306690) $$dot (0x82f5510)
+                    [
+                      collection/1 (0x830a188) [
+                        promote_expr xs:QName (0x83035b0) [
+                          data/1 (0x83067d8) [
+                            var_ref (0x82f97c8) [ testlib[=http://www.test.ch]:user (0x830a420) ]
+                          ]
+                        ]
+                      ]
+                    ]
+                    WHERE
+                      not/1 (0x82f5068) [
+                        value-equal/2 (0x82fc810) [
+                          promote_expr xs:anyAtomicType? (0x82fc208) [
+                            data/1 (0x83037b0) [
+                              relpath_expr (0x8303810) [
+                                var_ref (0x82f45c0) [ $$dot (0x82f5510) ]
+                                  REL STEP attribute::match_expr [name_test(deleted)]
+                              ]
+                            ]
+                          ]
+                          const_expr (0x82fc278) [ xs:boolean [ xs:boolean(true) ] ]
+                        ]
+                      ]
+                    RETURN
+                      var_ref (0x8303240) [ $$dot (0x82f5510) ]
+                  ]
+                ]
+              ]
+            ]
+            RETURN var_ref (0x82f9618) [ user (0x8304e20) ]
+          ]
+        ]
+      ELSE
+        flwor_expr (0x82fa288) [
+          LET (0x82f9c50) loginBefore (0x82f9840)
+           [
+            value-equal/2 (0x8304a98) [
+              promote_expr xs:anyAtomicType? (0x8304b68) [
+                data/1 (0x8304af8) [
+                  var_ref (0x8304998) [ query (0x8306358) ]
+                ]
+              ]
+              const_expr (0x8304a08) [ xs:string [ xs:string(before) ] ]
+            ]
+          ]
+          FOR (0x8304810) user (0x82f9e20)
+          [
+            wrapper_expr (0x82f9c98) [
+              if_expr (0x82fc400) [
+                unhoist/1 (0x82fca58) [
+                  var_ref (0x82fca00) [ $$opt_temp_0 (0x8304868) ]
+                ]
+                THEN
+                  flwor_expr (0x82f9670) [
+                    FOR (0x8304ef8) user (0x8304e20)
+                    [
+                      wrapper_expr (0x8304cc0) [
+                        function_trace_expr (0x82fc000) [
+                          flwor_expr (0x82fc598) [
+                            FOR (0x8306690) $$dot (0x82f5510)
+                            [
+                              collection/1 (0x830a188) [
+                                promote_expr xs:QName (0x83035b0) [
+                                  data/1 (0x83067d8) [
+                                    var_ref (0x82f97c8) [ testlib[=http://www.test.ch]:user (0x830a420) ]
+                                  ]
+                                ]
+                              ]
+                            ]
+                            WHERE
+                              not/1 (0x82f5068) [
+                                value-equal/2 (0x82fc810) [
+                                  promote_expr xs:anyAtomicType? (0x82fc208) [
+                                    data/1 (0x83037b0) [
+                                      relpath_expr (0x8303810) [
+                                        var_ref (0x82f45c0) [ $$dot (0x82f5510) ]
+                                          REL STEP attribute::match_expr [name_test(deleted)]
+                                      ]
+                                    ]
+                                  ]
+                                  const_expr (0x82fc278) [ xs:boolean [ xs:boolean(true) ] ]
+                                ]
+                              ]
+                            RETURN
+                              var_ref (0x8303240) [ $$dot (0x82f5510) ]
+                          ]
+                        ]
+                      ]
+                    ]
+                    RETURN
+                      var_ref (0x82f9618) [ user (0x8304e20) ]
+                  ]
+                ELSE
+                  concatenate/0 (0x82fd0d8) [ ]
+              ]
+            ]
+          ]
+          RETURN var_ref (0x82fa230) [ user (0x82f9e20) ]
+        ]
+    ]
+  ]
+  RETURN concatenate/0 (0x82f9998) [ ]
+]
+
+:)


Follow ups