You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by he...@apache.org on 2012/02/11 12:26:43 UTC
svn commit: r1243029 [1/2] - in /commons/proper/jexl/trunk: ./
src/main/java/org/apache/commons/jexl3/
src/main/java/org/apache/commons/jexl3/internal/
src/main/java/org/apache/commons/jexl3/parser/
src/test/java/org/apache/commons/jexl3/ src/test/java...
Author: henrib
Date: Sat Feb 11 11:26:42 2012
New Revision: 1243029
URL: http://svn.apache.org/viewvc?rev=1243029&view=rev
Log:
JEXL-127; added support for 'function', includes variable hoisting
Added:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Frame.java (with props)
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java (with props)
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlLambda.java
- copied, changed from r1211892, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java (with props)
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/PropertyAccessTest.java
- copied, changed from r1212868, commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayAccessTest.java
Modified:
commons/proper/jexl/trunk/pom.xml
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayAccessTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayLiteralTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/AssignTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JexlTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/parser/ParserTest.java
Modified: commons/proper/jexl/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/pom.xml?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/pom.xml (original)
+++ commons/proper/jexl/trunk/pom.xml Sat Feb 11 11:26:42 2012
@@ -19,7 +19,7 @@
<parent>
<groupId>org.apache.commons</groupId>
<artifactId>commons-parent</artifactId>
- <version>22</version>
+ <version>23</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.commons</groupId>
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/JexlException.java Sat Feb 11 11:26:42 2012
@@ -46,10 +46,7 @@ public class JexlException extends Runti
* @param msg the error message
*/
public JexlException(JexlNode node, String msg) {
- super(msg);
- mark = node;
- info = node != null ? node.jexlInfo() : null;
-
+ this(node, msg, null);
}
/**
@@ -59,32 +56,19 @@ public class JexlException extends Runti
* @param cause the exception causing the error
*/
public JexlException(JexlNode node, String msg, Throwable cause) {
- super(msg, unwrap(cause));
- mark = node;
- info = node != null ? node.jexlInfo() : null;
- }
-
- /**
- * Creates a new JexlException.
- * @param dbg the debugging information associated
- * @param msg the error message
- */
- public JexlException(JexlInfo dbg, String msg) {
- super(msg);
- mark = null;
- info = dbg;
+ this(node != null ? node.jexlInfo() : null, msg, cause);
}
/**
* Creates a new JexlException.
- * @param dbg the debugging information associated
+ * @param jinfo the debugging information associated
* @param msg the error message
* @param cause the exception causing the error
*/
- public JexlException(JexlInfo dbg, String msg, Throwable cause) {
+ public JexlException(JexlInfo jinfo, String msg, Throwable cause) {
super(msg, unwrap(cause));
mark = null;
- info = dbg;
+ info = jinfo;
}
/**
@@ -140,22 +124,22 @@ public class JexlException extends Runti
public static class Tokenization extends JexlException {
/**
* Creates a new Tokenization exception instance.
- * @param node the location info
+ * @param info the location info
* @param expr the expression
* @param cause the javacc cause
*/
- public Tokenization(JexlInfo node, CharSequence expr, TokenMgrError cause) {
- super(merge(node, cause), expr.toString(), cause);
+ public Tokenization(JexlInfo info, CharSequence expr, TokenMgrError cause) {
+ super(merge(info, cause), expr.toString(), cause);
}
/**
* Merge the node info and the cause info to obtain best possible location.
- * @param node the node
+ * @param info the node
* @param cause the cause
* @return the info to use
*/
- private static JexlInfo merge(JexlInfo node, TokenMgrError cause) {
- JexlInfo dbgn = node != null ? node : null;
+ private static JexlInfo merge(JexlInfo info, TokenMgrError cause) {
+ JexlInfo dbgn = info != null ? info : null;
if (cause == null) {
return dbgn;
} else if (dbgn == null) {
@@ -185,22 +169,22 @@ public class JexlException extends Runti
public static class Parsing extends JexlException {
/**
* Creates a new Variable exception instance.
- * @param node the offending ASTnode
+ * @param info the location information
* @param expr the offending source
* @param cause the javacc cause
*/
- public Parsing(JexlInfo node, CharSequence expr, ParseException cause) {
- super(merge(node, cause), expr.toString(), cause);
+ public Parsing(JexlInfo info, CharSequence expr, ParseException cause) {
+ super(merge(info, cause), expr.toString(), cause);
}
/**
* Merge the node info and the cause info to obtain best possible location.
- * @param node the node
+ * @param info the location information
* @param cause the cause
* @return the info to use
*/
- private static JexlInfo merge(JexlInfo node, ParseException cause) {
- JexlInfo dbgn = node != null ? node : null;
+ private static JexlInfo merge(JexlInfo info, ParseException cause) {
+ JexlInfo dbgn = info != null ? info : null;
if (cause == null) {
return dbgn;
} else if (dbgn == null) {
@@ -232,9 +216,10 @@ public class JexlException extends Runti
* Creates a new Variable exception instance.
* @param node the offending ASTnode
* @param var the unknown variable
+ * @param cause the exception causing the error
*/
public Variable(JexlNode node, String var) {
- super(node, var);
+ super(node, var, null);
}
/**
@@ -261,7 +246,17 @@ public class JexlException extends Runti
* @param var the unknown variable
*/
public Property(JexlNode node, String var) {
- super(node, var);
+ this(node, var, null);
+ }
+
+ /**
+ * Creates a new Property exception instance.
+ * @param node the offending ASTnode
+ * @param var the unknown variable
+ * @param cause the exception causing the error
+ */
+ public Property(JexlNode node, String var, Throwable cause) {
+ super(node, var, cause);
}
/**
@@ -286,9 +281,20 @@ public class JexlException extends Runti
* Creates a new Method exception instance.
* @param node the offending ASTnode
* @param name the unknown method
+ * @param cause the exception causing the error
+ */
+ public Method(JexlNode node, String name, Throwable cause) {
+ super(node, name, cause);
+ }
+
+ /**
+ * Creates a new Method exception instance.
+ * @param info the location information
+ * @param name the unknown method
+ * @param cause the exception causing the error
*/
- public Method(JexlNode node, String name) {
- super(node, name);
+ public Method(JexlInfo info, String name, Throwable cause) {
+ super(info, name, cause);
}
/**
@@ -319,7 +325,7 @@ public class JexlException extends Runti
* @param value the returned value
*/
public Return(JexlNode node, String msg, Object value) {
- super(node, msg);
+ super(node, msg, null);
this.result = value;
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Debugger.java Sat Feb 11 11:26:42 2012
@@ -17,6 +17,7 @@
package org.apache.commons.jexl3.internal;
import java.util.regex.Pattern;
+import org.apache.commons.jexl3.JexlExpression;
import org.apache.commons.jexl3.JexlScript;
import org.apache.commons.jexl3.parser.ASTAdditiveNode;
import org.apache.commons.jexl3.parser.ASTAdditiveOperator;
@@ -41,6 +42,7 @@ import org.apache.commons.jexl3.parser.A
import org.apache.commons.jexl3.parser.ASTGTNode;
import org.apache.commons.jexl3.parser.ASTIdentifier;
import org.apache.commons.jexl3.parser.ASTIfStatement;
+import org.apache.commons.jexl3.parser.ASTJexlLambda;
import org.apache.commons.jexl3.parser.ASTJexlScript;
import org.apache.commons.jexl3.parser.ASTLENode;
import org.apache.commons.jexl3.parser.ASTLTNode;
@@ -101,6 +103,19 @@ public final class Debugger extends Pars
}
/**
+ * Position the debugger on the root of an expression.
+ * @param jscript the expression
+ * @return true if the expression was a {@link Script} instance, false otherwise
+ */
+ public boolean debug(JexlExpression jscript) {
+ if (jscript instanceof Script) {
+ return debug(((Script) jscript).script);
+ } else {
+ return false;
+ }
+ }
+
+ /**
* Position the debugger on the root of a script.
* @param jscript the script
* @return true if the script was a {@link Script} instance, false otherwise
@@ -140,8 +155,7 @@ public final class Debugger extends Pars
public String data() {
return builder.toString();
}
-
-
+
/**
* Rebuilds an expression from a Jexl node.
* @param node the node to rebuilt from
@@ -431,14 +445,15 @@ public final class Debugger extends Pars
protected Object visit(ASTGTNode node, Object data) {
return infixChildren(node, " > ", false, data);
}
-
/** Checks identifiers that contain space, quote, double-quotes or backspace. */
private static final Pattern QUOTED_IDENTIFIER = Pattern.compile("['\"\\s\\\\]");
+ /** Checks number used as identifiers. */
+ private static final Pattern NUMBER_IDENTIFIER = Pattern.compile("^\\d*$");
@Override
protected Object visit(ASTIdentifier node, Object data) {
String image = node.image;
- if (QUOTED_IDENTIFIER.matcher(image).find()) {
+ if (QUOTED_IDENTIFIER.matcher(image).find() || NUMBER_IDENTIFIER.matcher(image).find()) {
// quote it
image = "'" + node.image.replace("'", "\\'") + "'";
}
@@ -471,6 +486,18 @@ public final class Debugger extends Pars
@Override
protected Object visit(ASTJexlScript node, Object data) {
+ if (node instanceof ASTJexlLambda) {
+ builder.append("function(");
+ String[] params = node.getParameters();
+ if (params != null && params.length > 0) {
+ builder.append(params[0]);
+ for (int p = 1; p < params.length; ++p) {
+ builder.append(", ");
+ builder.append(params[p]);
+ }
+ }
+ builder.append(")");
+ }
int num = node.jjtGetNumChildren();
for (int i = 0; i < num; ++i) {
JexlNode child = node.jjtGetChild(i);
@@ -699,5 +726,4 @@ public final class Debugger extends Pars
}
return data;
}
-
}
\ No newline at end of file
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Engine.java Sat Feb 11 11:26:42 2012
@@ -16,7 +16,6 @@
*/
package org.apache.commons.jexl3.internal;
-
import org.apache.commons.jexl3.JexlArithmetic;
import org.apache.commons.jexl3.JexlBuilder;
import org.apache.commons.jexl3.JexlContext;
@@ -54,7 +53,6 @@ import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -207,7 +205,7 @@ public class Engine extends JexlEngine {
public JexlArithmetic getArithmetic() {
return arithmetic;
}
-
+
@Override
public TemplateEngine createJxltEngine() {
return new TemplateEngine(this);
@@ -263,7 +261,7 @@ public class Engine extends JexlEngine {
public Script createScript(String scriptText) {
return createScript(scriptText, null, null);
}
-
+
@Override
public Script createScript(String scriptText, String... names) {
return createScript(scriptText, null, names);
@@ -275,7 +273,7 @@ public class Engine extends JexlEngine {
throw new NullPointerException("scriptText is null");
}
// Parse the expression
- ASTJexlScript tree = parse(scriptText, info, new Scope(names));
+ ASTJexlScript tree = parse(scriptText, info, new Scope(null, names));
return createScript(tree, scriptText);
}
@@ -334,7 +332,7 @@ public class Engine extends JexlEngine {
expr = "#0" + (expr.charAt(0) == '[' ? "" : ".") + expr + ";";
try {
parser.ALLOW_REGISTERS = true;
- Scope scope = new Scope("#0");
+ Scope scope = new Scope(null, "#0");
ASTJexlScript script = parse(expr, null, scope);
JexlNode node = script.jjtGetChild(0);
Frame frame = script.createFrame(bean);
@@ -365,7 +363,7 @@ public class Engine extends JexlEngine {
expr = "#0" + (expr.charAt(0) == '[' ? "" : ".") + expr + "=" + "#1" + ";";
try {
parser.ALLOW_REGISTERS = true;
- Scope scope = new Scope("#0", "#1");
+ Scope scope = new Scope(null, "#0", "#1");
ASTJexlScript script = parse(expr, null, scope);
JexlNode node = script.jjtGetChild(0);
Frame frame = script.createFrame(bean, value);
@@ -395,10 +393,10 @@ public class Engine extends JexlEngine {
if (method != null) {
result = method.invoke(obj, args);
} else {
- xjexl = new JexlException(info, "failed finding method " + meth);
+ xjexl = new JexlException.Method(info, meth, null);
}
} catch (Exception xany) {
- xjexl = new JexlException(info, "failed executing method " + meth, xany);
+ xjexl = new JexlException.Method(info, meth, xany);
} finally {
if (xjexl != null) {
if (silent) {
@@ -440,10 +438,10 @@ public class Engine extends JexlEngine {
if (ctor != null) {
result = ctor.invoke(clazz, args);
} else {
- xjexl = new JexlException(info, "failed finding constructor for " + clazz.toString());
+ xjexl = new JexlException.Method(info, clazz.toString(), null);
}
} catch (Exception xany) {
- xjexl = new JexlException(info, "failed executing constructor for " + clazz.toString(), xany);
+ xjexl = new JexlException.Method(info, clazz.toString(), xany);
} finally {
if (xjexl != null) {
if (silent) {
@@ -462,7 +460,7 @@ public class Engine extends JexlEngine {
* @param frame the interpreter frame
* @return an Interpreter
*/
- protected Interpreter createInterpreter(JexlContext context, Engine.Frame frame) {
+ protected Interpreter createInterpreter(JexlContext context, Frame frame) {
return new Interpreter(this, context == null ? EMPTY_CONTEXT : context, frame);
}
@@ -662,201 +660,6 @@ public class Engine extends JexlEngine {
}
/**
- * A script scope, stores the declaration of parameters and local variables.
- * @since 3.0
- */
- public static final class Scope {
- /**
- * The number of parameters.
- */
- private final int parms;
- /**
- * The map of named registers aka script parameters.
- * Each parameter is associated to a register and is materialized as an offset in the registers array used
- * during evaluation.
- */
- private Map<String, Integer> namedRegisters = null;
-
- /**
- * Creates a new scope with a list of parameters.
- * @param parameters the list of parameters
- */
- public Scope(String... parameters) {
- if (parameters != null) {
- parms = parameters.length;
- namedRegisters = new LinkedHashMap<String, Integer>();
- for (int p = 0; p < parms; ++p) {
- namedRegisters.put(parameters[p], p);
- }
- } else {
- parms = 0;
- }
- }
-
- @Override
- public int hashCode() {
- return namedRegisters == null ? 0 : parms ^ namedRegisters.hashCode();
- }
-
- @Override
- public boolean equals(Object o) {
- return o instanceof Scope && equals((Scope) o);
- }
-
- /**
- * Whether this frame is equal to another.
- * @param frame the frame to compare to
- * @return true if equal, false otherwise
- */
- public boolean equals(Scope frame) {
- if (this == frame) {
- return true;
- } else if (frame == null || parms != frame.parms) {
- return false;
- } else if (namedRegisters == null) {
- return frame.namedRegisters == null;
- } else {
- return namedRegisters.equals(frame.namedRegisters);
- }
- }
-
- /**
- * Checks whether an identifier is a local variable or argument, ie stored in a register.
- * @param name the register name
- * @return the register index
- */
- public Integer getRegister(String name) {
- return namedRegisters != null ? namedRegisters.get(name) : null;
- }
-
- /**
- * Declares a local variable.
- * <p>
- * This method creates an new entry in the named register map.
- * </p>
- * @param name the variable name
- * @return the register index storing this variable
- */
- public Integer declareVariable(String name) {
- if (namedRegisters == null) {
- namedRegisters = new LinkedHashMap<String, Integer>();
- }
- Integer register = namedRegisters.get(name);
- if (register == null) {
- register = Integer.valueOf(namedRegisters.size());
- namedRegisters.put(name, register);
- }
- return register;
- }
-
- /**
- * Creates a frame by copying values up to the number of parameters.
- * @param values the argument values
- * @return the arguments array
- */
- public Frame createFrame(Object... values) {
- if (namedRegisters != null) {
- Object[] arguments = new Object[namedRegisters.size()];
- if (values != null) {
- System.arraycopy(values, 0, arguments, 0, Math.min(parms, values.length));
- }
- return new Frame(arguments, namedRegisters.keySet().toArray(new String[0]));
- } else {
- return null;
- }
- }
-
- /**
- * Gets the (maximum) number of arguments this script expects.
- * @return the number of parameters
- */
- public int getArgCount() {
- return parms;
- }
-
- /**
- * Gets this script registers, i.e. parameters and local variables.
- * @return the register names
- */
- public String[] getRegisters() {
- return namedRegisters != null ? namedRegisters.keySet().toArray(new String[0]) : new String[0];
- }
-
- /**
- * Gets this script parameters, i.e. registers assigned before creating local variables.
- * @return the parameter names
- */
- public String[] getParameters() {
- if (namedRegisters != null && parms > 0) {
- String[] pa = new String[parms];
- int p = 0;
- for (Map.Entry<String, Integer> entry : namedRegisters.entrySet()) {
- if (entry.getValue().intValue() < parms) {
- pa[p++] = entry.getKey();
- }
- }
- return pa;
- } else {
- return null;
- }
- }
-
- /**
- * Gets this script local variable, i.e. registers assigned to local variables.
- * @return the parameter names
- */
- public String[] getLocalVariables() {
- if (namedRegisters != null && parms > 0) {
- String[] pa = new String[parms];
- int p = 0;
- for (Map.Entry<String, Integer> entry : namedRegisters.entrySet()) {
- if (entry.getValue().intValue() >= parms) {
- pa[p++] = entry.getKey();
- }
- }
- return pa;
- } else {
- return null;
- }
- }
- }
-
- /**
- * A call frame, created from a scope, stores the arguments and local variables as "registers".
- * @since 3.0
- */
- public static final class Frame {
- /** Registers or arguments. */
- private final Object[] registers;
- /** Parameter and argument names if any. */
- private final String[] parameters;
-
- /**
- * Creates a new frame.
- * @param r the registers
- * @param p the parameters
- */
- Frame(Object[] r, String[] p) {
- registers = r;
- parameters = p;
- }
-
- /**
- * @return the registers
- */
- public Object[] getRegisters() {
- return registers;
- }
-
- /**
- * @return the parameters
- */
- public String[] getParameters() {
- return parameters;
- }
- }
-
- /**
* Parses an expression.
* @param expression the expression to parse
* @param info debug information structure
@@ -886,13 +689,7 @@ public class Engine extends JexlEngine {
} else {
jexlInfo = info;
}
- parser.setFrame(frame);
- script = parser.parse(reader, jexlInfo);
- // reaccess in case local variables have been declared
- frame = parser.getFrame();
- if (frame != null) {
- script.setScope(frame);
- }
+ script = parser.parse(reader, frame, jexlInfo);
if (cache != null) {
cache.put(expr, script);
}
@@ -952,5 +749,4 @@ public class Engine extends JexlEngine {
}
return info;
}
-
}
Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Frame.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Frame.java?rev=1243029&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Frame.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Frame.java Sat Feb 11 11:26:42 2012
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.jexl3.internal;
+
+/**
+ * A call frame, created from a scope, stores the arguments and local variables as "registers".
+ * @since 3.0
+ */
+public final class Frame {
+ /** Registers or arguments. */
+ final Object[] registers;
+ /** Parameter and argument names if any. */
+ final String[] parameters;
+
+ /**
+ * Creates a new frame.
+ * @param r the registers
+ * @param p the parameters
+ */
+ public Frame(Object[] r, String[] p) {
+ registers = r;
+ parameters = p;
+ }
+
+ /**
+ * @return the registers
+ */
+ public Object[] getRegisters() {
+ return registers;
+ }
+
+ /**
+ * @return the parameters
+ */
+ public String[] getParameters() {
+ return parameters;
+ }
+
+ /**
+ * Assign arguments to the frame.
+ * @param values the argument values
+ * @return this frame
+ */
+ public Frame assign(Object... values) {
+ if (registers != null && values != null && values.length > 0) {
+ System.arraycopy(values, 0, registers, 0, Math.min(registers.length, values.length));
+ }
+ return this;
+ }
+
+}
Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Frame.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java Sat Feb 11 11:26:42 2012
@@ -89,6 +89,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import org.apache.commons.jexl3.parser.ASTJexlLambda;
/**
* An interpreter of JEXL syntax.
@@ -96,6 +97,8 @@ import java.util.Set;
* @since 2.0
*/
public class Interpreter extends ParserVisitor {
+ /** The JEXL engine. */
+ protected final Engine jexl;
/** The logger. */
protected final Log logger;
/** The uberspect. */
@@ -117,9 +120,7 @@ public class Interpreter extends ParserV
/** Cache executors. */
protected final boolean cache;
/** Registers or arguments. */
- protected final Object[] registers;
- /** Parameter names if any. */
- protected final String[] parameters;
+ protected final Frame frame;
/** Cancellation support. */
protected volatile boolean cancelled = false;
/** Empty parameters for method matching. */
@@ -127,20 +128,21 @@ public class Interpreter extends ParserV
/**
* Creates an interpreter.
- * @param jexl the engine creating this interpreter
+ * @param engine the engine creating this interpreter
* @param aContext the context to evaluate expression
* @param frame the engine evaluation frame
*/
- protected Interpreter(Engine jexl, JexlContext aContext, Engine.Frame frame) {
+ protected Interpreter(Engine engine, JexlContext aContext, Frame eFrame) {
+ this.jexl = engine;
this.logger = jexl.logger;
this.uberspect = jexl.uberspect;
- this.context = aContext != null? aContext : Engine.EMPTY_CONTEXT;
+ this.context = aContext != null ? aContext : Engine.EMPTY_CONTEXT;
if (this.context instanceof JexlEngine.Options) {
JexlEngine.Options opts = (JexlEngine.Options) context;
Boolean ostrict = opts.isStrict();
Boolean osilent = opts.isSilent();
- this.strictEngine = ostrict == null? jexl.isStrict() : ostrict.booleanValue();
- this.silent = osilent == null? jexl.isSilent() : osilent.booleanValue();
+ this.strictEngine = ostrict == null ? jexl.isStrict() : ostrict.booleanValue();
+ this.silent = osilent == null ? jexl.isSilent() : osilent.booleanValue();
this.arithmetic = jexl.arithmetic.options(opts);
} else {
this.strictEngine = jexl.isStrict();
@@ -150,26 +152,24 @@ public class Interpreter extends ParserV
this.functions = jexl.functions;
this.strictArithmetic = this.arithmetic.isStrict();
this.cache = jexl.cache != null;
- if (frame != null) {
- this.parameters = frame.getParameters();
- this.registers = frame.getRegisters();
- } else {
- this.parameters = null;
- this.registers = null;
- }
+ this.frame = eFrame;
this.functors = null;
}
- /**
- * Checks whether this interpreter considers unknown variables, methods and constructors as errors.
- * @return true if isStrict, false otherwise
- */
-
- /**
- * Checks whether this interpreter throws JexlException when encountering errors.
- * @return true if silent, false otherwise
- */
-
+ protected Interpreter(Interpreter copy, Frame eFrame) {
+ this.jexl = copy.jexl;
+ this.logger = copy.logger;
+ this.uberspect = copy.uberspect;
+ this.context = copy.context;
+ this.arithmetic = copy.arithmetic;
+ this.silent = copy.silent;
+ this.functions = copy.functions;
+ this.strictEngine = copy.strictEngine;
+ this.strictArithmetic = copy.strictArithmetic;
+ this.cache = copy.cache;
+ this.frame = eFrame;
+ this.functors = null;
+ }
/**
* Interpret the given script/expression.
@@ -207,7 +207,7 @@ public class Interpreter extends ParserV
*/
protected JexlNode findNullOperand(RuntimeException xrt, JexlNode node, Object left, Object right) {
if (xrt instanceof ArithmeticException
- && (Object) JexlException.NULL_OPERAND == xrt.getMessage()) {
+ && (Object) JexlException.NULL_OPERAND == xrt.getMessage()) {
if (left == null) {
return node.jjtGetChild(0);
}
@@ -283,7 +283,7 @@ public class Interpreter extends ParserV
if (namespace == null) {
namespace = functions.get(prefix);
if (prefix != null && namespace == null) {
- throw new JexlException(node, "no such function namespace " + prefix);
+ throw new JexlException(node, "no such function namespace " + prefix, null);
}
}
// allow namespace to be instantiated as functor with context if possible, not an error otherwise
@@ -422,7 +422,7 @@ public class Interpreter extends ParserV
// determine initial object & property:
JexlNode objectNode = null;
- Object object = register >= 0 ? registers[register] : null;
+ Object object = register >= 0 ? frame.registers[register] : null;
JexlNode propertyNode = null;
Object property = null;
boolean isVariable = true;
@@ -504,7 +504,7 @@ public class Interpreter extends ParserV
}
// deal with ant variable; set context
if (isRegister) {
- registers[register] = right;
+ frame.registers[register] = right;
return right;
} else if (antVar) {
if (isVariable && object == null) {
@@ -668,7 +668,7 @@ public class Interpreter extends ParserV
if (register < 0) {
context.set(loopVariable.image, value);
} else {
- registers[register] = value;
+ frame.registers[register] = value;
}
// execute statement
result = statement.jjtAccept(this, data);
@@ -766,7 +766,7 @@ public class Interpreter extends ParserV
if (data == null) {
int register = node.getRegister();
if (register >= 0) {
- return registers[register];
+ return frame.registers[register];
}
Object value = context.get(name);
if (value == null
@@ -824,13 +824,37 @@ public class Interpreter extends ParserV
@Override
protected Object visit(ASTJexlScript node, Object data) {
- int numChildren = node.jjtGetNumChildren();
- Object result = null;
- for (int i = 0; i < numChildren; i++) {
- JexlNode child = node.jjtGetChild(i);
- result = child.jjtAccept(this, data);
+ if (node instanceof ASTJexlLambda) {
+ return new Closure((ASTJexlLambda) node, frame);
+ } else {
+ final int numChildren = node.jjtGetNumChildren();
+ Object result = null;
+ for (int i = 0; i < numChildren; i++) {
+ JexlNode child = node.jjtGetChild(i);
+ result = child.jjtAccept(this, data);
+ }
+ return result;
}
- return result;
+ }
+
+ private static final class Closure {
+ Frame frame;
+ ASTJexlLambda lambda;
+ Closure(ASTJexlLambda l, Frame f) {
+ lambda = l;
+ frame = lambda.createFrame(f);
+ }
+ }
+
+ private Object call(Closure closure, Object[] argv) {
+ Frame cframe = closure.frame;
+ if (cframe != null) {
+ cframe.assign(argv);
+ }
+ ASTJexlLambda lambda = closure.lambda;
+ JexlNode block = lambda.jjtGetChild(lambda.jjtGetNumChildren() - 1);
+ Interpreter interpreter = new Interpreter(this, cframe);
+ return interpreter.interpret(block);
}
@Override
@@ -915,40 +939,49 @@ public class Interpreter extends ParserV
}
}
boolean cacheable = cache;
- JexlMethod vm = uberspect.getMethod(bean, methodName, argv);
- // DG: If we can't find an exact match, narrow the parameters and try again
- if (vm == null) {
- if (arithmetic.narrowArguments(argv)) {
- vm = uberspect.getMethod(bean, methodName, argv);
+ boolean narrow = true;
+ JexlMethod vm = null;
+ // pseudo loop
+ while (true) {
+ vm = uberspect.getMethod(bean, methodName, argv);
+ if (vm != null) {
+ break;
}
- if (vm == null) {
- Object functor = null;
- // could not find a method, try as a var
- if (bean == context) {
- int register = methodNode.getRegister();
- if (register >= 0) {
- functor = registers[register];
- } else {
- functor = context.get(methodName);
- }
+ Object functor = null;
+ // could not find a method, try as a var
+ if (bean == context) {
+ int register = methodNode.getRegister();
+ if (register >= 0) {
+ functor = frame.registers[register];
} else {
- JexlPropertyGet gfunctor = uberspect.getPropertyGet(bean, methodName);
- if (gfunctor != null) {
- functor = gfunctor.tryInvoke(bean, methodName);
- }
+ functor = context.get(methodName);
}
- // script of jexl method will do
- if (functor instanceof JexlScript) {
- return ((JexlScript) functor).execute(context, argv.length > 0 ? argv : null);
- } else if (functor instanceof JexlMethod) {
- vm = (JexlMethod) functor;
- cacheable = false;
- } else {
- xjexl = new JexlException.Method(node, methodName);
+ } else {
+ JexlPropertyGet gfunctor = uberspect.getPropertyGet(bean, methodName);
+ if (gfunctor != null) {
+ functor = gfunctor.tryInvoke(bean, methodName);
}
}
+ // lambda, script or jexl method will do
+ if (functor instanceof Closure) {
+ return call((Closure) functor, argv);
+ }
+ if (functor instanceof JexlScript) {
+ return ((JexlScript) functor).execute(context, argv);
+ }
+ if (functor instanceof JexlMethod) {
+ return ((JexlMethod) functor).invoke(bean, argv);
+ }
+ // if we did not find an exact match and we haven't tried yet,
+ // attempt to narrow the parameters and if this succeeds, try again
+ if (narrow && arithmetic.narrowArguments(argv)) {
+ narrow = false;
+ } else {
+ break;
+ }
}
- if (xjexl == null) {
+ // we have either evaluated and returned or might have found a method
+ if (vm != null) {
// vm cannot be null if xjexl is null
Object eval = vm.invoke(bean, argv);
// cache executor in volatile JexlNode.value
@@ -956,11 +989,11 @@ public class Interpreter extends ParserV
node.jjtSetValue(vm);
}
return eval;
+ } else {
+ xjexl = new JexlException.Method(node, methodName, null);
}
- } catch (InvocationTargetException e) {
- xjexl = new JexlException(node, "method invocation error", e.getCause());
- } catch (Exception e) {
- xjexl = new JexlException(node, "method error", e);
+ } catch (Exception xany) {
+ xjexl = new JexlException(node, methodName, xany);
}
return invocationFailed(xjexl);
}
@@ -1029,7 +1062,8 @@ public class Interpreter extends ParserV
ctor = uberspect.getConstructor(cobject, argv);
}
if (ctor == null) {
- xjexl = new JexlException.Method(node, cobject.toString());
+ String dbgStr = cobject != null ? cobject.toString() : null;
+ xjexl = new JexlException.Method(node, dbgStr, null);
}
}
if (xjexl == null) {
@@ -1040,10 +1074,9 @@ public class Interpreter extends ParserV
}
return instance;
}
- } catch (InvocationTargetException e) {
- xjexl = new JexlException(node, "constructor invocation error", e.getCause());
- } catch (Exception e) {
- xjexl = new JexlException(node, "constructor error", e);
+ } catch (Exception xany) {
+ String dbgStr = cobject != null ? cobject.toString() : null;
+ xjexl = new JexlException(node, dbgStr, xany);
}
return invocationFailed(xjexl);
}
@@ -1221,10 +1254,10 @@ public class Interpreter extends ParserV
// variable unknow in context and not (from) a register
&& !(context.has(variableName.toString())
|| (numChildren == 1
- && node.jjtGetChild(0) instanceof ASTIdentifier
- && ((ASTIdentifier) node.jjtGetChild(0)).getRegister() >= 0))) {
+ && node.jjtGetChild(0) instanceof ASTIdentifier
+ && ((ASTIdentifier) node.jjtGetChild(0)).getRegister() >= 0))) {
JexlException xjexl = propertyName != null
- ? new JexlException.Property(node, propertyName)
+ ? new JexlException.Property(node, variableName.toString())
: new JexlException.Variable(node, variableName.toString());
return unknownVariable(xjexl);
}
@@ -1423,16 +1456,13 @@ public class Interpreter extends ParserV
}
return value;
} catch (Exception xany) {
- if (node == null) {
- throw new RuntimeException(xany);
- } else {
- JexlException xjexl = new JexlException.Property(node, attribute.toString());
- if (strictArithmetic) {
- throw xjexl;
- }
- if (!silent) {
- logger.warn(xjexl.getMessage());
- }
+ String attrStr = attribute != null ? attribute.toString() : null;
+ JexlException xjexl = new JexlException.Property(node, attrStr, xany);
+ if (strictArithmetic) {
+ throw xjexl;
+ }
+ if (!silent) {
+ logger.warn(xjexl.getMessage());
}
}
}
Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java?rev=1243029&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java Sat Feb 11 11:26:42 2012
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.jexl3.internal;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * A script scope, stores the declaration of parameters and local variables.
+ * @since 3.0
+ */
+public final class Scope {
+ /**
+ * The parent scope.
+ */
+ private Scope parent = null;
+ /**
+ * The number of parameters.
+ */
+ private int parms;
+ /**
+ * The number of local variables.
+ */
+ private int vars;
+ /**
+ * The number of hoisted variables.
+ */
+ private int hoisted;
+ /**
+ * The map of named registers aka script parameters.
+ * Each parameter is associated to a register and is materialized as an offset in the registers array used
+ * during evaluation.
+ */
+ private Map<String, Integer> namedRegisters = null;
+ /**
+ * The map of registers to parent registers when hoisted by closure.
+ */
+ private Map<Integer, Integer> hoistedRegisters = null;
+
+ /**
+ * Creates a new scope with a list of parameters.
+ * @param parameters the list of parameters
+ */
+ public Scope(Scope scope, String... parameters) {
+ if (parameters != null) {
+ parms = parameters.length;
+ namedRegisters = new LinkedHashMap<String, Integer>();
+ for (int p = 0; p < parms; ++p) {
+ namedRegisters.put(parameters[p], p);
+ }
+ } else {
+ parms = 0;
+ }
+ vars = 0;
+ hoisted = 0;
+ parent = scope;
+ }
+
+ @Override
+ public int hashCode() {
+ return namedRegisters == null ? 0 : parms ^ namedRegisters.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof Scope && equals((Scope) o);
+ }
+
+ /**
+ * Whether this frame is equal to another.
+ * @param frame the frame to compare to
+ * @return true if equal, false otherwise
+ */
+ public boolean equals(Scope frame) {
+ if (this == frame) {
+ return true;
+ } else if (frame == null || parms != frame.parms) {
+ return false;
+ } else if (namedRegisters == null) {
+ return frame.namedRegisters == null;
+ } else {
+ return namedRegisters.equals(frame.namedRegisters);
+ }
+ }
+
+ /**
+ * Checks whether an identifier is a local variable or argument, ie stored in a register.
+ * If this fails, attempt to solve by hoisting parent registers.
+ * @param name the register name
+ * @return the register index
+ */
+ public Integer getRegister(String name) {
+ return getRegister(name, true);
+ }
+
+ /**
+ * Checks whether an identifier is a local variable or argument, ie stored in a register.
+ * @param name the register name
+ * @param hoist whether solving by hoisting parent registers is allowed
+ * @return the register index
+ */
+ private Integer getRegister(String name, boolean hoist) {
+ Integer register = namedRegisters != null ? namedRegisters.get(name) : null;
+ if (register == null && hoist && parent != null) {
+ Integer pr = parent.getRegister(name, false);
+ if (pr != null) {
+ if (hoistedRegisters == null) {
+ hoistedRegisters = new LinkedHashMap<Integer, Integer>();
+ }
+ register = Integer.valueOf(namedRegisters.size());
+ if (namedRegisters == null) {
+ namedRegisters = new LinkedHashMap<String, Integer>();
+ }
+ namedRegisters.put(name, register);
+ hoistedRegisters.put(register, pr);
+ hoisted += 1;
+ }
+ }
+ return register;
+ }
+
+ /**
+ * Declares a parameter.
+ * <p>
+ * This method creates an new entry in the named register map.
+ * </p>
+ * @param name the parameter name
+ */
+ public void declareParameter(String name) {
+ if (namedRegisters == null) {
+ namedRegisters = new LinkedHashMap<String, Integer>();
+ } else if (vars > 0) {
+ throw new IllegalStateException("cant declare parameters after variables");
+ }
+ Integer register = namedRegisters.get(name);
+ if (register == null) {
+ register = Integer.valueOf(namedRegisters.size());
+ namedRegisters.put(name, register);
+ parms += 1;
+ }
+ }
+
+ /**
+ * Declares a local variable.
+ * <p>
+ * This method creates an new entry in the named register map.
+ * </p>
+ * @param name the variable name
+ * @return the register index storing this variable
+ */
+ public Integer declareVariable(String name) {
+ if (namedRegisters == null) {
+ namedRegisters = new LinkedHashMap<String, Integer>();
+ }
+ Integer register = namedRegisters.get(name);
+ if (register == null) {
+ register = Integer.valueOf(namedRegisters.size());
+ namedRegisters.put(name, register);
+ vars += 1;
+ }
+ return register;
+ }
+
+ /**
+ * Creates a frame by copying values up to the number of parameters.
+ * @param values the argument values
+ * @return the arguments array
+ */
+ public Frame createFrame(Frame caller) {
+ if (namedRegisters != null) {
+ Object[] arguments = new Object[namedRegisters.size()];
+ if (caller != null && hoistedRegisters != null && parent != null) {
+ for (Map.Entry<Integer, Integer> hoist : hoistedRegisters.entrySet()) {
+ Integer target = hoist.getKey();
+ Integer source = hoist.getValue();
+ Object arg = caller.registers[source.intValue()];
+ arguments[target.intValue()] = arg;
+ }
+ }
+ return new Frame(arguments, namedRegisters.keySet().toArray(new String[namedRegisters.size()]));
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Gets the (maximum) number of arguments this script expects.
+ * @return the number of parameters
+ */
+ public int getArgCount() {
+ return parms;
+ }
+
+ /**
+ * Gets this script registers, i.e. parameters and local variables.
+ * @return the register names
+ */
+ public String[] getRegisters() {
+ return namedRegisters != null ? namedRegisters.keySet().toArray(new String[0]) : new String[0];
+ }
+
+ /**
+ * Gets this script parameters, i.e. registers assigned before creating local variables.
+ * @return the parameter names
+ */
+ public String[] getParameters() {
+ if (namedRegisters != null && parms > 0) {
+ String[] pa = new String[parms];
+ int p = 0;
+ for (Map.Entry<String, Integer> entry : namedRegisters.entrySet()) {
+ if (entry.getValue().intValue() < parms) {
+ pa[p++] = entry.getKey();
+ }
+ }
+ return pa;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Gets this script local variable, i.e. registers assigned to local variables.
+ * @return the parameter names
+ */
+ public String[] getLocalVariables() {
+ if (namedRegisters != null && vars > 0) {
+ String[] pa = new String[parms];
+ int p = 0;
+ for (Map.Entry<String, Integer> entry : namedRegisters.entrySet()) {
+ if (entry.getValue().intValue() >= parms) {
+ pa[p++] = entry.getKey();
+ }
+ }
+ return pa;
+ } else {
+ return null;
+ }
+ }
+
+}
Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Scope.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Script.java Sat Feb 11 11:26:42 2012
@@ -57,7 +57,7 @@ public class Script implements JexlScrip
if (script.jjtGetNumChildren() < 1) {
return null;
}
- Engine.Frame frame = script.createFrame((Object[]) null);
+ Frame frame = script.createFrame((Object[]) null);
Interpreter interpreter = jexl.createInterpreter(context, frame);
return interpreter.interpret(script.jjtGetChild(0));
}
@@ -94,7 +94,7 @@ public class Script implements JexlScrip
*/
@Override
public Object execute(JexlContext context) {
- Engine.Frame frame = script.createFrame((Object[]) null);
+ Frame frame = script.createFrame((Object[]) null);
Interpreter interpreter = jexl.createInterpreter(context, frame);
return interpreter.interpret(script);
}
@@ -104,7 +104,7 @@ public class Script implements JexlScrip
*/
@Override
public Object execute(JexlContext context, Object... args) {
- Engine.Frame frame = script.createFrame(args);
+ Frame frame = script.createFrame(args != null && args.length > 0? args : null);
Interpreter interpreter = jexl.createInterpreter(context, frame);
return interpreter.interpret(script);
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/TemplateEngine.java Sat Feb 11 11:26:42 2012
@@ -257,7 +257,7 @@ public final class TemplateEngine extend
@Override
public final TemplateExpression prepare(JexlContext context) {
try {
- Engine.Frame frame = context instanceof TemplateContext
+ Frame frame = context instanceof TemplateContext
? ((TemplateContext) context).getFrame()
: null;
Interpreter interpreter = jexl.createInterpreter(context, frame);
@@ -275,7 +275,7 @@ public final class TemplateEngine extend
@Override
public final Object evaluate(JexlContext context) {
try {
- Engine.Frame frame = context instanceof TemplateContext
+ Frame frame = context instanceof TemplateContext
? ((TemplateContext) context).getFrame()
: null;
Interpreter interpreter = jexl.createInterpreter(context, frame);
@@ -681,7 +681,7 @@ public final class TemplateEngine extend
* @return the unified expression instance
* @throws JexlException if an error occur during parsing
*/
- private TemplateExpression parseExpression(String expr, Engine.Scope scope) {
+ private TemplateExpression parseExpression(String expr, Scope scope) {
final int size = expr.length();
ExpressionBuilder builder = new ExpressionBuilder(0);
StringBuilder strb = new StringBuilder(size);
@@ -893,7 +893,7 @@ public final class TemplateEngine extend
if (reader == null) {
throw new NullPointerException("null input");
}
- Engine.Scope scope = new Engine.Scope(parms);
+ Scope scope = new Scope(null, parms);
prefix = directive;
List<Block> blocks = readTemplate(prefix, reader);
List<TemplateExpression> uexprs = new ArrayList<TemplateExpression>();
@@ -973,7 +973,7 @@ public final class TemplateEngine extend
@Override
public TemplateScript prepare(JexlContext context) {
- Engine.Frame frame = script.createFrame((Object[]) null);
+ Frame frame = script.createFrame((Object[]) null);
TemplateContext tcontext = new TemplateContext(context, frame, exprs, null);
TemplateExpression[] immediates = new TemplateExpression[exprs.length];
for (int e = 0; e < exprs.length; ++e) {
@@ -989,7 +989,7 @@ public final class TemplateEngine extend
@Override
public void evaluate(JexlContext context, Writer writer, Object... args) {
- Engine.Frame frame = script.createFrame(args);
+ Frame frame = script.createFrame(args);
TemplateContext tcontext = new TemplateContext(context, frame, exprs, writer);
Interpreter interpreter = jexl.createInterpreter(tcontext, frame);
interpreter.interpret(script);
@@ -1009,7 +1009,7 @@ public final class TemplateEngine extend
/** The writer used to output. */
private final Writer writer;
/** The call frame. */
- private final Engine.Frame frame;
+ private final Frame frame;
/**
* Creates a TemplateScript context instance.
@@ -1018,7 +1018,7 @@ public final class TemplateEngine extend
* @param expressions the list of TemplateExpression from the TemplateScript to evaluate
* @param out the output writer
*/
- protected TemplateContext(JexlContext jcontext, Engine.Frame jframe,
+ protected TemplateContext(JexlContext jcontext, Frame jframe,
UnifiedExpression[] expressions, Writer out) {
wrap = jcontext;
frame = jframe;
@@ -1030,7 +1030,7 @@ public final class TemplateEngine extend
* Gets this context calling frame.
* @return the engine frame
*/
- public Engine.Frame getFrame() {
+ public Frame getFrame() {
return frame;
}
Copied: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlLambda.java (from r1211892, commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java)
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlLambda.java?p2=commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlLambda.java&p1=commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java&r1=1211892&r2=1243029&rev=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlLambda.java Sat Feb 11 11:26:42 2012
@@ -16,81 +16,32 @@
*/
package org.apache.commons.jexl3.parser;
-import org.apache.commons.jexl3.internal.Engine;
+import org.apache.commons.jexl3.internal.Frame;
/**
* Enhanced script to allow parameters declaration.
*/
-public class ASTJexlScript extends JexlNode {
- /** The script scope. */
- private Engine.Scope scope = null;
-
- public ASTJexlScript(int id) {
+public class ASTJexlLambda extends ASTJexlScript {
+ public ASTJexlLambda(int id) {
super(id);
}
- public ASTJexlScript(Parser p, int id) {
+ public ASTJexlLambda(Parser p, int id) {
super(p, id);
}
-
- @Override
- public Object jjtAccept(ParserVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-
- /**
- * Sets the parameters and registers
- * @param theScope the scope
- */
- public void setScope(Engine.Scope theScope) {
- this.scope = theScope;
- }
-
- /**
- * Gets this script scope.
- */
- public Engine.Scope getScope() {
- return scope;
- }
-
+
/**
* Creates an array of arguments by copying values up to the number of parameters.
* @param values the argument values
* @return the arguments array
*/
- public Engine.Frame createFrame(Object... values) {
- return scope != null? scope.createFrame(values) : null;
- }
-
- /**
- * Gets the (maximum) number of arguments this script expects.
- * @return the number of parameters
- */
- public int getArgCount() {
- return scope != null? scope.getArgCount() : 0;
- }
-
- /**
- * Gets this script registers, i.e. parameters and local variables.
- * @return the register names
- */
- public String[] getRegisters() {
- return scope != null? scope.getRegisters() : null;
- }
-
- /**
- * Gets this script parameters, i.e. registers assigned before creating local variables.
- * @return the parameter names
- */
- public String[] getParameters() {
- return scope != null? scope.getParameters() : null;
- }
-
- /**
- * Gets this script local variable, i.e. registers assigned to local variables.
- * @return the parameter names
- */
- public String[] getLocalVariables() {
- return scope != null? scope.getLocalVariables() : null;
+ public Frame createFrame(Frame frame, Object... values) {
+ if (scope != null) {
+ Frame cframe = scope.createFrame(frame);
+ if (cframe != null) {
+ return cframe.assign(values);
+ }
+ }
+ return null;
}
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTJexlScript.java Sat Feb 11 11:26:42 2012
@@ -17,13 +17,15 @@
package org.apache.commons.jexl3.parser;
import org.apache.commons.jexl3.internal.Engine;
+import org.apache.commons.jexl3.internal.Frame;
+import org.apache.commons.jexl3.internal.Scope;
/**
* Enhanced script to allow parameters declaration.
*/
public class ASTJexlScript extends JexlNode {
/** The script scope. */
- private Engine.Scope scope = null;
+ protected Scope scope = null;
public ASTJexlScript(int id) {
super(id);
@@ -42,14 +44,14 @@ public class ASTJexlScript extends JexlN
* Sets the parameters and registers
* @param theScope the scope
*/
- public void setScope(Engine.Scope theScope) {
+ public void setScope(Scope theScope) {
this.scope = theScope;
}
/**
* Gets this script scope.
*/
- public Engine.Scope getScope() {
+ public Scope getScope() {
return scope;
}
@@ -58,8 +60,13 @@ public class ASTJexlScript extends JexlN
* @param values the argument values
* @return the arguments array
*/
- public Engine.Frame createFrame(Object... values) {
- return scope != null? scope.createFrame(values) : null;
+ public Frame createFrame(Object... values) {
+ if (scope != null) {
+ Frame frame = scope.createFrame(null);
+ return frame != null? frame.assign(values) : null;
+ } else {
+ return null;
+ }
}
/**
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java Sat Feb 11 11:26:42 2012
@@ -16,21 +16,25 @@
*/
package org.apache.commons.jexl3.parser;
-import org.apache.commons.jexl3.internal.Engine;
+import java.io.Reader;
+import java.util.Stack;
import org.apache.commons.jexl3.JexlException;
import org.apache.commons.jexl3.JexlInfo;
+import org.apache.commons.jexl3.internal.Engine;
+import org.apache.commons.jexl3.internal.Scope;
/**
* The base class for parsing, manages the parameter/local variable frame.
* @author henri
*/
-public class JexlParser extends StringParser {
+public abstract class JexlParser extends StringParser {
/**
* The map of named registers aka script parameters.
* Each parameter is associated to a register and is materialized as an offset in the registers array used
* during evaluation.
*/
- protected Engine.Scope frame;
+ protected Scope frame = null;
+ protected Stack<Scope> frames = new Stack<Scope>();
/**
* Sets the frame to use bythis parser.
@@ -39,7 +43,7 @@ public class JexlParser extends StringPa
* </p>
* @param theFrame the register map
*/
- public void setFrame(Engine.Scope theFrame) {
+ public void setFrame(Scope theFrame) {
frame = theFrame;
}
@@ -51,10 +55,31 @@ public class JexlParser extends StringPa
* </p>
* @return the named register map
*/
- public Engine.Scope getFrame() {
+ public Scope getFrame() {
return frame;
}
+ /**
+ * Create a new local variable frame and push it as current scope.
+ */
+ public void pushFrame() {
+ if (frame != null) {
+ frames.push(frame);
+ }
+ frame = new Scope(frame, (String[])null);
+ }
+
+ /**
+ * Pops back to previous local variable frame.
+ */
+ public void popFrame() {
+ if (!frames.isEmpty()) {
+ frame = frames.pop();
+ } else {
+ frame = null;
+ }
+ }
+
/**
* Checks whether an identifier is a local variable or argument, ie stored in a register.
@@ -82,12 +107,27 @@ public class JexlParser extends StringPa
*/
public void declareVariable(ASTVar identifier, String image) {
if (frame == null) {
- frame = new Engine.Scope((String[])null);
+ frame = new Scope(null, (String[])null);
}
Integer register = frame.declareVariable(image);
identifier.setRegister(register.intValue());
identifier.image = image;
}
+
+ /**
+ * Declares a local parameter.
+ * <p>
+ * This method creates an new entry in the named register map.
+ * </p>
+ * @param identifier the identifier used to declare
+ * @param image the variable name
+ */
+ public void declareParameter(String image) {
+ if (frame == null) {
+ frame = new Scope(null, (String[])null);
+ }
+ frame.declareParameter(image);
+ }
/**
* Default implementation does nothing but is overriden by generated code.
@@ -125,5 +165,13 @@ public class JexlParser extends StringPa
}
throw new JexlException.Parsing(dbgInfo, "Ambiguous statement, missing ';' between expressions", null);
}
+ if (n instanceof ASTJexlScript) {
+ ASTJexlScript script = (ASTJexlScript) n;
+ // reaccess in case local variables have been declared
+ if (script.getScope() != frame) {
+ script.setScope(frame);
+ }
+ popFrame();
+ }
}
}
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt (original)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt Sat Feb 11 11:26:42 2012
@@ -32,12 +32,14 @@ package org.apache.commons.jexl3.parser;
import java.io.Reader;
import org.apache.commons.jexl3.JexlInfo;
+import org.apache.commons.jexl3.internal.Engine;
+import org.apache.commons.jexl3.internal.Scope;
public class Parser extends JexlParser
{
public boolean ALLOW_REGISTERS = false;
- public ASTJexlScript parse(Reader reader, JexlInfo info)
+ public ASTJexlScript parse(Reader reader, Scope scope, JexlInfo info)
throws ParseException {
/*
* If registers are allowed, the default parser state has to be REGISTERS.
@@ -51,9 +53,10 @@ public class Parser extends JexlParser
* safe - it's a pain to remember
*/
- ASTJexlScript tree = JexlScript();
- tree.value = info;
- return tree;
+ frame = scope;
+ ASTJexlScript script = JexlScript(scope);
+ script.value = info;
+ return script;
}
}
@@ -92,6 +95,7 @@ PARSER_END(Parser)
| < TRUE : "true" >
| < FALSE : "false" >
| < RETURN : "return" >
+ | < FUNCTION : "function" >
}
<FOR_EACH_IN> TOKEN : /* foreach in */
@@ -110,6 +114,7 @@ PARSER_END(Parser)
| < COLON : ":" >
| < COMMA : "," >
| < DOT : "." >
+ | < LAMBDA : "->" >
}
<*> TOKEN : { /* CONDITIONALS */
@@ -185,7 +190,9 @@ PARSER_END(Parser)
* Statements
***************************************/
-ASTJexlScript JexlScript() : {}
+ASTJexlScript JexlScript(Scope frame) : {
+ jjtThis.setScope(frame);
+}
{
( Statement() )* <EOF>
{ return jjtThis;}
@@ -519,12 +526,12 @@ void SizeFunction() : {}
void Function() #FunctionNode: {}
{
- Identifier() <COLON> Identifier() <LPAREN>[ Expression() ( <COMMA> Expression() )* ] <RPAREN>
+ Identifier(true) <COLON> Identifier() <LPAREN>[ Expression() ( <COMMA> Expression() )* ] <RPAREN>
}
void Method() #MethodNode: {}
{
- Identifier() <LPAREN>[ Expression() ( <COMMA> Expression() )* ] <RPAREN>
+ Identifier(true) <LPAREN>[ Expression() ( <COMMA> Expression() )* ] <RPAREN>
}
void AnyMethod() #void : {}
@@ -544,6 +551,22 @@ void Constructor() #ConstructorNode() :
<NEW> <LPAREN>[ Expression() ( <COMMA> Expression() )* ] <RPAREN>
}
+void DeclareParm() #void :
+{
+ Token t;
+}
+{
+ t=<IDENTIFIER> { declareParameter(t.image); }
+}
+
+void Lambda() #JexlLambda() : {
+ pushFrame();
+}
+{
+ <FUNCTION> <LPAREN>[ DeclareParm() ( <COMMA> DeclareParm() )* ] <RPAREN> Block()
+}
+
+
/***************************************
* References
@@ -564,6 +587,7 @@ void PrimaryExpression() #void : {}
LOOKAHEAD( <LBRACKET> (Expression() | <RBRACKET>) ) ArrayLiteral()
|
Literal()
+| Lambda()
}
void ArrayAccess() : {}
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java Sat Feb 11 11:26:42 2012
@@ -123,7 +123,7 @@ public class ArithmeticTest extends Jexl
asserter.setVariable("aBigDecimal", new BigDecimal("8.8"));
asserter.assertExpression("-3", new Integer("-3"));
- asserter.assertExpression("-3.0", new Float("-3.0"));
+ asserter.assertExpression("-3.0", new Double("-3.0"));
asserter.assertExpression("-aByte", new Byte((byte) -1));
asserter.assertExpression("-aShort", new Short((short) -2));
asserter.assertExpression("-anInteger", new Integer(-3));
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayAccessTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayAccessTest.java?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayAccessTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayAccessTest.java Sat Feb 11 11:26:42 2012
@@ -21,6 +21,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.apache.commons.jexl3.internal.Debugger;
import org.apache.commons.jexl3.junit.Asserter;
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayLiteralTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayLiteralTest.java?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayLiteralTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ArrayLiteralTest.java Sat Feb 11 11:26:42 2012
@@ -51,7 +51,7 @@ public class ArrayLiteralTest extends Je
JexlContext jc = new MapContext();
Object o = e.evaluate( jc );
- Object[] check = { new Float(5), new Integer(10) };
+ Object[] check = { new Double(5), new Integer(10) };
assertTrue( Arrays.equals(check, (Object[])o) );
assertTrue (o.getClass().isArray() && o.getClass().getComponentType().equals(Number.class));
}
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/AssignTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/AssignTest.java?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/AssignTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/AssignTest.java Sat Feb 11 11:26:42 2012
@@ -157,6 +157,4 @@ public class AssignTest extends JexlTest
o = JEXL.getProperty(quux, "['froboz']['value']");
assertEquals("Result is not 1000", new Integer(1000), o);
}
-
-
}
\ No newline at end of file
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/IssuesTest.java Sat Feb 11 11:26:42 2012
@@ -17,7 +17,6 @@
package org.apache.commons.jexl3;
import org.apache.commons.jexl3.internal.Engine;
-import org.apache.commons.jexl3.internal.Script;
import org.apache.commons.jexl3.internal.TemplateEngine;
import org.apache.commons.jexl3.internal.Debugger;
import java.math.BigDecimal;
@@ -35,7 +34,7 @@ public class IssuesTest extends JexlTest
public IssuesTest() {
super("IssuesTest", null);
}
-
+
@Override
public void setUp() throws Exception {
// ensure jul logging is only error to avoid warning in silent mode
@@ -56,7 +55,7 @@ public class IssuesTest extends JexlTest
assertEquals(42.0d, vars.get("d"));
assertEquals(56.3f, vars.get("e"));
assertEquals(56.3f, vars.get("f"));
- assertEquals(63.5f, vars.get("g"));
+ assertEquals(63.5d, vars.get("g"));
assertEquals(0x10, vars.get("h"));
assertEquals(010, vars.get("i"));
assertEquals(0x10L, vars.get("j"));
@@ -496,6 +495,10 @@ public class IssuesTest extends JexlTest
public String getPropA() {
return propA;
}
+
+ public String uppercase(String str) {
+ return str.toUpperCase();
+ }
}
public void test105() throws Exception {
@@ -617,10 +620,6 @@ public class IssuesTest extends JexlTest
RichContext(JexlEngine jexl, A105 a105) {
super(jexl, a105);
}
-
- public String uppercase(String str) {
- return str.toUpperCase();
- }
}
public void testRichContext() throws Exception {
@@ -719,131 +718,25 @@ public class IssuesTest extends JexlTest
assertTrue((Boolean) result);
}
- public void testStringIdentifier() throws Exception {
- JexlEngine jexl = new Engine();
- Map<String, String> foo = new HashMap<String, String>();
- JexlContext jc = new MapContext();
- jc.set("foo", foo);
- foo.put("q u u x", "456");
- JexlExpression e = jexl.createExpression("foo.\"q u u x\"");
- Object result = e.evaluate(jc);
- assertEquals("456", result);
- e = jexl.createExpression("foo.'q u u x'");
- result = e.evaluate(jc);
- assertEquals("456", result);
- JexlScript s = jexl.createScript("foo.\"q u u x\"");
- result = s.execute(jc);
- assertEquals("456", result);
- s = jexl.createScript("foo.'q u u x'");
- result = s.execute(jc);
- assertEquals("456", result);
-
- Debugger dbg = new Debugger();
-// dbg.debug(((Script)s).script);
-// String dbgdata = dbg.data();
-// assertEquals("foo.'q u u x';", dbgdata);
- }
-
- public static class Container {
- String value0;
- int value1;
- public Container(String name, int number) {
- value0 = name;
- value1 = number;
- }
-
- public Object getProperty(String name) {
- if ("name".equals(name)) {
- return value0;
- } else if ("number".equals(name)) {
- return value1;
- } else {
- return null;
- }
- }
- public Object getProperty(int ref) {
- if (0 == ref) {
- return value0;
- } else if (1 == ref) {
- return value1;
- } else {
- return null;
- }
+
+
+ public static class Foo125 {
+ public String method() {
+ return "OK";
}
-
- public void setProperty(String name, String value) {
- if ("name".equals(name)) {
- this.value0 = value;
- }
- }
-
- public void setProperty(String name, int value) {
- if ("number".equals(name)) {
- this.value1 = value;
- }
- }
- public void setProperty(int ref, String value) {
- if (0 == ref) {
- this.value0 = value;
- }
- }
-
- public void setProperty(int ref, int value) {
- if (1 == ref) {
- this.value1 = value;
- }
+ }
+
+ public static class Foo125Context extends ObjectContext<Foo125> {
+ public Foo125Context(JexlEngine engine, Foo125 wrapped) {
+ super(engine, wrapped);
}
}
- public void test119() throws Exception {
+ public void test125() throws Exception {
JexlEngine jexl = new Engine();
- Container quux = new Container("quux", 42);
- JexlScript get;
- Object result;
-
- JexlScript getName = jexl.createScript("foo.property.name", "foo");
- result = getName.execute(null, quux);
- assertEquals("quux", result);
-
- JexlScript get0 = jexl.createScript("foo.property.0", "foo");
- result = get0.execute(null, quux);
- assertEquals("quux", result);
-
- JexlScript getNumber = jexl.createScript("foo.property.number", "foo");
- result = getNumber.execute(null, quux);
- assertEquals(42, result);
-
- JexlScript get1 = jexl.createScript("foo.property.1", "foo");
- result = get1.execute(null, quux);
- assertEquals(42, result);
-
- JexlScript setName = jexl.createScript("foo.property.name = $0", "foo", "$0");
- setName.execute(null, quux, "QUUX");
- result = getName.execute(null, quux);
- assertEquals("QUUX", result);
- result = get0.execute(null, quux);
- assertEquals("QUUX", result);
-
- JexlScript set0 = jexl.createScript("foo.property.0 = $0", "foo", "$0");
- set0.execute(null, quux, "BAR");
- result = getName.execute(null, quux);
- assertEquals("BAR", result);
- result = get0.execute(null, quux);
- assertEquals("BAR", result);
-
- JexlScript setNumber = jexl.createScript("foo.property.number = $0", "foo", "$0");
- setNumber.execute(null, quux, -42);
- result = getNumber.execute(null, quux);
- assertEquals(-42, result);
- result = get1.execute(null, quux);
- assertEquals(-42, result);
-
- JexlScript set1 = jexl.createScript("foo.property.1 = $0", "foo", "$0");
- set1.execute(null, quux, 24);
- result = getNumber.execute(null, quux);
- assertEquals(24, result);
- result = get1.execute(null, quux);
- assertEquals(24, result);
+ JexlExpression e = jexl.createExpression("method()");
+ JexlContext jc = new Foo125Context(jexl, new Foo125());
+ assertEquals("OK", e.evaluate(jc));
}
}
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JexlTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JexlTest.java?rev=1243029&r1=1243028&r2=1243029&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JexlTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JexlTest.java Sat Feb 11 11:26:42 2012
@@ -649,7 +649,7 @@ public class JexlTest extends JexlTestCa
Foo foo = new Foo();
jc.set("foo", foo);
Parser parser = new Parser(new StringReader(";"));
- parser.parse(new StringReader("aString = 'World';"), null);
+ parser.parse(new StringReader("aString = 'World';"), null, null);
assertExpression(jc, "hello = 'world'", "world");
assertEquals("hello variable not changed", "world", jc.get("hello"));
Added: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java?rev=1243029&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java (added)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java Sat Feb 11 11:26:42 2012
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.jexl3;
+
+import org.apache.commons.jexl3.internal.Engine;
+
+/**
+ * Tests function/lambda/closure features.
+ */
+public class LambdaTest extends JexlTestCase {
+
+ public LambdaTest(String testName) {
+ super(testName);
+ }
+
+ public void testScriptArguments() throws Exception {
+ JexlEngine jexl = new Engine();
+ JexlScript s = jexl.createScript("{ x + x }", "x");
+ String strs = "s(21)";
+ JexlScript s42 = jexl.createScript("s(21)", "s");
+ Object result = s42.execute(null, s);
+ assertEquals(42, result);
+ }
+
+ public void testLambda() throws Exception {
+ JexlEngine jexl = new Engine();
+ String strs = "var s = function(x) { x + x }; s(21)";
+ JexlScript s42 = jexl.createScript(strs);
+ Object result = s42.execute(null);
+ assertEquals(42, result);
+ strs = "var s = function(x, y) { x + y }; s(15, 27)";
+ s42 = jexl.createScript(strs);
+ result = s42.execute(null);
+ assertEquals(42, result);
+ }
+
+ public void testLambdaClosure() throws Exception {
+ JexlEngine jexl = new Engine();
+ String strs = "var t = 20; var s = function(x, y) { x + y + t}; s(15, 7)";
+ JexlScript s42 = jexl.createScript(strs);
+ Object result = s42.execute(null);
+ assertEquals(42, result);
+ strs = "var t = 19; var s = function(x, y) { var t = 20; x + y + t}; s(15, 7)";
+ s42 = jexl.createScript(strs);
+ result = s42.execute(null);
+ assertEquals(42, result);
+ strs = "var t = 20; var s = function(x, y) {x + y + t}; t = 54; s(15, 7)";
+ s42 = jexl.createScript(strs);
+ result = s42.execute(null);
+ assertEquals(42, result);
+ strs = "var t = 19; var s = function(x, y) { var t = 20; x + y + t}; t = 54; s(15, 7)";
+ s42 = jexl.createScript(strs);
+ result = s42.execute(null);
+ assertEquals(42, result);
+ }
+}
Propchange: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java
------------------------------------------------------------------------------
svn:eol-style = native