Author: markt
Date: Thu Jul 18 20:56:44 2013
New Revision: 1504657

URL: http://svn.apache.org/r1504657
Log:
Yet more adventures with lambda expressions.
I suspect - but haven't yet checked - that there is scope to make the code more 
efficient and/or reduce duplication.

Modified:
    tomcat/trunk/java/org/apache/el/parser/AstFunction.java
    tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java
    tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java

Modified: tomcat/trunk/java/org/apache/el/parser/AstFunction.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/parser/AstFunction.java?rev=1504657&r1=1504656&r2=1504657&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/el/parser/AstFunction.java (original)
+++ tomcat/trunk/java/org/apache/el/parser/AstFunction.java Thu Jul 18 20:56:44 
2013
@@ -98,12 +98,18 @@ public final class AstFunction extends S
                 // Build arguments
                 int i = 0;
                 while (obj instanceof LambdaExpression &&
-                        i < this.jjtGetNumChildren()) {
+                        i < jjtGetNumChildren()) {
                     Node args = jjtGetChild(i);
                     obj = ((LambdaExpression) obj).invoke(
                             ((AstMethodParameters) args).getParameters(ctx));
                     i++;
                 }
+                if (i < jjtGetNumChildren()) {
+                    // Haven't consumed all the sets of parameters therefore
+                    // there were too many sets of parameters
+                    throw new ELException(MessageFactory.get(
+                            "error.lambda.tooManyMethodParameterSets"));
+                }
                 return obj;
             }
         }

Modified: tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java?rev=1504657&r1=1504656&r2=1504657&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java (original)
+++ tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java Thu Jul 18 
20:56:44 2013
@@ -36,22 +36,39 @@ public class AstLambdaExpression extends
     @Override
     public Object getValue(EvaluationContext ctx) throws ELException {
 
-        // Check that there are not more sets of method parameters than there
-        // are nested lambda expressions
+        // Check;
+        // - that there are not more sets of method parameters than there are
+        //   nested lambda expressions
+        // - if any of the nested expressions declare formal parameters
         int methodParameterSetCount = jjtGetNumChildren() - 2;
-        if (methodParameterSetCount > 0) {
-            // We know this node is an expression
-            methodParameterSetCount--;
-            Node n = this.jjtGetChild(1);
-            while (methodParameterSetCount > 0) {
-                if (n.jjtGetNumChildren() <2 ||
-                        !(n.jjtGetChild(0) instanceof AstLambdaParameters)) {
-                    throw new ELException(MessageFactory.get(
-                            "error.lambda.tooManyMethodParameterSets"));
+        boolean declaresParameters = false;
+        // We know this node is an expression
+        int lambdaExpressionCount = 1;
+        // child at index 1 is the expression
+        Node n = jjtGetChild(1);
+        while (n instanceof AstLambdaExpression) {
+            lambdaExpressionCount++;
+            if (n.jjtGetChild(0) instanceof AstLambdaParameters) {
+                if (!declaresParameters &&
+                        n.jjtGetChild(0).jjtGetNumChildren() > 0) {
+                    declaresParameters = true;
                 }
                 n = n.jjtGetChild(1);
-                methodParameterSetCount--;
+            } else {
+                n = null;
+            }
+        }
+        if (methodParameterSetCount > lambdaExpressionCount) {
+            throw new ELException(MessageFactory.get(
+                    "error.lambda.tooManyMethodParameterSets"));
+        }
+        // Also need to check parents for declaration of formal parameters
+        n = parent;
+        while (!declaresParameters && n instanceof AstLambdaExpression) {
+            if (n.jjtGetChild(0).jjtGetNumChildren() > 0) {
+                declaresParameters = true;
             }
+            n = n.jjtGetParent();
         }
 
         // First child is always parameters even if there aren't any
@@ -74,10 +91,9 @@ public class AstLambdaExpression extends
         le.setELContext(ctx);
 
         if (jjtGetNumChildren() == 2) {
-            if (formalParameters.isEmpty() &&
-                    !(parent instanceof AstLambdaExpression)) {
-                // No formal parameters or method parameters and not a nested
-                // expression so invoke the expression.
+            if (formalParameters.isEmpty() && !declaresParameters) {
+                // No formal parameters or method parameters and not nested
+                // inside another lambda expression so invoke the expression.
                 return le.invoke(ctx, (Object[]) null);
             } else {
                 // Has formal parameters but no method parameters or is a 
nested

Modified: tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java?rev=1504657&r1=1504656&r2=1504657&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java 
(original)
+++ tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java Thu Jul 
18 20:56:44 2013
@@ -147,11 +147,80 @@ public class TestAstLambdaExpression {
 
 
     @Test
-    public void testLambdaAsFunction() {
+    public void testNested07() {
+        ELProcessor processor = new ELProcessor();
+        Object result =
+                processor.getValue("()->()->()->42",
+                        Integer.class);
+        Assert.assertEquals(Integer.valueOf(42), result);
+    }
+
+
+    @Test
+    public void testLambdaAsFunction01() {
         ELProcessor processor = new ELProcessor();
         Object result =
                 processor.getValue("v = (x->y->x-y); v(2)(1)",
                         Integer.class);
         Assert.assertEquals(Integer.valueOf(1), result);
     }
+
+
+    @Test
+    public void testLambdaAsFunction02() {
+        ELProcessor processor = new ELProcessor();
+        Object result =
+                processor.getValue("v = (()->y->2-y); v()(1)",
+                        Integer.class);
+        Assert.assertEquals(Integer.valueOf(1), result);
+    }
+
+
+    @Test
+    public void testLambdaAsFunction03() {
+        ELProcessor processor = new ELProcessor();
+        Object result =
+                processor.getValue("v = (()->y->()->2-y); v()(1)()",
+                        Integer.class);
+        Assert.assertEquals(Integer.valueOf(1), result);
+    }
+
+
+    @Test(expected=ELException.class)
+    public void testLambdaAsFunction04() {
+        ELProcessor processor = new ELProcessor();
+        // More method parameters than there are nested lambda expressions
+        processor.getValue("v = (()->y->()->2-y); v()(1)()()",
+                    Integer.class);
+    }
+
+
+    @Test
+    public void testLambdaAsFunction05() {
+        ELProcessor processor = new ELProcessor();
+        Object result =
+                processor.getValue("v = (()->y->()->x->x-y); v()(1)()(2)",
+                        Integer.class);
+        Assert.assertEquals(Integer.valueOf(1), result);
+    }
+
+
+    @Test
+    public void testLambdaAsFunction06() {
+        ELProcessor processor = new ELProcessor();
+        Object result =
+                processor.getValue("v = (()->y->()->()->x->x-y); 
v()(1)()()(2)",
+                        Integer.class);
+        Assert.assertEquals(Integer.valueOf(1), result);
+    }
+
+
+    @Test
+    public void testLambdaAsFunction07() {
+        ELProcessor processor = new ELProcessor();
+        Object result =
+                processor.getValue("v = (()->y->()->()->x->x-y); 
v()(1)()(3)(2)",
+                        Integer.class);
+        Assert.assertEquals(Integer.valueOf(1), result);
+    }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to