diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java index 3cc3caf3c0d0dba9049a8ab6d9502655c2971130..c3ea2d467ac13740518b397f3f789c3452ca1b26 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java @@ -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); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Recall.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Recall.java index beaf7bfb0e93c3017f2264209f4bc25a33edcb9b..66bbf7874645300b317d4fb9eb2964e3cb269610 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Recall.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Recall.java @@ -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) }"); }