Skip to content
Snippets Groups Projects
Commit 90203e3d authored by Lukas Stadler's avatar Lukas Stadler
Browse files

implement Recall using RCallNode

parent f977cf27
Branches
No related tags found
No related merge requests found
......@@ -28,16 +28,16 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.profiles.BranchProfile;
import com.oracle.truffle.r.nodes.access.FrameSlotNode;
import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode;
import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
import com.oracle.truffle.r.nodes.function.CallMatcherNode;
import com.oracle.truffle.r.nodes.function.GetCallerFrameNode;
import com.oracle.truffle.r.nodes.function.RCallNode;
import com.oracle.truffle.r.runtime.ArgumentsSignature;
import com.oracle.truffle.r.runtime.RArguments;
import com.oracle.truffle.r.runtime.RError;
import com.oracle.truffle.r.runtime.Utils;
import com.oracle.truffle.r.runtime.builtins.RBuiltin;
import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
import com.oracle.truffle.r.runtime.data.RFunction;
......@@ -51,21 +51,27 @@ public abstract class Recall extends RBuiltinNode {
private final BranchProfile errorProfile = BranchProfile.create();
@Child private LocalReadVariableNode readArgs = LocalReadVariableNode.create(ArgumentsSignature.VARARG_NAME, false);
@Child private CallMatcherNode call = CallMatcherNode.create(false, false);
@Child private GetCallerFrameNode callerFrame = new GetCallerFrameNode();
private final Object argsIdentifier = new Object();
@Child private RCallNode call = RCallNode.createExplicitCall(argsIdentifier);
@Child private FrameSlotNode slot = FrameSlotNode.createTemp(argsIdentifier, true);
@Specialization
protected Object recall(VirtualFrame frame, @SuppressWarnings("unused") RArgsValuesAndNames args) {
/*
* The args passed to the Recall internal are ignored, they are always "...". Instead, this
* builtin looks at the arguments passed to the surrounding function.
*/
Frame cframe = Utils.getCallerFrame(frame, FrameAccess.READ_ONLY);
Frame cframe = callerFrame.execute(frame);
RFunction function = RArguments.getFunction(cframe);
if (function == null) {
errorProfile.enter();
throw RError.error(this, RError.Message.RECALL_CALLED_OUTSIDE_CLOSURE);
throw RError.error(RError.SHOW_CALLER, RError.Message.RECALL_CALLED_OUTSIDE_CLOSURE);
}
/*
* The args passed to the Recall internal are ignored, they are always "...". Instead, this
* builtin looks at the arguments passed to the surrounding function.
*/
RArgsValuesAndNames actualArgs = (RArgsValuesAndNames) readArgs.execute(frame);
return call.execute(frame, actualArgs.getSignature(), actualArgs.getArguments(), function, null, null);
frame.setObject(slot.executeFrameSlot(frame), actualArgs);
return call.execute(frame, function);
}
}
......@@ -22,7 +22,7 @@ public class TestBuiltin_Recall extends TestBase {
assertEval("{ f<-function(i) { if(i<=1) 1 else i*Recall(i-1) } ; f(10) }");
assertEval("{ f<-function(i) { if(i<=1) 1 else i*Recall(i-1) } ; g <- f ; f <- sum ; g(10) }");
assertEval("{ f<-function(i) { if (i==1) { 1 } else if (i==2) { 1 } else { Recall(i-1) + Recall(i-2) } } ; f(10) }");
assertEval(Output.IgnoreErrorContext, "{ Recall(10) }");
assertEval("{ Recall(10) }");
// Recall with more then 1 argument
assertEval("{ f <- function(tarDepth,curDepth) { if (tarDepth == curDepth) {curDepth} else {Recall(tarDepth,curDepth+1)}}; f(3,0) }");
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment