blob: 0e77c1c3b58e3eef4d58e1185da39e7ef933869f [file] [log] [blame]
/*!
* Copyright (c) 2015 by Contributors
* \file export.cc
* \brief Exporter module to export document and wrapper functions.
*/
#include <Rcpp.h>
#include <fstream>
#include <sstream>
#include "./base.h"
#include "./export.h"
namespace mxnet {
namespace R {
// docstring related function.
std::string MakeDocString(mx_uint num_args,
const char **arg_names,
const char **arg_type_infos,
const char **arg_descriptions,
bool remove_dup) {
std::set<std::string> visited;
std::ostringstream os;
for (mx_uint i = 0; i < num_args; ++i) {
std::string arg = arg_names[i];
if (visited.count(arg) != 0 && remove_dup) continue;
for (size_t j = 0; j < arg.length(); ++j) {
if (arg[j] == '_') arg[j] = '.';
}
visited.insert(arg);
os << "@param " << arg << " " << arg_type_infos[i] << "\n"
<< " " << arg_descriptions[i] << "\n";
}
return os.str();
}
Exporter* Exporter::Get() {
static Exporter inst;
return &inst;
}
void Exporter::InitRcppModule() {
using namespace Rcpp; // NOLINT(*)
Exporter::Get()->scope_ = ::getCurrentScope();
function("mxnet.internal.export", &Exporter::Export,
Rcpp::List::create(_["path"]),
"Internal function of mxnet, used to export generated functions file.");
}
std::string ExportDocString(const std::string& docstring) {
std::ostringstream os;
std::istringstream is(docstring);
std::string line;
line.resize(1024);
while (is.getline(&line[0], line.length())) {
os << "#' " << line.c_str() << "\n";
}
return os.str();
}
void ExportVArgFunction(std::ostream& os, // NOLINT(*)
const std::string& func_name,
const std::string& docstr) {
std::string prefix = "mx.varg.";
std::string new_name = std::string("mx.") + (func_name.c_str() + prefix.length());
os << "\n" << ExportDocString(docstr)
<< new_name << " <- function(...) {\n"
<< " " << func_name << "(list(...))\n"
<< "}\n";
RLOG_INFO << "Exporting " << func_name << " as " << new_name << "\n";
}
void ExportNormalFunction(std::ostream& os, // NOLINT(*)
const std::string& func_name,
const std::string& docstr) {
os << "\n"
<< ExportDocString(docstr)
<< "#' @name " << func_name << "\n"
<< "NULL\n";
RLOG_INFO << "Exporting " << func_name << " docstring\n";
}
void Exporter::Export(const std::string& path) {
std::string filename = path + "/R/mxnet_generated.R";
std::ofstream script(filename.c_str());
RLOG_INFO << "Start to generate "<< path << " ...\n";
script << "######\n"
<< "# Generated by mxnet.export, do not edit by hand.\n"
<< "######\n";
Rcpp::Module *scope = Exporter::Get()->scope_;
Rcpp::CharacterVector func_names = scope->functions_names();
for (size_t i = 0; i < func_names.size(); ++i) {
std::string fname = Rcpp::as<std::string>(func_names[i]);
// skip internal functions
if (fname.find("internal.") != std::string::npos) continue;
if (fname == "mx.varg.symbol.Concat" || fname == "mx.varg.symbol.concat") continue;
Rcpp::List func_info(scope->get_function(fname));
std::string docstr = Rcpp::as<std::string>(func_info[2]);
if (docstr.find("@export") == std::string::npos) continue;
if (fname.find("mx.varg.") == 0) {
ExportVArgFunction(script, fname, docstr);
} else {
ExportNormalFunction(script, fname, docstr);
}
}
RLOG_INFO << "All generation finished on "<< path << " ...\n";
}
} // namespace R
} // namespace mxnet