diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java index 737f8b3c1547a86c4344402613d31458db012c13..98fb2f8d2753965bc23da337adaac3fe3bf3805e 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java @@ -302,12 +302,12 @@ final class REngine implements Engine { } } - public Object eval(RExpression exprs, REnvironment envir, REnvironment enclos, int depth) { + public Object eval(RExpression exprs, REnvironment envir, int depth) { Object result = RNull.instance; for (int i = 0; i < exprs.getLength(); i++) { Object obj = RASTUtils.checkForRSymbol(exprs.getDataAt(i)); if (obj instanceof RLanguage) { - result = evalNode((RNode) ((RLanguage) obj).getRep(), envir, enclos, depth); + result = evalNode((RNode) ((RLanguage) obj).getRep(), envir, depth); } else { result = obj; } @@ -315,8 +315,8 @@ final class REngine implements Engine { return result; } - public Object eval(RLanguage expr, REnvironment envir, REnvironment enclos, int depth) { - return evalNode((RNode) expr.getRep(), envir, enclos, depth); + public Object eval(RLanguage expr, REnvironment envir, int depth) { + return evalNode((RNode) expr.getRep(), envir, depth); } public Object eval(RExpression expr, MaterializedFrame frame) { @@ -350,11 +350,11 @@ final class REngine implements Engine { return func.getTarget().call(rArgs); } - private Object evalNode(RNode exprRep, REnvironment envir, REnvironment enclos, int depth) { + private Object evalNode(RNode exprRep, REnvironment envir, int depth) { RNode n = exprRep; RootCallTarget callTarget = doMakeCallTarget(n, EVAL_FUNCTION_NAME); RCaller call = RArguments.getCall(envir.getFrame()); - return evalTarget(callTarget, call, envir, enclos, depth); + return evalTarget(callTarget, call, envir, depth); } /** @@ -367,7 +367,7 @@ final class REngine implements Engine { * inefficient. In particular, in the case where a {@link VirtualFrame} is available, then the * {@code eval} methods that take such a {@link VirtualFrame} should be used in preference. */ - private Object evalTarget(RootCallTarget callTarget, RCaller call, REnvironment envir, @SuppressWarnings("unused") REnvironment enclos, int depth) { + private Object evalTarget(RootCallTarget callTarget, RCaller call, REnvironment envir, int depth) { MaterializedFrame envFrame = envir.getFrame(); // Here we create fake frame that wraps the original frame's context and has an only // slightly changed arguments array (function and callSrc). diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java index 790ff3db820762373764493107fab58f06337d16..8cc1665cb385d281583cfa8569d2254f9a134ce5 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EvalFunctions.java @@ -37,19 +37,17 @@ import com.oracle.truffle.r.runtime.nodes.*; /** * The {@code eval} {@code .Internal} and the {@code withVisible} {@code .Primitive}. - * - * TODO the {@code list} variants and the interpretation of the {@code enclos} argument. */ public class EvalFunctions { public abstract static class EvalAdapter extends RBuiltinNode { @TruffleBoundary - protected Object doEvalBody(int depth, Object exprArg, REnvironment envir, REnvironment enclos) { + protected Object doEvalBody(int depth, Object exprArg, REnvironment envir) { Object expr = RASTUtils.checkForRSymbol(exprArg); if (expr instanceof RExpression) { - return RContext.getEngine().eval((RExpression) expr, envir, enclos, depth); + return RContext.getEngine().eval((RExpression) expr, envir, depth); } else if (expr instanceof RLanguage) { - return RContext.getEngine().eval((RLanguage) expr, envir, enclos, depth); + return RContext.getEngine().eval((RLanguage) expr, envir, depth); } else { // just return value return expr; @@ -62,23 +60,45 @@ public class EvalFunctions { public abstract Object execute(VirtualFrame frame, Object expr, REnvironment envir, REnvironment enclos); + private final RAttributeProfiles attributeProfiles = RAttributeProfiles.create(); + @Specialization - protected Object doEval(VirtualFrame frame, Object expr, REnvironment envir, REnvironment enclos) { + protected Object doEval(VirtualFrame frame, Object expr, REnvironment envir, @SuppressWarnings("unused") REnvironment enclos) { controlVisibility(); - return doEvalBody(RArguments.getDepth(frame) + 1, expr, envir, enclos); + return doEvalBody(RArguments.getDepth(frame) + 1, expr, envir); } @Specialization protected Object doEval(VirtualFrame frame, Object expr, @SuppressWarnings("unused") RNull envir, REnvironment enclos) { controlVisibility(); - return doEvalBody(RArguments.getDepth(frame) + 1, expr, REnvironment.emptyEnv(), enclos); + return doEvalBody(RArguments.getDepth(frame) + 1, expr, enclos); + } + + @Specialization + protected Object doEval(VirtualFrame frame, Object expr, RList list, REnvironment enclos) { + return doEvalBody(RArguments.getDepth(frame) + 1, expr, REnvironment.createFromList(attributeProfiles, list, enclos)); + } + + @Specialization + protected Object doEval(VirtualFrame frame, Object expr, RPairList list, REnvironment enclos) { + return doEvalBody(RArguments.getDepth(frame) + 1, expr, REnvironment.createFromList(attributeProfiles, list.toRList(), enclos)); + } + + @Specialization + protected Object doEval(VirtualFrame frame, Object expr, RDataFrame dataFrame, REnvironment enclos) { + RVector vector = dataFrame.getVector(); + if (vector instanceof RList) { + return doEvalBody(RArguments.getDepth(frame) + 1, expr, REnvironment.createFromList(attributeProfiles, (RList) vector, enclos)); + } else { + throw RError.nyi(this, "eval on non-list dataframe"); + } } @SuppressWarnings("unused") @Fallback @TruffleBoundary protected Object doEval(Object expr, Object envir, Object enclos) { - throw RError.nyi(this, "eval arg type"); + throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); } } @@ -89,8 +109,7 @@ public class EvalFunctions { @Specialization protected RList withVisible(VirtualFrame frame, RPromise expr) { controlVisibility(); - Object result = doEvalBody(RArguments.getDepth(frame) + 1, RDataFactory.createLanguage((RNode) expr.getRep()), REnvironment.frameToEnvironment(frame.materialize()), - REnvironment.emptyEnv()); + Object result = doEvalBody(RArguments.getDepth(frame) + 1, RDataFactory.createLanguage((RNode) expr.getRep()), REnvironment.frameToEnvironment(frame.materialize())); Object[] data = new Object[]{result, RRuntime.asLogical(RContext.getInstance().isVisible())}; // Visibility is changed by the evaluation (else this code would not work), // so we have to force it back on. diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java index 29b959bdebd85b255166ce77fe660aed6074b77b..b83c11e6e09e75f6d1692bf33257d3d43d60af85 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java @@ -128,27 +128,12 @@ public interface Engine { /** * Support for the {@code eval} {@code .Internal}. */ - Object eval(RExpression expr, REnvironment envir, REnvironment enclos, int depth); + Object eval(RExpression expr, REnvironment envir, int depth); /** - * Convenience method for common case. + * Variant of {@link #eval(RExpression, REnvironment, int)} for a single language element. */ - default Object eval(RExpression expr, REnvironment envir, int depth) { - return eval(expr, envir, null, depth); - } - - /** - * Variant of {@link #eval(RExpression, REnvironment, REnvironment, int)} for a single language - * element. - */ - Object eval(RLanguage expr, REnvironment envir, REnvironment enclos, int depth); - - /** - * Convenience method for common case. - */ - default Object eval(RLanguage expr, REnvironment envir, int depth) { - return eval(expr, envir, null, depth); - } + Object eval(RLanguage expr, REnvironment envir, int depth); /** * Evaluate {@code expr} in {@code frame}. diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test index 316598fa646c1eb0922db6f1c303439e8ee6bf34..b7578a1d7e1897e255c3f779dbde3e0918f5ad99 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test @@ -17371,6 +17371,10 @@ x #{ g<-function(y) { f<-function(x) { x }; substitute(f(y)) } ; eval(g(42)) } [1] 42 +##com.oracle.truffle.r.test.builtins.TestBuiltin_eval.testEval +#{ l <- list(a=1, b=2); eval(quote(a), l)} +[1] 1 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_eval.testEval #{ ne <- new.env(); eval(x <- 1, ne); ls() } [1] "ne" "x" diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java index 2d228ab03fe97770ab0a02e3df3e7b005f1ec889..02b466ede4ef00055977bbcd27c6cf9e5be61ac0 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java @@ -43,5 +43,8 @@ public class TestBuiltin_eval extends TestBase { // should print two values, xx^2 and xx assertEval(Ignored.Unknown, "eval({ xx <- pi; xx^2}) ; xx"); + + // lists + assertEval("{ l <- list(a=1, b=2); eval(quote(a), l)}"); } }