[Rcpp-commits] r3996 - in pkg/Rcpp: . man src
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Mon Nov 19 15:32:12 CET 2012
Author: jjallaire
Date: 2012-11-19 15:32:11 +0100 (Mon, 19 Nov 2012)
New Revision: 3996
Modified:
pkg/Rcpp/ChangeLog
pkg/Rcpp/TODO
pkg/Rcpp/man/exportAttribute.Rd
pkg/Rcpp/src/Attributes.cpp
pkg/Rcpp/src/AttributesParser.cpp
pkg/Rcpp/src/AttributesParser.h
Log:
support for argument default values
Modified: pkg/Rcpp/ChangeLog
===================================================================
--- pkg/Rcpp/ChangeLog 2012-11-18 20:59:00 UTC (rev 3995)
+++ pkg/Rcpp/ChangeLog 2012-11-19 14:32:11 UTC (rev 3996)
@@ -1,3 +1,10 @@
+2012-11-19 JJ Allaire <jj at rstudio.org>
+
+ * src/AttributesParser.h: support for argument default values
+ * src/AttributesParser.cpp: support for argument default values
+ * src/Attributes.cpp: support for argument default values
+ * man/exportAttribute.Rd: documentation updates
+
2012-11-18 JJ Allaire <jj at rstudio.org>
* R/Attributes.R: sourceCpp embedded R code; print warning if
Modified: pkg/Rcpp/TODO
===================================================================
--- pkg/Rcpp/TODO 2012-11-18 20:59:00 UTC (rev 3995)
+++ pkg/Rcpp/TODO 2012-11-19 14:32:11 UTC (rev 3996)
@@ -132,9 +132,6 @@
o Add unit tests
- o Mechanism for specifying default values for exported R functions
- (Rcpp::defaults attribute?)
-
o onBuildCompleted hook should pass succeeded = false if the loading
of the dynamic library fails
Modified: pkg/Rcpp/man/exportAttribute.Rd
===================================================================
--- pkg/Rcpp/man/exportAttribute.Rd 2012-11-18 20:59:00 UTC (rev 3995)
+++ pkg/Rcpp/man/exportAttribute.Rd 2012-11-19 14:32:11 UTC (rev 3996)
@@ -20,8 +20,25 @@
\item Have a return type that is either void or compatible with \code{Rcpp::wrap} and parameter types that are compatible with \code{Rcpp::as} (see sections 3.1 and 3.2 of the \emph{Rcpp-introduction} vignette for more details).
\item Use fully qualified type names for the return value and all parameters. However, Rcpp types may appear without the namespace qualifier (i.e. \code{DataFrame} is okay as a type name but \code{std::string} must be specified fully).
}
+ If default argument values are provided in the C++ function definition then these defaults are also used for the exported R function. For example, the following C++ function:
+
+\preformatted{
+DataFrame readData(
+ CharacterVector file,
+ CharacterVector exclude = CharacterVector::create(),
+ bool fill = true)
}
+ Will be exported to R as:
+
+\preformatted{
+function (file, exclude = character(0), fill = TRUE)
+}
+
+ Note that C++ rules for default arguments still apply: they must occur consecutively at the end of the function signature and unlike R can't rely on the values of other arguments.
+
+}
+
\note{
When a C++ function has export bindings automatically generated by the \code{\link{compileAttributes}} function, it can optionally also have a direct C++ interface generated using the \code{\link[=interfacesAttribute]{Rcpp::interfaces}} attribute.
Modified: pkg/Rcpp/src/Attributes.cpp
===================================================================
--- pkg/Rcpp/src/Attributes.cpp 2012-11-18 20:59:00 UTC (rev 3995)
+++ pkg/Rcpp/src/Attributes.cpp 2012-11-19 14:32:11 UTC (rev 3996)
@@ -134,7 +134,10 @@
it->function().arguments();
ostr << ", Rcpp::List::create(";
for (size_t i=0; i<args.size(); i++) {
- ostr << "Rcpp::Named(\"" << args[i].name() << "\")";
+ const Argument& arg = args[i];
+ ostr << "Rcpp::Named(\"" << arg.name() << "\")";
+ if (!arg.defaultValue().empty())
+ ostr << " = " << arg.defaultValue();
if (i != (args.size()-1))
ostr << ", ";
}
Modified: pkg/Rcpp/src/AttributesParser.cpp
===================================================================
--- pkg/Rcpp/src/AttributesParser.cpp 2012-11-18 20:59:00 UTC (rev 3995)
+++ pkg/Rcpp/src/AttributesParser.cpp 2012-11-19 14:32:11 UTC (rev 3996)
@@ -146,6 +146,8 @@
if (!argument.name().empty()) {
os << " ";
os << argument.name();
+ if (!argument.defaultValue().empty())
+ os << " = " << argument.defaultValue();
}
}
return os;
@@ -388,7 +390,7 @@
// Start at the end and look for the () that deliniates the arguments
// (bail with an empty result if we can't find them)
std::string::size_type endParenLoc = signature.find_last_of(')');
- std::string::size_type beginParenLoc = signature.find_last_of('(');
+ std::string::size_type beginParenLoc = signature.find_first_of('(');
if (endParenLoc == std::string::npos ||
beginParenLoc == std::string::npos ||
endParenLoc < beginParenLoc) {
@@ -451,6 +453,16 @@
// we don't warn here because the compilation will fail anyway
continue;
}
+
+ // If the argument has an = within it then it has a default value
+ std::string defaultValue;
+ std::string::size_type eqPos = arg.find_first_of('=');
+ if ( (eqPos != std::string::npos) && ((eqPos + 1) < arg.size()) ) {
+ defaultValue = arg.substr(eqPos+1);
+ trimWhitespace(&defaultValue);
+ arg = arg.substr(0, eqPos);
+ trimWhitespace(&arg);
+ }
// Scan backwards for whitespace to determine where the type ends
// (we go backwards because whitespace is valid inside the type
@@ -480,7 +492,7 @@
}
// add argument
- arguments.push_back(Argument(name, type));
+ arguments.push_back(Argument(name, type, defaultValue));
}
return Function(type, name, arguments, signature);
@@ -517,23 +529,45 @@
const std::string& argText) {
int templateCount = 0;
+ int parenCount = 0;
+ bool insideQuotes = false;
std::string currentArg;
std::vector<std::string> args;
+ char prevChar = 0;
for (std::string::const_iterator
it = argText.begin(); it != argText.end(); ++it) {
char ch = *it;
- if (ch == ',' && templateCount == 0) {
+ if (ch == '"' && prevChar != '\\') {
+ insideQuotes = !insideQuotes;
+ }
+
+ if ((ch == ',') &&
+ (templateCount == 0) &&
+ (parenCount == 0) &&
+ !insideQuotes) {
args.push_back(currentArg);
currentArg.clear();
continue;
} else {
- currentArg.push_back(ch);
- if (ch == '<')
- templateCount++;
- else if (ch == '>')
- templateCount--;
+ currentArg.push_back(ch);
+ switch(ch) {
+ case '<':
+ templateCount++;
+ break;
+ case '>':
+ templateCount--;
+ break;
+ case '(':
+ parenCount++;
+ break;
+ case ')':
+ parenCount--;
+ break;
+ }
}
+
+ prevChar = ch;
}
if (!currentArg.empty())
Modified: pkg/Rcpp/src/AttributesParser.h
===================================================================
--- pkg/Rcpp/src/AttributesParser.h 2012-11-18 20:59:00 UTC (rev 3995)
+++ pkg/Rcpp/src/AttributesParser.h 2012-11-19 14:32:11 UTC (rev 3996)
@@ -58,8 +58,10 @@
class Argument {
public:
Argument() {}
- Argument(const std::string& name, const Type& type)
- : name_(name), type_(type)
+ Argument(const std::string& name,
+ const Type& type,
+ const std::string& defaultValue)
+ : name_(name), type_(type), defaultValue_(defaultValue)
{
}
@@ -67,10 +69,12 @@
const std::string& name() const { return name_; }
const Type& type() const { return type_; }
+ const std::string& defaultValue() const { return defaultValue_; }
private:
std::string name_;
Type type_;
+ std::string defaultValue_;
};
// Function info
More information about the Rcpp-commits
mailing list