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/12 18:59:34 UTC
svn commit: r1243285 - in /commons/proper/jexl/trunk/src:
main/java/org/apache/commons/jexl3/internal/
test/java/org/apache/commons/jexl3/
Author: henrib
Date: Sun Feb 12 17:59:34 2012
New Revision: 1243285
URL: http://svn.apache.org/viewvc?rev=1243285&view=rev
Log:
Closure implements JexlScript (execute, callable);
Added:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Closure.java (with props)
Modified:
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/Interpreter.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ScriptCallableTest.java
Added: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Closure.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Closure.java?rev=1243285&view=auto
==============================================================================
--- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Closure.java (added)
+++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Closure.java Sun Feb 12 17:59:34 2012
@@ -0,0 +1,92 @@
+/*
+ * 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.concurrent.Callable;
+import org.apache.commons.jexl3.JexlContext;
+import org.apache.commons.jexl3.parser.ASTJexlLambda;
+import org.apache.commons.jexl3.parser.JexlNode;
+
+/**
+ * A Script closure.
+ */
+final class Closure extends Script {
+ /** The frame. */
+ private final Scope.Frame frame;
+ /** The caller, kept to copy options, flags and functors. */
+ private final Interpreter caller;
+
+ /**
+ * Creates a closure.
+ * @param theCaller the calling interpreter
+ * @param lambda the lambda
+ */
+ Closure(Interpreter theCaller, ASTJexlLambda lambda) {
+ super(theCaller.jexl, null, lambda);
+ caller = theCaller;
+ frame = lambda.createFrame(theCaller.frame);
+ }
+
+ @Override
+ public String getExpression() {
+ Debugger debug = new Debugger();
+ boolean d = debug.debug(script);
+ return debug.data();
+ }
+
+ @Override
+ public Object evaluate(JexlContext context) {
+ return execute(context, (Object[])null);
+ }
+
+ @Override
+ public Object execute(JexlContext context) {
+ return execute(context, (Object[])null);
+ }
+
+ @Override
+ public Object execute(JexlContext context, Object... args) {
+ if (frame != null) {
+ frame.assign(args);
+ }
+ Interpreter interpreter = new Interpreter(caller, context, frame);
+ JexlNode block = script.jjtGetChild(script.jjtGetNumChildren() - 1);
+ return interpreter.interpret(block);
+ }
+
+ @Override
+ public Callable<Object> callable(JexlContext context, Object... args) {
+ if (frame != null) {
+ frame.assign(args);
+ }
+ final Interpreter interpreter = new Interpreter(caller, context, frame);
+ return new Callable<Object>() {
+ /** Use interpreter as marker for not having run. */
+ private Object result = interpreter;
+
+ @Override
+ public Object call() throws Exception {
+ if (result == interpreter) {
+ JexlNode block = script.jjtGetChild(script.jjtGetNumChildren() - 1);
+ return interpreter.interpret(block);
+ }
+ return result;
+ }
+ };
+ }
+
+}
Propchange: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/internal/Closure.java
------------------------------------------------------------------------------
svn:eol-style = native
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=1243285&r1=1243284&r2=1243285&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 Sun Feb 12 17:59:34 2012
@@ -496,7 +496,7 @@ public final class Debugger extends Pars
builder.append(params[p]);
}
}
- builder.append(")");
+ builder.append(") ");
}
int num = node.jjtGetNumChildren();
for (int i = 0; i < num; ++i) {
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=1243285&r1=1243284&r2=1243285&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 Sun Feb 12 17:59:34 2012
@@ -21,12 +21,10 @@ import org.apache.commons.jexl3.JexlCont
import org.apache.commons.jexl3.JexlEngine;
import org.apache.commons.jexl3.JexlException;
import org.apache.commons.jexl3.JexlScript;
-
import org.apache.commons.jexl3.introspection.JexlMethod;
import org.apache.commons.jexl3.introspection.JexlPropertyGet;
import org.apache.commons.jexl3.introspection.JexlPropertySet;
import org.apache.commons.jexl3.introspection.JexlUberspect;
-
import org.apache.commons.jexl3.parser.ASTAdditiveNode;
import org.apache.commons.jexl3.parser.ASTAdditiveOperator;
import org.apache.commons.jexl3.parser.ASTAndNode;
@@ -50,6 +48,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;
@@ -89,7 +88,6 @@ 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.
@@ -155,17 +153,18 @@ public class Interpreter extends ParserV
this.frame = eFrame;
this.functors = null;
}
-
+
/**
* Creates a copy of an interpreter, used for function/lambda evaluation.
* @param copy the interpreter to copy
+ * @param eContext the global variables context
* @param eFrame the interpreter evaluation frame
*/
- protected Interpreter(Interpreter copy, Scope.Frame eFrame) {
+ protected Interpreter(Interpreter copy, JexlContext eContext, Scope.Frame eFrame) {
this.jexl = copy.jexl;
this.logger = copy.logger;
this.uberspect = copy.uberspect;
- this.context = copy.context;
+ this.context = eContext;
this.arithmetic = copy.arithmetic;
this.silent = copy.silent;
this.functions = copy.functions;
@@ -830,7 +829,7 @@ public class Interpreter extends ParserV
@Override
protected Object visit(ASTJexlScript node, Object data) {
if (node instanceof ASTJexlLambda) {
- return new Closure((ASTJexlLambda) node, frame);
+ return new Closure(this, (ASTJexlLambda) node);
} else {
final int numChildren = node.jjtGetNumChildren();
Object result = null;
@@ -841,41 +840,6 @@ public class Interpreter extends ParserV
return result;
}
}
-
- /**
- * A function closure.
- */
- private static final class Closure {
- /** The frame. */
- private final Scope.Frame frame;
- /** The actual lambda. */
- private final ASTJexlLambda lambda;
- /** Creates a closure.
- * @param l the lambda
- * @param f the interpreter frame
- */
- Closure(ASTJexlLambda l, Scope.Frame f) {
- lambda = l;
- frame = lambda.createFrame(f);
- }
- }
-
- /**
- * Evaluates a closure.
- * @param closure the closure
- * @param argv the arguments
- * @return the result of evaluation
- */
- private Object call(Closure closure, Object[] argv) {
- Scope.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
protected Object visit(ASTLENode node, Object data) {
@@ -983,9 +947,6 @@ public class Interpreter extends ParserV
}
}
// 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);
}
@@ -1274,8 +1235,8 @@ 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, variableName.toString())
: new JexlException.Variable(node, variableName.toString());
Modified: 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=1243285&r1=1243284&r2=1243285&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/LambdaTest.java Sun Feb 12 17:59:34 2012
@@ -30,12 +30,27 @@ public class LambdaTest extends JexlTest
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 testScriptContext() throws Exception {
+ JexlEngine jexl = new Engine();
+ JexlScript s = jexl.createScript("function(x) { x + x }");
+ JexlScript fs = (JexlScript) s.execute(null);
+ String fsstr = fs.getExpression();
+ assertEquals("function(x) { x + x; };", fsstr);
+ assertEquals(42, fs.execute(null, 21));
+ JexlScript s42 = jexl.createScript("s(21)");
+ JexlEvalContext ctxt = new JexlEvalContext();
+ ctxt.set("s", fs);
+ Object result = s42.execute(ctxt);
+ assertEquals(42, result);
+ result = s42.evaluate(ctxt);
+ assertEquals(42, result);
+ }
+
public void testLambda() throws Exception {
JexlEngine jexl = new Engine();
String strs = "var s = function(x) { x + x }; s(21)";
Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ScriptCallableTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ScriptCallableTest.java?rev=1243285&r1=1243284&r2=1243285&view=diff
==============================================================================
--- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ScriptCallableTest.java (original)
+++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ScriptCallableTest.java Sun Feb 12 17:59:34 2012
@@ -66,8 +66,26 @@ public class ScriptCallableTest extends
future.cancel(true);
assertTrue(future.isCancelled());
}
+
+ public void testCallableClosure() throws Exception {
+ JexlScript e = JEXL.createScript("function(t) {while(t);}");
+ e = (JexlScript) e.execute(null);
+ Callable<Object> c = e.callable(null, Boolean.TRUE);
+
+ ExecutorService executor = Executors.newFixedThreadPool(1);
+ Future<?> future = executor.submit(c);
+ try {
+ future.get(100, TimeUnit.MILLISECONDS);
+ fail("should have timed out");
+ } catch (TimeoutException xtimeout) {
+ // ok, ignore
+ }
+ future.cancel(true);
+ assertTrue(future.isCancelled());
+ }
public static class TestContext extends MapContext implements JexlContext.NamespaceResolver {
+ @Override
public Object resolveNamespace(String name) {
return name == null ? this : null;
}