Skip to content
Snippets Groups Projects
Commit bbf5bb15 authored by Mick Jordan's avatar Mick Jordan
Browse files

implement list variants of eval

parent 4ca22858
Branches
No related tags found
No related merge requests found
......@@ -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).
......
......@@ -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.
......
......@@ -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}.
......
......@@ -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"
......@@ -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)}");
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment