@@ -54,6 +54,14 @@ namespace attributes {
54
54
bool exists () const { return exists_; }
55
55
time_t lastModified () const { return lastModified_; }
56
56
57
+ std::string extension () const {
58
+ std::string::size_type pos = path_.find_last_of (' .' );
59
+ if (pos != std::string::npos)
60
+ return path_.substr (pos);
61
+ else
62
+ return " " ;
63
+ }
64
+
57
65
bool operator <(const FileInfo& other) const {
58
66
return path_ < other.path_ ;
59
67
};
@@ -143,7 +151,17 @@ namespace attributes {
143
151
{
144
152
}
145
153
bool empty () const { return name ().empty (); }
146
-
154
+
155
+ bool operator ==(const Type& other) const {
156
+ return name_ == other.name_ &&
157
+ isConst_ == other.isConst_ &&
158
+ isReference_ == other.isReference_ ;
159
+ };
160
+
161
+ bool operator !=(const Type& other) const {
162
+ return !(*this == other);
163
+ };
164
+
147
165
const std::string& name () const { return name_; }
148
166
std::string full_name () const {
149
167
std::string res ;
@@ -175,6 +193,17 @@ namespace attributes {
175
193
}
176
194
177
195
bool empty () const { return type ().empty (); }
196
+
197
+ bool operator ==(const Argument& other) const {
198
+ return name_ == other.name_ &&
199
+ type_ == other.type_ &&
200
+ defaultValue_ == other.defaultValue_ ;
201
+ };
202
+
203
+ bool operator !=(const Argument& other) const {
204
+ return !(*this == other);
205
+ };
206
+
178
207
179
208
const std::string& name () const { return name_; }
180
209
const Type& type () const { return type_; }
@@ -192,14 +221,13 @@ namespace attributes {
192
221
Function () {}
193
222
Function (const Type& type,
194
223
const std::string& name,
195
- const std::vector<Argument>& arguments,
196
- const std::string& source)
197
- : type_(type), name_(name), arguments_(arguments), source_(source)
224
+ const std::vector<Argument>& arguments)
225
+ : type_(type), name_(name), arguments_(arguments)
198
226
{
199
227
}
200
228
201
229
Function renamedTo (const std::string& name) const {
202
- return Function (type (), name, arguments (), source () );
230
+ return Function (type (), name, arguments ());
203
231
}
204
232
205
233
std::string signature () const { return signature (name ()); }
@@ -210,17 +238,25 @@ namespace attributes {
210
238
}
211
239
212
240
bool empty () const { return name ().empty (); }
241
+
242
+ bool operator ==(const Function& other) const {
243
+ return type_ == other.type_ &&
244
+ name_ == other.name_ &&
245
+ arguments_ == other.arguments_ ;
246
+ };
247
+
248
+ bool operator !=(const Function& other) const {
249
+ return !(*this == other);
250
+ };
213
251
214
252
const Type& type () const { return type_; }
215
253
const std::string& name () const { return name_; }
216
254
const std::vector<Argument>& arguments () const { return arguments_; }
217
- const std::string& source () const { return source_; }
218
-
255
+
219
256
private:
220
257
Type type_;
221
258
std::string name_;
222
259
std::vector<Argument> arguments_;
223
- std::string source_;
224
260
};
225
261
226
262
// Attribute parameter (with optional value)
@@ -229,6 +265,16 @@ namespace attributes {
229
265
Param () {}
230
266
explicit Param (const std::string& paramText);
231
267
bool empty () const { return name ().empty (); }
268
+
269
+ bool operator ==(const Param& other) const {
270
+ return name_ == other.name_ &&
271
+ value_ == other.value_ ;
272
+ };
273
+
274
+ bool operator !=(const Param& other) const {
275
+ return !(*this == other);
276
+ };
277
+
232
278
233
279
const std::string& name () const { return name_; }
234
280
const std::string& value () const { return value_; }
@@ -251,6 +297,18 @@ namespace attributes {
251
297
}
252
298
253
299
bool empty () const { return name ().empty (); }
300
+
301
+ bool operator ==(const Attribute& other) const {
302
+ return name_ == other.name_ &&
303
+ params_ == other.params_ &&
304
+ function_ == other.function_ &&
305
+ roxygen_ == other.roxygen_ ;
306
+ };
307
+
308
+ bool operator !=(const Attribute& other) const {
309
+ return !(*this == other);
310
+ };
311
+
254
312
255
313
const std::string& name () const { return name_; }
256
314
@@ -749,6 +807,9 @@ namespace attributes {
749
807
Rcpp::Function filepath = baseEnv[" file.path" ];
750
808
Rcpp::Function normalizePath = baseEnv[" normalizePath" ];
751
809
Rcpp::Function fileExists = baseEnv[" file.exists" ];
810
+ Rcpp::Environment toolsEnv = Rcpp::Environment::namespace_env (
811
+ " tools" );
812
+ Rcpp::Function filePathSansExt = toolsEnv[" file_path_sans_ext" ];
752
813
753
814
// get the path to the source file's directory
754
815
Rcpp::CharacterVector sourceDir = dirname (sourceFile);
@@ -789,6 +850,25 @@ namespace attributes {
789
850
newDependencies.push_back (
790
851
FileInfo (Rcpp::as<std::string>(include)));
791
852
}
853
+
854
+ std::vector<std::string> exts;
855
+ exts.push_back (" .cc" );
856
+ exts.push_back (" .cpp" );
857
+ for (size_t i = 0 ; i<exts.size (); ++i) {
858
+
859
+ // look for corresponding cpp file and add it
860
+ std::string file = Rcpp::as<std::string>(
861
+ filePathSansExt (include)) + exts[i];
862
+
863
+ exists = fileExists (file);
864
+ if (exists[0 ]) {
865
+ if (addUniqueDependency (file,
866
+ pDependencies)) {
867
+ FileInfo fileInfo (file);
868
+ newDependencies.push_back (fileInfo);
869
+ }
870
+ }
871
+ }
792
872
}
793
873
}
794
874
}
@@ -804,8 +884,17 @@ namespace attributes {
804
884
// parse the source dependencies from the passed lines
805
885
std::vector<FileInfo> parseSourceDependencies (
806
886
const std::string& sourceFile) {
887
+
888
+ // parse dependencies
807
889
std::vector<FileInfo> dependencies;
808
890
parseSourceDependencies (sourceFile, &dependencies);
891
+
892
+ // remove main source file
893
+ dependencies.erase (std::remove (dependencies.begin (),
894
+ dependencies.end (),
895
+ FileInfo (sourceFile)),
896
+ dependencies.end ());
897
+
809
898
return dependencies;
810
899
}
811
900
@@ -912,22 +1001,32 @@ namespace attributes {
912
1001
return os;
913
1002
}
914
1003
915
- // Argument operator <<
916
- std::ostream& operator <<(std::ostream& os, const Argument& argument) {
1004
+ // Print argument
1005
+ void printArgument (std::ostream& os,
1006
+ const Argument& argument,
1007
+ bool printDefault = true ) {
917
1008
if (!argument.empty ()) {
918
1009
os << argument.type ();
919
1010
if (!argument.name ().empty ()) {
920
1011
os << " " ;
921
1012
os << argument.name ();
922
- if (!argument.defaultValue ().empty ())
1013
+ if (printDefault && !argument.defaultValue ().empty ())
923
1014
os << " = " << argument.defaultValue ();
924
1015
}
925
1016
}
1017
+ }
1018
+
1019
+ // Argument operator <<
1020
+ std::ostream& operator <<(std::ostream& os, const Argument& argument) {
1021
+ printArgument (os, argument);
926
1022
return os;
927
1023
}
928
1024
929
- // Function operator <<
930
- std::ostream& operator <<(std::ostream& os, const Function& function) {
1025
+ // Print function
1026
+ void printFunction (std::ostream& os,
1027
+ const Function& function,
1028
+ bool printArgDefaults = true ) {
1029
+
931
1030
if (!function.empty ()) {
932
1031
if (!function.type ().empty ()) {
933
1032
os << function.type ();
@@ -937,12 +1036,17 @@ namespace attributes {
937
1036
os << " (" ;
938
1037
const std::vector<Argument>& arguments = function.arguments ();
939
1038
for (std::size_t i = 0 ; i<arguments.size (); i++) {
940
- os << arguments[i];
1039
+ printArgument (os, arguments[i], printArgDefaults) ;
941
1040
if (i != (arguments.size ()-1 ))
942
1041
os << " , " ;
943
1042
}
944
1043
os << " )" ;
945
1044
}
1045
+ }
1046
+
1047
+ // Function operator <<
1048
+ std::ostream& operator <<(std::ostream& os, const Function& function) {
1049
+ printFunction (os, function);
946
1050
return os;
947
1051
}
948
1052
@@ -1075,21 +1179,26 @@ namespace attributes {
1075
1179
// Recursively parse dependencies if requested
1076
1180
if (parseDependencies) {
1077
1181
1078
- // get local includes
1182
+ // get source dependencies
1079
1183
sourceDependencies_ = parseSourceDependencies (sourceFile);
1080
1184
1081
- // parse attributes and modules from each local include
1185
+ // parse attributes and modules from each dependent file
1082
1186
for (size_t i = 0 ; i<sourceDependencies_.size (); i++) {
1083
1187
1084
1188
// perform parse
1085
1189
std::string dependency = sourceDependencies_[i].path ();
1086
1190
SourceFileAttributesParser parser (dependency, false );
1087
1191
1088
- // copy to base attributes
1089
- std::copy (parser.begin (),
1090
- parser.end (),
1091
- std::back_inserter (attributes_));
1092
-
1192
+ // copy to base attributes (if it's a new attribute)
1193
+ for (SourceFileAttributesParser::const_iterator
1194
+ it = parser.begin (); it != parser.end (); ++it) {
1195
+ if (std::find (attributes_.begin (),
1196
+ attributes_.end (),
1197
+ *it) == attributes_.end ()) {
1198
+ attributes_.push_back (*it);
1199
+ }
1200
+ }
1201
+
1093
1202
// copy to base modules
1094
1203
std::copy (parser.modules ().begin (),
1095
1204
parser.modules ().end (),
@@ -1339,7 +1448,7 @@ namespace attributes {
1339
1448
arguments.push_back (Argument (name, type, defaultValue));
1340
1449
}
1341
1450
1342
- return Function (type, name, arguments, signature );
1451
+ return Function (type, name, arguments);
1343
1452
}
1344
1453
1345
1454
@@ -2390,7 +2499,8 @@ namespace attributes {
2390
2499
// include prototype if requested
2391
2500
if (includePrototype) {
2392
2501
ostr << " // " << function.name () << std::endl;
2393
- ostr << function << " ;" ;
2502
+ printFunction (ostr, function, false );
2503
+ ostr << " ;" ;
2394
2504
}
2395
2505
2396
2506
// write the C++ callable SEXP-based function (this version
@@ -2746,7 +2856,7 @@ namespace {
2746
2856
// always include Rcpp.h in case the user didn't
2747
2857
ostr << std::endl << std::endl;
2748
2858
ostr << " #include <Rcpp.h>" << std::endl;
2749
- generateCpp (ostr, sourceAttributes, false , false , contextId_);
2859
+ generateCpp (ostr, sourceAttributes, true , false , contextId_);
2750
2860
generatedCpp_ = ostr.str ();
2751
2861
std::ofstream cppOfs (generatedCppSourcePath ().c_str (),
2752
2862
std::ofstream::out | std::ofstream::app);
@@ -2813,6 +2923,17 @@ namespace {
2813
2923
const std::string& cppSourcePath () const {
2814
2924
return cppSourcePath_;
2815
2925
}
2926
+
2927
+ const std::vector<std::string> cppDependencySourcePaths () {
2928
+ std::vector<std::string> dependencies;
2929
+ for (size_t i = 0 ; i<sourceDependencies_.size (); ++i) {
2930
+ FileInfo dep = sourceDependencies_[i];
2931
+ if (dep.extension () == " .cc" || dep.extension () == " .cpp" ) {
2932
+ dependencies.push_back (dep.path ());
2933
+ }
2934
+ }
2935
+ return dependencies;
2936
+ }
2816
2937
2817
2938
std::string buildDirectory () const {
2818
2939
return buildDirectory_;
@@ -3044,6 +3165,7 @@ BEGIN_RCPP
3044
3165
return List::create (
3045
3166
_[" contextId" ] = pDynlib->contextId (),
3046
3167
_[" cppSourcePath" ] = pDynlib->cppSourcePath (),
3168
+ _[" cppDependencySourcePaths" ] = pDynlib->cppDependencySourcePaths (),
3047
3169
_[" buildRequired" ] = buildRequired,
3048
3170
_[" buildDirectory" ] = pDynlib->buildDirectory (),
3049
3171
_[" generatedCpp" ] = pDynlib->generatedCpp (),
0 commit comments