From 8d648d26e13ed5502c16b4ce28bb753a32023203 Mon Sep 17 00:00:00 2001 From: JJ Allaire Date: Thu, 12 Feb 2015 12:01:56 -0500 Subject: [PATCH 1/2] add rng parameter to Rcpp::export to prevent inclusion of RNGScope in generated code --- ChangeLog | 6 +++++ DESCRIPTION | 2 +- TODO | 3 --- inst/NEWS.Rd | 2 ++ src/attributes.cpp | 66 +++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 69 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index ed0ecef13..a9ba7e3d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-02-12 JJ Allaire + + * DESCRIPTION: bump version + * src/attributes.cpp: Add rng parameter to Rcpp::export to + prevent inclusion of RNGScope in generated code. + 2015-02-06 Kevin Ushey * inst/include/Rcpp/vector/Subsetter.h: compare CHARSXP pointers diff --git a/DESCRIPTION b/DESCRIPTION index 696871674..22fa20fec 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: Rcpp Title: Seamless R and C++ Integration -Version: 0.11.4.4 +Version: 0.11.4.5 Date: 2015-02-03 Author: Dirk Eddelbuettel, Romain Francois, JJ Allaire, Kevin Ushey, Douglas Bates, and John Chambers diff --git a/TODO b/TODO index 813e0de9b..4cd4a14f3 100644 --- a/TODO +++ b/TODO @@ -84,9 +84,6 @@ Attributes o Add unit tests - o Add random = false parameter to Rcpp::export once we support parsing - key/value pairs in attribute parameters - o Detect useDynLib .registration = TRUE and in that case emit .Call wrappers as symbols rather than strings w/ PACKAGE = diff --git a/inst/NEWS.Rd b/inst/NEWS.Rd index 405ada4fd..9de8902a9 100644 --- a/inst/NEWS.Rd +++ b/inst/NEWS.Rd @@ -23,6 +23,8 @@ \item Simplify generated attributes code for \code{RNGScope} (use \code{RObject} and it's destructor rather than \code{SEXP} protect/unprotect). + \item Add rng parameter to Rcpp::export to prevent inclusion of + RNGScope in generated code. } } } diff --git a/src/attributes.cpp b/src/attributes.cpp index 6aac05cdb..34dee139d 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -103,11 +103,15 @@ namespace attributes { // Known attribute names & parameters const char * const kExportAttribute = "export"; + const char * const kExportName = "name"; + const char * const kExportRng = "rng"; const char * const kDependsAttribute = "depends"; const char * const kPluginsAttribute = "plugins"; const char * const kInterfacesAttribute = "interfaces"; const char * const kInterfaceR = "r"; const char * const kInterfaceCpp = "cpp"; + const char * const kParamValueFalse = "false"; + const char * const kParamValueTrue = "true"; // Type info class Type { @@ -244,10 +248,29 @@ namespace attributes { } std::string exportedName() const { - if (!params().empty()) + + // check for explicit name parameter + if (hasParameter(kExportName)) + { + return paramNamed(kExportName).value(); + } + // otherwise un-named parameter in the first slot + else if (!params().empty() && params()[0].value().empty()) + { return params()[0].name(); - else + } + // otherwise the actual function name + { return function().name(); + } + } + + bool rng() const { + Param rngParam = paramNamed(kExportRng); + if (!rngParam.empty()) + return rngParam.value() != kParamValueFalse; + else + return true; } const std::vector& roxygen() const { return roxygen_; } @@ -740,6 +763,7 @@ namespace attributes { } else { name_ = paramText; + trimWhitespace(&name_); stripQuotes(&name_); } } @@ -984,6 +1008,34 @@ namespace attributes { function = parseFunction(lineNumber + 1); else rcppExportWarning("No function found", lineNumber); + + // validate parameters + for (std::size_t i=0; i 0)) { + rcppExportWarning("No value specified for parameter '" + + name + "'", + lineNumber); + } + // parameter that isn't name or rng + else if (!value.empty() && + (name != kExportName) && + (name != kExportRng)) { + rcppExportWarning("Unrecognized parameter '" + name + "'", + lineNumber); + } + // rng that isn't true or false + else if (name == kExportRng) { + if (value != kParamValueFalse && value != kParamValueTrue) { + rcppExportWarning("rng value must be true or false", + lineNumber); + } + } + } } // validate interfaces parameter @@ -1014,7 +1066,7 @@ namespace attributes { std::vector SourceFileAttributesParser::parseParameters( const std::string& input) { - const std::string delimiters(" ,"); + const std::string delimiters(","); std::vector params; std::string::size_type current; @@ -1694,7 +1746,8 @@ namespace attributes { ostr() << " }" << std::endl; ostr() << " RObject __result;" << std::endl; ostr() << " {" << std::endl; - ostr() << " RNGScope __rngScope;" << std::endl; + if (it->rng()) + ostr() << " RNGScope __rngScope;" << std::endl; ostr() << " __result = " << ptrName << "("; const std::vector& args = function.arguments(); @@ -2226,7 +2279,7 @@ namespace attributes { ostr << "BEGIN_RCPP" << std::endl; if (!function.type().isVoid()) ostr << " Rcpp::RObject __result;" << std::endl; - if (!cppInterface) + if (!cppInterface && attribute.rng()) ostr << " Rcpp::RNGScope __rngScope;" << std::endl; for (size_t i = 0; i Date: Thu, 12 Feb 2015 13:09:56 -0500 Subject: [PATCH 2/2] accept TRUE and FALSE for logical attribute parameters --- src/attributes.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/attributes.cpp b/src/attributes.cpp index 34dee139d..f5e4b3b00 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -112,6 +112,8 @@ namespace attributes { const char * const kInterfaceCpp = "cpp"; const char * const kParamValueFalse = "false"; const char * const kParamValueTrue = "true"; + const char * const kParamValueFALSE = "FALSE"; + const char * const kParamValueTRUE = "TRUE"; // Type info class Type { @@ -268,7 +270,8 @@ namespace attributes { bool rng() const { Param rngParam = paramNamed(kExportRng); if (!rngParam.empty()) - return rngParam.value() != kParamValueFalse; + return rngParam.value() == kParamValueTrue || + rngParam.value() == kParamValueTRUE; else return true; } @@ -1030,7 +1033,10 @@ namespace attributes { } // rng that isn't true or false else if (name == kExportRng) { - if (value != kParamValueFalse && value != kParamValueTrue) { + if (value != kParamValueFalse && + value != kParamValueTrue && + value != kParamValueFALSE && + value != kParamValueTRUE) { rcppExportWarning("rng value must be true or false", lineNumber); }