From dd6c986fd4ba7db1c52b70af46310fe9d7ef9be1 Mon Sep 17 00:00:00 2001 From: Jim Hester Date: Thu, 29 Apr 2021 10:43:30 -0400 Subject: [PATCH] Evaluate calls in the current frame This improves backtraces, as the cost of having to look up the current frame for every call. --- inst/include/cpp11/function.hpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/inst/include/cpp11/function.hpp b/inst/include/cpp11/function.hpp index 24086b98..a4b9010c 100644 --- a/inst/include/cpp11/function.hpp +++ b/inst/include/cpp11/function.hpp @@ -12,6 +12,27 @@ #include "cpp11/sexp.hpp" // for sexp namespace cpp11 { +namespace internal { +inline SEXP new_function(SEXP formals, SEXP body, SEXP env) { + SEXP fn = Rf_allocSExp(CLOSXP); + SET_FORMALS(fn, formals); + SET_BODY(fn, body); + SET_CLOENV(fn, env); + return fn; +} + +inline sexp construct_current_frame_call() { + sexp body(safe[Rf_lang2](Rf_install("sys.frame"), Rf_ScalarInteger(-1))); + sexp fn = new_function(R_NilValue, body, R_BaseEnv); + + return Rf_lang1(fn); +} + +static sexp current_frame_call = construct_current_frame_call(); + +inline SEXP peek_frame() { return Rf_eval(current_frame_call, R_EmptyEnv); } + +} // namespace internal class function { public: @@ -26,7 +47,9 @@ class function { construct_call(call, data_, std::forward(args)...); - return safe[Rf_eval](call, R_GlobalEnv); + SEXP env = internal::peek_frame(); + + return safe[Rf_eval](call, env); } private: