@@ -18,6 +18,8 @@ extern SEXP sym_dot_should_validate;
18
18
extern SEXP sym_dot_getting_prop ;
19
19
extern SEXP sym_dot_setting_prop ;
20
20
21
+ extern SEXP fn_base_quote ;
22
+
21
23
static inline
22
24
SEXP eval_here (SEXP lang ) {
23
25
PROTECT (lang );
@@ -26,6 +28,51 @@ SEXP eval_here(SEXP lang) {
26
28
return ans ;
27
29
}
28
30
31
+ static inline
32
+ SEXP do_call1 (SEXP fn , SEXP arg ) {
33
+ SEXP call , answer ;
34
+ switch (TYPEOF (arg )) {
35
+ case LANGSXP :
36
+ case SYMSXP :
37
+ arg = PROTECT (Rf_lang2 (fn_base_quote , arg ));
38
+ call = PROTECT (Rf_lang2 (fn , arg ));
39
+ answer = Rf_eval (call , ns_S7 );
40
+ UNPROTECT (2 );
41
+ return answer ;
42
+ default :
43
+ call = PROTECT (Rf_lang2 (fn , arg ));
44
+ answer = Rf_eval (call , ns_S7 );
45
+ UNPROTECT (1 );
46
+ return answer ;
47
+ }
48
+ }
49
+
50
+ static inline SEXP do_call2 (SEXP fn , SEXP arg1 , SEXP arg2 ) {
51
+ int n_protected = 0 ;
52
+ // Protect the arguments from evaluation if they are SYMSXP or LANGSXP
53
+ switch (TYPEOF (arg1 )) {
54
+ case LANGSXP :
55
+ case SYMSXP :
56
+ arg1 = PROTECT (Rf_lang2 (fn_base_quote , arg1 ));
57
+ ++ n_protected ;
58
+ }
59
+
60
+ switch (TYPEOF (arg2 )) {
61
+ case LANGSXP :
62
+ case SYMSXP :
63
+ arg2 = PROTECT (Rf_lang2 (fn_base_quote , arg2 ));
64
+ ++ n_protected ;
65
+ }
66
+
67
+ SEXP call = PROTECT (Rf_lang3 (fn , arg1 , arg2 ));
68
+ ++ n_protected ;
69
+
70
+ SEXP result = Rf_eval (call , ns_S7 );
71
+
72
+ UNPROTECT (n_protected );
73
+ return result ;
74
+ }
75
+
29
76
static __attribute__((noreturn ))
30
77
void signal_is_not_S7 (SEXP object ) {
31
78
static SEXP check_is_S7 = NULL ;
@@ -207,13 +254,25 @@ void obj_validate(SEXP object) {
207
254
if (validate == NULL )
208
255
validate = Rf_findVarInFrame (ns_S7 , Rf_install ("validate" ));
209
256
210
- eval_here (Rf_lang4 (
211
- validate , object ,
212
- /* recursive = */ Rf_ScalarLogical (TRUE),
213
- /* properties = */ Rf_ScalarLogical (FALSE)));
214
- }
215
-
257
+ switch (TYPEOF (object )) {
258
+ case LANGSXP :
259
+ case SYMSXP : {
260
+ // Wrap the call or symbol in quote(), so it doesn't evaluate in Rf_eval()
261
+ object = PROTECT (Rf_lang2 (fn_base_quote , object ));
262
+ eval_here (Rf_lang4 (validate , object ,
263
+ /* recursive = */ Rf_ScalarLogical (TRUE),
264
+ /* properties = */ Rf_ScalarLogical (FALSE)));
265
+ UNPROTECT (1 ); // object
266
+ return ;
267
+ }
216
268
269
+ default :
270
+ eval_here (Rf_lang4 (
271
+ validate , object ,
272
+ /* recursive = */ Rf_ScalarLogical (TRUE),
273
+ /* properties = */ Rf_ScalarLogical (FALSE)));
274
+ }
275
+ }
217
276
218
277
static inline
219
278
Rboolean getter_callable_no_recurse (SEXP getter , SEXP object , SEXP name_sym ) {
@@ -248,9 +307,10 @@ SEXP prop_(SEXP object, SEXP name) {
248
307
SEXP getter = extract_name (property , "getter" );
249
308
if (TYPEOF (getter ) == CLOSXP &&
250
309
getter_callable_no_recurse (getter , object , name_sym )) {
251
- SEXP value = PROTECT (eval_here (Rf_lang2 (getter , object )));
310
+
311
+ SEXP value = PROTECT (do_call1 (getter , object ));
252
312
getter_no_recurse_clear (object , name_sym );
253
- UNPROTECT (1 );
313
+ UNPROTECT (1 ); // value
254
314
return value ;
255
315
}
256
316
@@ -316,7 +376,7 @@ SEXP prop_set_(SEXP object, SEXP name, SEXP check_sexp, SEXP value) {
316
376
317
377
if (setter_callable_no_recurse (setter , object , name_sym , & should_validate_obj )) {
318
378
// use setter()
319
- REPROTECT (object = eval_here ( Rf_lang3 ( setter , object , value ) ), object_pi );
379
+ REPROTECT (object = do_call2 ( setter , object , value ), object_pi );
320
380
setter_no_recurse_clear (object , name_sym );
321
381
} else {
322
382
// don't use setter()
0 commit comments