[Rcpp-commits] r3991 - in pkg/Rcpp: . R man src

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Sun Nov 18 17:32:11 CET 2012


Author: jjallaire
Date: 2012-11-18 17:32:11 +0100 (Sun, 18 Nov 2012)
New Revision: 3991

Modified:
   pkg/Rcpp/ChangeLog
   pkg/Rcpp/R/Attributes.R
   pkg/Rcpp/TODO
   pkg/Rcpp/man/sourceCpp.Rd
   pkg/Rcpp/src/Attributes.cpp
   pkg/Rcpp/src/AttributesParser.cpp
   pkg/Rcpp/src/AttributesParser.h
Log:
 sourceCpp embedded R code

Modified: pkg/Rcpp/ChangeLog
===================================================================
--- pkg/Rcpp/ChangeLog	2012-11-18 16:16:04 UTC (rev 3990)
+++ pkg/Rcpp/ChangeLog	2012-11-18 16:32:11 UTC (rev 3991)
@@ -1,3 +1,10 @@
+2012-11-18  JJ Allaire <jj at rstudio.org>
+
+        * R/Attributes.R: sourceCpp embedded R code
+        * src/AttributesParser.h: sourceCpp embedded R code
+        * src/AttributesParser.cpp: sourceCpp embedded R code
+        * src/Attributes.cpp: sourceCpp embedded R code
+
 2012-11-18  Romain Francois <romain at r-enthusiasts.com>
 
         * include/Rcpp/vector/converter.h: allow CharacterVector::create( NA_STRING )

Modified: pkg/Rcpp/R/Attributes.R
===================================================================
--- pkg/Rcpp/R/Attributes.R	2012-11-18 16:16:04 UTC (rev 3990)
+++ pkg/Rcpp/R/Attributes.R	2012-11-18 16:32:11 UTC (rev 3991)
@@ -140,6 +140,12 @@
                  env)
     }
     
+    # source the embeddedR
+    if (length(context$embeddedR) > 0) {
+        srcConn <- textConnection(context$embeddedR)
+        source(file=srcConn, print.eval=TRUE)
+    }
+    
     # return (invisibly) a list of exported functions
     invisible(context$exportedFunctions)
 }

Modified: pkg/Rcpp/TODO
===================================================================
--- pkg/Rcpp/TODO	2012-11-18 16:16:04 UTC (rev 3990)
+++ pkg/Rcpp/TODO	2012-11-18 16:32:11 UTC (rev 3991)
@@ -152,9 +152,6 @@
     o   Clarify in 5.1 of vignette that attribute package features still
         require Makevars, etc. created by Rcpp.package.skeleton 
 
-    o   Provide single action to source both C++ and R code (possible
-        source_with attribute and/or embed R code in cpp file w/ comment)
-
     o   Add docstring parameter to Rcpp::export attribute
 
     o   Emit warning if sourceCpp finds no exports (control via option)

Modified: pkg/Rcpp/man/sourceCpp.Rd
===================================================================
--- pkg/Rcpp/man/sourceCpp.Rd	2012-11-18 16:16:04 UTC (rev 3990)
+++ pkg/Rcpp/man/sourceCpp.Rd	2012-11-18 16:32:11 UTC (rev 3991)
@@ -39,6 +39,17 @@
     
     If the source file has compilation dependencies on other packages (e.g. \pkg{Matrix}, \pkg{RcppArmadillo}) then an \code{\link[=dependsAttribute]{Rcpp::depends}} attribute should be provided naming these dependencies. 
     
+    It's possible to embed chunks of R code within the C++ that will be sourced alone with the C++ functions. This is done by starting a block comment with the prefix of \code{/*** R}. For example:
+    
+\preformatted{
+/*** R
+
+# Call the fibonacci function defined in C++
+fibonacci(10)
+
+*/
+}
+    
     The \code{sourceCpp} function will not rebuild the shared library if the source file has not changed since the last compilation.
 }
 
@@ -50,6 +61,7 @@
     The \code{sourceCpp} function is designed for compiling a standalone source file whose only dependencies are R packages. If you are compiling more than one source file or have external dependencies then you should create an R package rather than using \code{sourceCpp}. Note that the \code{\link[=exportAttribute]{Rcpp::export}} attribute can also be used within packages via the \code{\link{compileAttributes}} function.
     
     If you are sourcing a C++ file from within the \code{src} directory of a package then the package's \code{LinkingTo} dependencies, \code{inst/include}, and \code{src} directories are automatically included in the compilation.
+
 }
 
 \seealso{

Modified: pkg/Rcpp/src/Attributes.cpp
===================================================================
--- pkg/Rcpp/src/Attributes.cpp	2012-11-18 16:16:04 UTC (rev 3990)
+++ pkg/Rcpp/src/Attributes.cpp	2012-11-18 16:32:11 UTC (rev 3991)
@@ -920,6 +920,9 @@
                         depends_.push_back(it->params()[i].name());
                  }   
             }
+            
+            // capture embededded R
+            embeddedR_ = sourceAttributes.embeddedR();
         }
         
         const std::string& moduleName() const {
@@ -955,6 +958,8 @@
         }
         
         const std::vector<std::string>& depends() const { return depends_; };
+        
+        const std::vector<std::string>& embeddedR() const { return embeddedR_; }
           
     private:
     
@@ -973,6 +978,7 @@
         std::string dynlibExt_;
         std::vector<std::string> exportedFunctions_;
         std::vector<std::string> depends_;
