You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vxquery.apache.org by pr...@apache.org on 2015/06/29 03:00:41 UTC

[2/3] vxquery git commit: Rewrite rules modified to convert(to and from) algebrics function correctly

Rewrite rules modified to convert(to and from) algebrics function correctly


Project: http://git-wip-us.apache.org/repos/asf/vxquery/repo
Commit: http://git-wip-us.apache.org/repos/asf/vxquery/commit/c31a36cb
Tree: http://git-wip-us.apache.org/repos/asf/vxquery/tree/c31a36cb
Diff: http://git-wip-us.apache.org/repos/asf/vxquery/diff/c31a36cb

Branch: refs/heads/master
Commit: c31a36cbbe942860e99e3450e97884412a36773a
Parents: 0771073
Author: Shivani Mall <sm...@ucr.edu>
Authored: Thu Jun 25 14:16:40 2015 -0700
Committer: Preston Carman <pr...@apache.org>
Committed: Sun Jun 28 17:56:38 2015 -0700

----------------------------------------------------------------------
 .../ConvertFromAlgebricksExpressionsRule.java   |  73 +++++++-----
 .../ConvertToAlgebricksExpressionsRule.java     | 110 ++++++++++++-------
 .../rewriter/rules/util/ExpressionToolbox.java  |  17 ++-
 3 files changed, 135 insertions(+), 65 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/vxquery/blob/c31a36cb/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertFromAlgebricksExpressionsRule.java
----------------------------------------------------------------------
diff --git a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertFromAlgebricksExpressionsRule.java b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertFromAlgebricksExpressionsRule.java
index 1bc2bd6..2ea95fe 100644
--- a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertFromAlgebricksExpressionsRule.java
+++ b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertFromAlgebricksExpressionsRule.java
@@ -29,10 +29,12 @@ import org.apache.vxquery.functions.BuiltinFunctions;
 import org.apache.vxquery.functions.BuiltinOperators;
 
 import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.common.utils.Pair;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.IOptimizationContext;
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IExpressionAnnotation;
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
 import edu.uci.ics.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
 import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
@@ -40,8 +42,8 @@ import edu.uci.ics.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
 import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
 
 /**
- * The rule searches for where the Algebricks builtin function are temporarly in the plan in place of XQuery function. 
- * The combination the Algebricks builtin function are replace with boolean XQuery function and the XQuery equivalent 
+ * The rule searches for where the Algebricks builtin function are temporarly in the plan in place of XQuery function.
+ * The combination the Algebricks builtin function are replace with boolean XQuery function and the XQuery equivalent
  * function.
  * 
  * <pre>
@@ -60,23 +62,30 @@ import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
  *   plan__child
  * </pre>
  * 
- * @author prestonc
+ * @author prestonc, shivanim
  */
 public class ConvertFromAlgebricksExpressionsRule implements IAlgebraicRewriteRule {
     final List<Mutable<ILogicalExpression>> functionList = new ArrayList<Mutable<ILogicalExpression>>();
-
-    final Map<FunctionIdentifier, IFunctionInfo> ALGEBRICKS_MAP = new HashMap<FunctionIdentifier, IFunctionInfo>();
+    final static Map<FunctionIdentifier, Pair<IFunctionInfo, IFunctionInfo>> ALGEBRICKS_MAP = new HashMap<FunctionIdentifier, Pair<IFunctionInfo, IFunctionInfo>>();
+    final static String ConversionToAndFromAlgebrics = "ConversionToAndFromAlgebrics";
 
     public ConvertFromAlgebricksExpressionsRule() {
-        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.AND, BuiltinOperators.AND);
-        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.OR, BuiltinOperators.OR);
-        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.NOT, BuiltinFunctions.FN_NOT_1);
-        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.EQ, BuiltinOperators.VALUE_EQ);
-        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.NEQ, BuiltinOperators.VALUE_NE);
-        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.LT, BuiltinOperators.VALUE_LT);
-        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.LE, BuiltinOperators.VALUE_LE);
-        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.GT, BuiltinOperators.VALUE_GT);
-        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.GE, BuiltinOperators.VALUE_GE);
+        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.AND, new Pair(BuiltinOperators.AND, null));
+        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.EQ, new Pair(BuiltinOperators.VALUE_EQ,
+                BuiltinOperators.GENERAL_EQ));
+        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.GT, new Pair(BuiltinOperators.VALUE_GT,
+                BuiltinOperators.GENERAL_GT));
+        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.GE, new Pair(BuiltinOperators.VALUE_GE,
+                BuiltinOperators.GENERAL_GE));
+        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.IS_NULL, new Pair(null, BuiltinFunctions.FN_EMPTY_1));
+        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.LT, new Pair(BuiltinOperators.VALUE_LT,
+                BuiltinOperators.GENERAL_LT));
+        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.LE, new Pair(BuiltinOperators.VALUE_LE,
+                BuiltinOperators.GENERAL_LE));
+        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.NOT, new Pair(null, BuiltinFunctions.FN_NOT_1));
+        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.NEQ, new Pair(BuiltinOperators.VALUE_NE,
+                BuiltinOperators.GENERAL_NE));
+        ALGEBRICKS_MAP.put(AlgebricksBuiltinFunctions.OR, new Pair(BuiltinOperators.OR, null));
     }
 
     @Override
