Skip to content

Commit 9cfabf8

Browse files
better implementation, and dropping the special handling for 'data'
1 parent 813e902 commit 9cfabf8

3 files changed

Lines changed: 53 additions & 27 deletions

File tree

R/Attributes.R

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -402,21 +402,12 @@ registerPlugin <- function(name, plugin) {
402402

403403
# Take an empty function body and connect it to the specified external symbol
404404
sourceCppFunction <- function(func, isVoid, dll, symbol) {
405-
406405
args <- names(formals(func))
407406
if( identical( args, "..." ) ){
408407
body <- substitute({
409-
dots <- as.list( sys.call()[-1L] )
410-
parent_frame <- parent.frame()
411-
if( "data" %in% names(dots) ){
412-
data <- eval( dots[["data"]], parent_frame )
413-
dots <- dots[ names(dots) != "data" ]
414-
env <- as.environment(data)
415-
parent.env(env) <- parent_frame
416-
} else {
417-
env <- parent_frame
418-
}
419-
DOT_CALL( FUN, dots, env )
408+
calls <- sys.calls()
409+
frames <- sys.frames()
410+
DOT_CALL( FUN, calls, frames )
420411
}, list( FUN = getNativeSymbolInfo(symbol, dll)$address, DOT_CALL = .Call) )
421412
} else {
422413

inst/include/Rcpp/Dots.h

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,64 @@ namespace Rcpp{
2222

2323
class Dots {
2424
public:
25-
Dots( List data_, Environment env_): data(data_), env(env_){}
2625

27-
SEXP eval( int i ){ return eval_(i); }
26+
Dots( List calls_, List frames_ ) :
27+
calls(calls_), frames(frames_), env(0), exprs(0), tags(0)
28+
{
29+
init() ;
30+
}
31+
32+
SEXP eval(int i){
33+
return Rf_eval( exprs[i], env[i] );
34+
}
2835

29-
template <typename T>
30-
T eval( int i ){
31-
return as<T>( eval_(i) ) ;
36+
SEXP envir(int i){
37+
return env[i] ;
3238
}
3339

34-
SEXP operator[]( int i ){
35-
return data[i] ;
40+
SEXP expr( int i ){
41+
return exprs[i] ;
3642
}
3743

38-
inline size_t size() const{ return data.size(); }
39-
44+
inline size_t size() const{ return exprs.size(); }
45+
46+
4047
private:
4148

42-
inline SEXP eval_( int i){
43-
return Rf_eval( data[i], env ) ;
49+
void init(){
50+
process( frames.size() - 1 ) ;
4451
}
4552

46-
List data ;
47-
Environment env ;
53+
void process(int i){
54+
if( i < 0 ) return ;
55+
SEXP p = calls[i] ;
56+
if( TYPEOF(p) != LANGSXP ) return ;
57+
58+
p = CDR(p) ;
59+
SEXP head ;
60+
while( p != R_NilValue ){
61+
head = CAR(p) ;
62+
if( is_ellipsis(head) ) {
63+
process(i-1) ;
64+
} else {
65+
exprs.push_back( head ) ;
66+
env.push_back( frames[i-1] ) ;
67+
tags.push_back( TAG(p) );
68+
}
69+
p = CDR(p) ;
70+
}
71+
}
72+
73+
bool is_ellipsis( SEXP x){
74+
return x == R_DotsSymbol ;
75+
}
76+
77+
List calls, frames ;
78+
// all of what we put in there is already protected by R.
79+
std::vector<SEXP> env ;
80+
std::vector<SEXP> exprs ;
81+
std::vector<SEXP> tags ;
82+
4883
} ;
4984

5085
} // Rcpp

src/attributes.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2161,7 +2161,7 @@ namespace attributes {
21612161
const std::vector<Argument>& arguments = function.arguments();
21622162
// deal with functions with a single argument of class "Dots"
21632163
if( function.is_Dots() ){
2164-
ostrArgs << "SEXP args, SEXP env" ;
2164+
ostrArgs << "SEXP calls, SEXP frames" ;
21652165
} else {
21662166
for (size_t i = 0; i<arguments.size(); i++) {
21672167
const Argument& argument = arguments[i];
@@ -2179,7 +2179,7 @@ namespace attributes {
21792179
if (!cppInterface)
21802180
ostr << " Rcpp::RNGScope __rngScope;" << std::endl;
21812181
if( function.is_Dots() ){
2182-
ostr << " Rcpp::Dots dots( args, env ) ;" << std::endl;
2182+
ostr << " Rcpp::Dots dots( calls, frames ) ;" << std::endl;
21832183
} else {
21842184
for (size_t i = 0; i<arguments.size(); i++) {
21852185
const Argument& argument = arguments[i];

0 commit comments

Comments
 (0)