+        std::vector<std::string> embeddedR_;
     };
     
     // Dynlib cache that allows lookup by either file path or code contents
@@ -1087,6 +1093,7 @@
         _["cppSourceFilename"] = dynlib.cppSourceFilename(),
         _["dynlibFilename"] = dynlib.dynlibFilename(),
         _["dynlibPath"] = dynlib.dynlibPath(),
-        _["depends"] = dynlib.depends());
+        _["depends"] = dynlib.depends(),
+        _["embeddedR"] = dynlib.embeddedR());
 END_RCPP
 }

Modified: pkg/Rcpp/src/AttributesParser.cpp
===================================================================
--- pkg/Rcpp/src/AttributesParser.cpp	2012-11-18 16:16:04 UTC (rev 3990)
+++ pkg/Rcpp/src/AttributesParser.cpp	2012-11-18 16:32:11 UTC (rev 3991)
@@ -60,7 +60,18 @@
         if ( (quote == '\'' || quote == '\"') && (*(pStr->rbegin()) == quote) )
             *pStr = pStr->substr(1, pStr->length()-2);
     }
-      
+    
+    Rcpp::List regexMatches(Rcpp::CharacterVector lines, 
+                            const std::string& regex)
+    {
+        Rcpp::Environment base("package:base");
+        Rcpp::Function regexec = base["regexec"];
+        Rcpp::Function regmatches = base["regmatches"];
+        Rcpp::RObject result =  regexec(regex, lines);
+        Rcpp::List matches = regmatches(lines, result);
+        return matches;
+    }
+
 } // anonymous namespace
 
 namespace Rcpp {
@@ -231,12 +242,8 @@
             
             // Scan for attributes 
             CommentState commentState;
-            Rcpp::Environment base("package:base");
-            Rcpp::Function regexec = base["regexec"];
-            Rcpp::Function regmatches = base["regmatches"];
-            Rcpp::RObject result =  regexec(
-                "^\\s*//\\s+\\[\\[Rcpp::(\\w+)(\\(.*?\\))?\\]\\]\\s*$", lines_);
-            Rcpp::List matches = regmatches(lines_, result);
+            Rcpp::List matches = regexMatches(lines_, 
+                "^\\s*//\\s+\\[\\[Rcpp::(\\w+)(\\(.*?\\))?\\]\\]\\s*$");
             for (int i = 0; i<matches.size(); i++) {   
                 
                 // track whether we are in a comment and bail if we are in one
@@ -272,6 +279,9 @@
                     }
                 } 
             }
+            
+            // Parse embedded R
+            embeddedR_ = parseEmbeddedR(lines_, lines);
         }       
     }
    
@@ -568,6 +578,44 @@
         return Type(type, isConst, isReference);
     }
     
+     // Parse embedded R code chunks from a file (receives the lines of the 
+    // file as a CharcterVector for using with regexec and as a standard
+    // stl vector for traversal/insepection)
+    std::vector<std::string> SourceFileAttributes::parseEmbeddedR(
+                                    Rcpp::CharacterVector linesVector,
+                                    const std::deque<std::string>& lines) {
+        Rcpp::List matches = regexMatches(linesVector, 
+                                          "^\\s*/\\*{3,}\\s+[Rr]\\s*$");
+        bool withinRBlock = false;
+        CommentState commentState;
+        std::vector<std::string> embeddedR;
+                
+        for (int i = 0; i<matches.size(); i++) {   
+         
+            // track comment state
+            std::string line = lines[i];
+            commentState.submitLine(line);
+         
+            // is this a line that begins an R code block?
+            const Rcpp::CharacterVector match = matches[i];
+            bool beginRBlock = match.size() > 0;
+             
+            // check state and do the right thing
+            if (beginRBlock) {
+                withinRBlock = true;
+            } 
+            else if (withinRBlock) {
+                if (commentState.inComment())
+                    embeddedR.push_back(line);
+                else
+                    withinRBlock = false;
+            }
+        }
+          
+        return embeddedR;
+    }
+      
+    
     // Validation helpers
     
     bool SourceFileAttributes::isKnownAttribute(const std::string& name) const {

Modified: pkg/Rcpp/src/AttributesParser.h
===================================================================
--- pkg/Rcpp/src/AttributesParser.h	2012-11-18 16:16:04 UTC (rev 3990)
+++ pkg/Rcpp/src/AttributesParser.h	2012-11-18 16:32:11 UTC (rev 3991)
@@ -210,6 +210,11 @@
             else
                 return false;            
         }
+        
+        // Get lines of embedded R code
+        const std::vector<std::string>& embeddedR() const {
+            return embeddedR_;
+        }
          
     private:
     
@@ -221,6 +226,9 @@
         std::string parseSignature(size_t lineNumber);
         std::vector<std::string> parseArguments(const std::string& argText); 
         Type parseType(const std::string& text); 
+        std::vector<std::string> parseEmbeddedR(
+                                        Rcpp::CharacterVector linesVector,
+                                        const std::deque<std::string>& lines);
         
         // Validation helpers
         bool isKnownAttribute(const std::string& name) const; 
@@ -254,6 +262,7 @@
         std::string sourceFile_;
         CharacterVector lines_;
         std::vector<Attribute> attributes_;
+        std::vector<std::string> embeddedR_;
         std::vector<std::string> roxygenBuffer_;
     };
 



More information about the Rcpp-commits mailing list