|
21 | 21 | #include <Rcpp/Interrupt.h> |
22 | 22 | #include <Rversion.h> |
23 | 23 |
|
24 | | -#if (defined(RCPP_PROTECTED_EVAL) && defined(R_VERSION) && R_VERSION >= R_Version(3, 5, 0)) |
25 | | -#define RCPP_USE_PROTECT_UNWIND |
| 24 | +// outer definition from RcppCommon.h |
| 25 | +#if defined(RCPP_USE_UNWIND_PROTECT) |
| 26 | + #if (defined(RCPP_PROTECTED_EVAL) && defined(R_VERSION) && R_VERSION >= R_Version(3, 5, 0)) |
| 27 | + // file-local and only used here |
| 28 | + #define RCPP_USE_PROTECT_UNWIND |
| 29 | + #endif |
26 | 30 | #endif |
27 | 31 |
|
28 | | - |
29 | 32 | namespace Rcpp { |
30 | 33 | namespace internal { |
31 | 34 |
|
@@ -96,39 +99,48 @@ inline SEXP Rcpp_eval(SEXP expr, SEXP env) { |
96 | 99 |
|
97 | 100 | // 'identity' function used to capture errors, interrupts |
98 | 101 | SEXP identity = Rf_findFun(::Rf_install("identity"), R_BaseNamespace); |
99 | | - |
| 102 | + |
100 | 103 | if (identity == R_UnboundValue) { |
101 | 104 | stop("Failed to find 'base::identity()'"); |
102 | 105 | } |
103 | 106 |
|
104 | 107 | // define the evalq call -- the actual R evaluation we want to execute |
105 | 108 | Shield<SEXP> evalqCall(Rf_lang3(::Rf_install("evalq"), expr, env)); |
106 | | - |
| 109 | + |
107 | 110 | // define the call -- enclose with `tryCatch` so we can record and forward error messages |
108 | 111 | Shield<SEXP> call(Rf_lang4(::Rf_install("tryCatch"), evalqCall, identity, identity)); |
109 | 112 | SET_TAG(CDDR(call), ::Rf_install("error")); |
110 | 113 | SET_TAG(CDDR(CDR(call)), ::Rf_install("interrupt")); |
111 | 114 |
|
| 115 | +#if defined(RCPP_USE_UNWIND_PROTECT) |
| 116 | + Shield<SEXP> res(::Rf_eval(call, R_GlobalEnv)) // execute the call |
| 117 | +#else |
112 | 118 | Shield<SEXP> res(internal::Rcpp_eval_impl(call, R_GlobalEnv)); |
| 119 | +#endif |
113 | 120 |
|
114 | 121 | // check for condition results (errors, interrupts) |
115 | 122 | if (Rf_inherits(res, "condition")) { |
116 | | - |
| 123 | + |
117 | 124 | if (Rf_inherits(res, "error")) { |
118 | | - |
| 125 | + |
119 | 126 | Shield<SEXP> conditionMessageCall(::Rf_lang2(::Rf_install("conditionMessage"), res)); |
120 | | - |
121 | | - Shield<SEXP> conditionMessage(internal::Rcpp_eval_impl(conditionMessageCall, R_GlobalEnv)); |
| 127 | + |
| 128 | +#if defined(RCPP_USE_UNWIND_PROTECT) |
| 129 | + Shield<SEXP> conditionMessage(internal::Rcpp_eval_impl(conditionMessageCall, |
| 130 | + R_GlobalEnv)); |
| 131 | +#else |
| 132 | + Shield<SEXP> conditionMessage(::Rf_eval(conditionMessageCall, R_GlobalEnv)); |
| 133 | +#endif |
122 | 134 | throw eval_error(CHAR(STRING_ELT(conditionMessage, 0))); |
123 | 135 | } |
124 | | - |
| 136 | + |
125 | 137 | // check for interrupt |
126 | 138 | if (Rf_inherits(res, "interrupt")) { |
127 | 139 | throw internal::InterruptedException(); |
128 | 140 | } |
129 | | - |
| 141 | + |
130 | 142 | } |
131 | | - |
| 143 | + |
132 | 144 | return res; |
133 | 145 | } |
134 | 146 |
|
|
0 commit comments