@@ -100,20 +109,32 @@ public class ConvertFromAlgebricksExpressionsRule implements IAlgebraicRewriteRu
     @SuppressWarnings("unchecked")
     private boolean processExpression(Mutable<ILogicalOperator> opRef, Mutable<ILogicalExpression> search) {
         boolean modified = false;
-        for (FunctionIdentifier fid : ALGEBRICKS_MAP.keySet()) {
-            functionList.clear();
-            ExpressionToolbox.findAllFunctionExpressions(search, fid, functionList);
-            for (Mutable<ILogicalExpression> searchM : functionList) {
-                AbstractFunctionCallExpression searchFunction = (AbstractFunctionCallExpression) searchM.getValue();
-                searchFunction.setFunctionInfo(ALGEBRICKS_MAP.get(fid));
-                // Add boolean function before vxquery expression.
-                ScalarFunctionCallExpression booleanExp = new ScalarFunctionCallExpression(
-                        BuiltinFunctions.FN_BOOLEAN_1, new MutableObject<ILogicalExpression>(searchM.getValue()));
-                searchM.setValue(booleanExp);
-                modified = true;
+        functionList.clear();
+        ExpressionToolbox.findAllFunctionExpressions(search, functionList);
+        for (Mutable<ILogicalExpression> searchM : functionList) {
+            AbstractFunctionCallExpression searchFunction = (AbstractFunctionCallExpression) searchM.getValue();
+            if (ALGEBRICKS_MAP.containsKey(searchFunction.getFunctionIdentifier())) {
+                ScalarFunctionCallExpression booleanFunctionCallExp = null;
+                IExpressionAnnotation annotate = searchFunction.getAnnotations().get(ConversionToAndFromAlgebrics);
+                FunctionIdentifier fid = searchFunction.getFunctionIdentifier();
+                if (((FunctionIdentifier) annotate.getObject()).equals(ALGEBRICKS_MAP.get(fid).first
+                        .getFunctionIdentifier())) {
+                    searchFunction.setFunctionInfo(ALGEBRICKS_MAP.get(fid).first);
+                    booleanFunctionCallExp = new ScalarFunctionCallExpression(BuiltinFunctions.FN_BOOLEAN_1,
+                            new MutableObject<ILogicalExpression>(searchM.getValue()));
+                    searchM.setValue(booleanFunctionCallExp);
+                    modified = true;
+                } else if (((FunctionIdentifier) annotate.getObject()).equals(ALGEBRICKS_MAP.get(fid).second
+                        .getFunctionIdentifier())) {
+                    searchFunction.setFunctionInfo(ALGEBRICKS_MAP.get(fid).second);
+                    booleanFunctionCallExp = new ScalarFunctionCallExpression(ALGEBRICKS_MAP.get(fid).second,
+                            searchFunction.getArguments());
+                    searchM.setValue(booleanFunctionCallExp);
+                    modified = true;
+                } else {
+                }
             }
         }
         return modified;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/vxquery/blob/c31a36cb/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertToAlgebricksExpressionsRule.java
----------------------------------------------------------------------
diff --git a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertToAlgebricksExpressionsRule.java b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertToAlgebricksExpressionsRule.java
index 943d630..fd9fa7c 100644
--- a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertToAlgebricksExpressionsRule.java
+++ b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/ConvertToAlgebricksExpressionsRule.java
@@ -16,13 +16,11 @@
  */
 package org.apache.vxquery.compiler.rewriter.rules;
 
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.lang3.mutable.Mutable;
-import org.apache.vxquery.compiler.rewriter.rules.util.ExpressionToolbox;
 import org.apache.vxquery.compiler.rewriter.rules.util.OperatorToolbox;
 import org.apache.vxquery.functions.BuiltinFunctions;
 import org.apache.vxquery.functions.BuiltinOperators;
@@ -33,21 +31,24 @@ import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalOperator;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.IOptimizationContext;
 import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ExpressionAnnotationNoCopyImpl;
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IExpressionAnnotation;
 import edu.uci.ics.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
 import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import edu.uci.ics.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
 import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
 
 /**
- * The rule searches for where the XQuery function are used in place of Algebricks builtin function. 
- * The combination the boolean XQuery function and the XQuery equivalent function are replace with 
- * the Algebricks builtin function  .
+ * The rule searches for where the XQuery function are used in place of Algebricks builtin function.
+ * The combination of the boolean XQuery function and the XQuery equivalent function are replaced with
+ * the Algebricks builtin function .
  * 
  * <pre>
  * Before
  * 
  *   plan__parent
- *   %OPERATOR( $v1 : boolean(xquery_function( \@input_expression ) ) )
+ *   %OPERATOR( $v1 : boolean(xquery_function( \@input_expression ) or $v1 : general-compare(xquery_function( \@input_expression ) 
+ *    or $v1 : fn_empty(xquery_function( \@input_expression ) or $v1 : fn_not(xquery_function( \@input_expression 
  *   plan__child
  *   
  *   Where xquery_function creates an atomic value.
@@ -59,23 +60,32 @@ import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
  *   plan__child
  * </pre>
  * 
- * @author prestonc
+ * @author prestonc, shivanim
  */
 public class ConvertToAlgebricksExpressionsRule implements IAlgebraicRewriteRule {
-    final List<Mutable<ILogicalExpression>> functionList = new ArrayList<Mutable<ILogicalExpression>>();
-
     final Map<FunctionIdentifier, FunctionIdentifier> ALGEBRICKS_MAP = new HashMap<FunctionIdentifier, FunctionIdentifier>();
+    final Map<FunctionIdentifier, FunctionIdentifier> ALGEBRICKS_BOOL_MAP = new HashMap<FunctionIdentifier, FunctionIdentifier>();
+    final static String ConversionToAndFromAlgebrics = "ConversionToAndFromAlgebrics";
 
     public ConvertToAlgebricksExpressionsRule() {
-        ALGEBRICKS_MAP.put(BuiltinOperators.AND.getFunctionIdentifier(), AlgebricksBuiltinFunctions.AND);
-        ALGEBRICKS_MAP.put(BuiltinOperators.OR.getFunctionIdentifier(), AlgebricksBuiltinFunctions.OR);
+
+        ALGEBRICKS_BOOL_MAP.put(BuiltinOperators.AND.getFunctionIdentifier(), AlgebricksBuiltinFunctions.AND);
+        ALGEBRICKS_BOOL_MAP.put(BuiltinOperators.OR.getFunctionIdentifier(), AlgebricksBuiltinFunctions.OR);
+        ALGEBRICKS_BOOL_MAP.put(BuiltinOperators.VALUE_NE.getFunctionIdentifier(), AlgebricksBuiltinFunctions.NEQ);
+        ALGEBRICKS_BOOL_MAP.put(BuiltinOperators.VALUE_EQ.getFunctionIdentifier(), AlgebricksBuiltinFunctions.EQ);
+        ALGEBRICKS_BOOL_MAP.put(BuiltinOperators.VALUE_LE.getFunctionIdentifier(), AlgebricksBuiltinFunctions.LE);
+        ALGEBRICKS_BOOL_MAP.put(BuiltinOperators.VALUE_LT.getFunctionIdentifier(), AlgebricksBuiltinFunctions.LT);
+        ALGEBRICKS_BOOL_MAP.put(BuiltinOperators.VALUE_GT.getFunctionIdentifier(), AlgebricksBuiltinFunctions.GT);
+        ALGEBRICKS_BOOL_MAP.put(BuiltinOperators.VALUE_GE.getFunctionIdentifier(), AlgebricksBuiltinFunctions.GE);
+
+        ALGEBRICKS_MAP.put(BuiltinFunctions.FN_EMPTY_1.getFunctionIdentifier(), AlgebricksBuiltinFunctions.IS_NULL);
         ALGEBRICKS_MAP.put(BuiltinFunctions.FN_NOT_1.getFunctionIdentifier(), AlgebricksBuiltinFunctions.NOT);
-        ALGEBRICKS_MAP.put(BuiltinOperators.VALUE_EQ.getFunctionIdentifier(), AlgebricksBuiltinFunctions.EQ);
-        ALGEBRICKS_MAP.put(BuiltinOperators.VALUE_NE.getFunctionIdentifier(), AlgebricksBuiltinFunctions.NEQ);
-        ALGEBRICKS_MAP.put(BuiltinOperators.VALUE_LT.getFunctionIdentifier(), AlgebricksBuiltinFunctions.LT);
-        ALGEBRICKS_MAP.put(BuiltinOperators.VALUE_LE.getFunctionIdentifier(), AlgebricksBuiltinFunctions.LE);
-        ALGEBRICKS_MAP.put(BuiltinOperators.VALUE_GT.getFunctionIdentifier(), AlgebricksBuiltinFunctions.GT);
-        ALGEBRICKS_MAP.put(BuiltinOperators.VALUE_GE.getFunctionIdentifier(), AlgebricksBuiltinFunctions.GE);
+        ALGEBRICKS_MAP.put(BuiltinOperators.GENERAL_LT.getFunctionIdentifier(), AlgebricksBuiltinFunctions.LT);
+        ALGEBRICKS_MAP.put(BuiltinOperators.GENERAL_EQ.getFunctionIdentifier(), AlgebricksBuiltinFunctions.EQ);
+        ALGEBRICKS_MAP.put(BuiltinOperators.GENERAL_LE.getFunctionIdentifier(), AlgebricksBuiltinFunctions.LE);
+        ALGEBRICKS_MAP.put(BuiltinOperators.GENERAL_GE.getFunctionIdentifier(), AlgebricksBuiltinFunctions.GE);
+        ALGEBRICKS_MAP.put(BuiltinOperators.GENERAL_GT.getFunctionIdentifier(), AlgebricksBuiltinFunctions.GT);
+        ALGEBRICKS_MAP.put(BuiltinOperators.GENERAL_NE.getFunctionIdentifier(), AlgebricksBuiltinFunctions.NEQ);
     }
 
     @Override
@@ -89,36 +99,60 @@ public class ConvertToAlgebricksExpressionsRule implements IAlgebraicRewriteRule
         boolean modified = false;
         List<Mutable<ILogicalExpression>> expressions = OperatorToolbox.getExpressions(opRef);
         for (Mutable<ILogicalExpression> expression : expressions) {
-            if (processExpression(opRef, expression, context)) {
+            if (processExpression(expression, context)) {
                 modified = true;
             }
         }
         return modified;
     }
 
-    private boolean processExpression(Mutable<ILogicalOperator> opRef, Mutable<ILogicalExpression> search,
-            IOptimizationContext context) {
+    private boolean processExpression(Mutable<ILogicalExpression> search, IOptimizationContext context) {
+        return checkAllFunctionExpressions(search, context);
+    }
+
+    public boolean convertFunctionToAlgebricksExpression(Mutable<ILogicalExpression> searchM,
+            AbstractFunctionCallExpression functionCall, IOptimizationContext context,
+            Map<FunctionIdentifier, FunctionIdentifier> map) {
+
+        if (map.containsKey(functionCall.getFunctionIdentifier())) {
+            IExpressionAnnotation annotate = new ExpressionAnnotationNoCopyImpl();
+            annotate.setObject(functionCall.getFunctionIdentifier());
+            FunctionIdentifier algebricksFid = map.get(functionCall.getFunctionIdentifier());
+            IFunctionInfo algebricksFunction = context.getMetadataProvider().lookupFunction(algebricksFid);
+            functionCall.setFunctionInfo(algebricksFunction);
+            functionCall.getAnnotations().put(ConversionToAndFromAlgebrics, annotate);
+            searchM.setValue(functionCall);
+            return true;
+        }
+        return false;
+    }
+
+    public boolean checkAllFunctionExpressions(Mutable<ILogicalExpression> search, IOptimizationContext context) {
         boolean modified = false;
-        functionList.clear();
-        ExpressionToolbox.findAllFunctionExpressions(search, BuiltinFunctions.FN_BOOLEAN_1.getFunctionIdentifier(),
-                functionList);
-        for (Mutable<ILogicalExpression> searchM : functionList) {
-            // Get input function
-            AbstractFunctionCallExpression searchFunction = (AbstractFunctionCallExpression) searchM.getValue();
-            ILogicalExpression argFirst = searchFunction.getArguments().get(0).getValue();
-            if (argFirst.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
-                continue;
+        ILogicalExpression le = search.getValue();
+
+        if (le.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
+            AbstractFunctionCallExpression afce = (AbstractFunctionCallExpression) le;
+            if (afce.getFunctionIdentifier().equals(BuiltinFunctions.FN_BOOLEAN_1.getFunctionIdentifier())) {
+                ILogicalExpression argFirst = afce.getArguments().get(0).getValue();
+                if (argFirst.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
+                    AbstractFunctionCallExpression functionCall = (AbstractFunctionCallExpression) argFirst;
+                    if (convertFunctionToAlgebricksExpression(search, functionCall, context, ALGEBRICKS_BOOL_MAP)) {
+                        modified = true;
+                    }
+                }
+            } else if (ALGEBRICKS_MAP.containsKey(afce.getFunctionIdentifier())) {
+                if (convertFunctionToAlgebricksExpression(search, afce, context, ALGEBRICKS_MAP)) {
+                    modified = true;
+                }
+            } else {
             }
-            AbstractFunctionCallExpression functionCall = (AbstractFunctionCallExpression) argFirst;
-            if (ALGEBRICKS_MAP.containsKey(functionCall.getFunctionIdentifier())) {
-                FunctionIdentifier algebricksFid = ALGEBRICKS_MAP.get(functionCall.getFunctionIdentifier());
-                IFunctionInfo algebricksFunction = context.getMetadataProvider().lookupFunction(algebricksFid);
-                functionCall.setFunctionInfo(algebricksFunction);
-                searchM.setValue(argFirst);
-                modified = true;
+            for (Mutable<ILogicalExpression> argExp : afce.getArguments()) {
+                if (checkAllFunctionExpressions(argExp, context)) {
+                    modified = true;
+                }
             }
         }
         return modified;
     }
-
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/vxquery/blob/c31a36cb/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/util/ExpressionToolbox.java
----------------------------------------------------------------------
diff --git a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/util/ExpressionToolbox.java b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/util/ExpressionToolbox.java
index 2b2bf0c..9374cc3 100644
--- a/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/util/ExpressionToolbox.java
+++ b/vxquery-core/src/main/java/org/apache/vxquery/compiler/rewriter/rules/util/ExpressionToolbox.java
@@ -130,7 +130,22 @@ public class ExpressionToolbox {
     }
 
     /**
-     * Find all functions for a specific expression.
+     * Finds all functions for a given expression.
+     */
+    public static void findAllFunctionExpressions(Mutable<ILogicalExpression> mutableLe,
+            List<Mutable<ILogicalExpression>> finds) {
+        ILogicalExpression le = mutableLe.getValue();
+        if (le.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
+            AbstractFunctionCallExpression afce = (AbstractFunctionCallExpression) le;
+            finds.add(mutableLe);
+            for (Mutable<ILogicalExpression> argExp : afce.getArguments()) {
+                findAllFunctionExpressions(argExp, finds);
+            }
+        }
+    }
+
+    /**
+     * Finds all functions for a given expression and function identifier.
      */
     public static void findAllFunctionExpressions(Mutable<ILogicalExpression> mutableLe, FunctionIdentifier fi,
             List<Mutable<ILogicalExpression>> finds) {