11 #include <boost/filesystem.hpp> 
   19 #include <vcsn/config.hh> 
   34       : 
std::runtime_error(what)
 
   42       xgetenv(
const std::string& var, 
const std::string& val = 
"")
 
   44         const char* cp = getenv(var.c_str());
 
   48 #define XGETENV(Name) xgetenv(#Name, Name) 
   52       std::string expand_tilda(std::string 
res)
 
   54         if (!res.empty() && res[0] == 
'~')
 
   56             assert(res.size() == 1 || res[1] == 
'/');
 
   57             auto home = xgetenv(
"HOME", xgetenv(
"USERPROFILE"));
 
   58             char const *hdrive = getenv(
"HOMEDRIVE");
 
   59             char const *hres = getenv(
"HOMERES");
 
   61               res.replace(0, 1, home);
 
   62             else if (hdrive && hres)
 
   63               res.replace(0, 1, std::string(hdrive) + hres);
 
   65               res.replace(0, 1, xgetenv(
"VCSN_TMPDIR", 
"/tmp"));
 
   71       void ensure_parent_directory(
const std::string& path)
 
   73         boost::filesystem::path p(path);
 
   74         boost::filesystem::create_directories(p.parent_path());
 
   78       std::string tmpname(std::string 
res)
 
   98         void print(
const std::string& base)
 
  100           ensure_parent_directory(base);
 
  103           auto tmp = tmpname(base);
 
  105             std::ofstream o{tmp + 
".cc"};
 
  108           boost::filesystem::rename(tmp + 
".cc", base + 
".cc");
 
  119         void print_type(
const std::string& 
type)
 
  127         void throw_compiler_errors(std::string cmd,
 
  128                                    const std::string& err)
 
  147           static auto r1 = std::regex{
"static assertion failed: (.*)$",
 
  148                                       std::regex::extended};
 
  149           static auto r2 = std::regex{
"static_assert failed \"(.*)\"$",
 
  150                                       std::regex::extended};
 
  153           std::string assertions;
 
  154           while (std::getline(*is, line))
 
  155             if (std::regex_search(line, smatch, r1)
 
  156                 || std::regex_search(line, smatch, r2))
 
  157               assertions += std::string(smatch[1]) + 
'\n';
 
  158           if (getenv(
"VCSN_VERBOSE"))
 
  160               cmd += 
"\n  compiler error messages:\n";
 
  163           throw jit_error(assertions, 
"  failed command:\n    " + cmd);
 
  170         void cxx(std::string cmd, 
const std::string& tmp)
 
  172           auto err = tmp + 
".err";
 
  173           if (getenv(
"VCSN_DEBUG"))
 
  174             std::cerr << 
"run: " << cmd << std::endl;
 
  175           if (system((cmd + 
" 2>'" + err + 
"'").c_str()))
 
  176             throw_compiler_errors(cmd, err);
 
  180               std::ifstream 
log{err};
 
  181               std::cerr << 
log.rdbuf();
 
  186               boost::filesystem::remove(err);
 
  193         void cxx_compile(
const std::string& base)
 
  195           auto tmp = tmpname(base);
 
  198           auto cmd = (std::string{
"LC_ALL=C"}
 
  203                       + 
" -fPIC '" + base + 
".cc' -c" 
  204                       + 
" -o '" + tmp + 
".o'");
 
  211         void cxx_link(
const std::string& base)
 
  213           auto tmp = tmpname(base);
 
  214           auto cmd = (std::string{
"LC_ALL=C"}
 
  218                       + 
" -fPIC -lvcsn '" + tmp + 
".o' -shared" 
  219                       + 
" -o '" + tmp + 
".so'" 
  225         std::string plugindir()
 const 
  227           auto res = xgetenv(
"VCSN_PLUGINDIR",
 
  228                              xgetenv(
"VCSN_HOME", 
"~/.vcsn") + 
"/plugins");
 
  229           res = expand_tilda(res);
 
  235         std::string 
split(
const std::string& s)
 const 
  238           const size_t size = 150;
 
  239           for (
unsigned i = 0; i < s.length(); i += 
size)
 
  243               res += s.substr(i, size);
 
  256         void jit(
const std::string& base)
 
  258           auto tmp = tmpname(base);
 
  260             namespace chr = std::chrono;
 
  261             using clock = chr::steady_clock;
 
  262             auto start = clock::now();
 
  263             static bool no_python = !!getenv(
"VCSN_NO_PYTHON");
 
  268                 boost::filesystem::rename(tmp + 
".so", base + 
".so");
 
  273                 if (!getenv(
"VCSN_DEBUG"))
 
  274                   boost::filesystem::remove(tmp + 
".o");
 
  278                 auto linkflags = 
printer_.linkflags();
 
  279                 if (!linkflags.empty())
 
  280                   linkflags = 
" LDFLAGS+='" + linkflags + 
"'";
 
  281                 cxx(
"vcsn compile -shared" + linkflags + 
" '" + base + 
".cc'",
 
  285               = chr::duration_cast<chr::milliseconds>(clock::now() - start);
 
  286             if (getenv(
"VCSN_TIME"))
 
  288                 std::ofstream{
"/tmp/vcsn-compile.log",
 
  291                 << (no_python ? 
"C++, " : 
"Py,  ")
 
  292                 << 
'\'' << base.substr(plugindir().
size()) << 
'\'' 
  294                 if (getenv(
"VCSN_TIME2"))
 
  295                   std::cerr << d.count() << 
"ms: " << base << 
'\n';
 
  298           static bool first = 
true;
 
  304           lt_dlhandle lib = lt_dlopen((base + 
".so").c_str());
 
  305           VCSN_REQUIRE(lib, 
"cannot load lib: ", base, 
".so: ", lt_dlerror());
 
  309         void compile(
const std::string& ctx)
 
  311           printer_.header(
"vcsn/ctx/instantiate.hh");
 
  313             plugindir() + 
"contexts/" + 
split(ctx);
 
  321             "  VCSN_CTX_INSTANTIATE(ctx_t);\n" 
  331           printer_.header(
"vcsn/misc/attributes.hh"); 
 
  332           printer_.header(
"vcsn/dyn/name.hh"); 
 
  333           printer_.header(
"vcsn/dyn/registries.hh");
 
  334           for (
const auto& algo: algos)
 
  338           for (
const auto& algo: algos)
 
  341                  << 
"// " << algo.first << 
'.';
 
  344               for (
const auto& s: algo.second)
 
  351                   types += (first ? 
"" : 
", ") + t;
 
  357                 "static bool vcsn_" << algo.first << 
" ATTRIBUTE_USED =" << 
incendl 
  358                  << 
"vcsn::dyn::detail::" << algo.first << 
"_register(" << 
incendl 
  359                  << 
"vcsn::ssignature<" << types << 
">()," << 
iendl 
  360                  << 
"vcsn::dyn::detail::" << algo.first << 
"<" << types << 
">" << 
decendl 
  366           std::string base = (plugindir()
 
  368                               + begin(algos)->first + 
"/" 
  369                               + 
split(begin(algos)->second.to_string()));
 
  375         std::ostringstream 
os;
 
  382       translation translate;
 
  383       translate.compile(ctx);
 
  388       translation translate;
 
  389       std::set<std::pair<std::string, signature>> algos{{algo, sig}};
 
  390       if (algo == 
"delay_automaton" 
  391           || algo == 
"is_synchronized")
 
  393           algos.emplace(
"delay_automaton", sig);
 
  394           algos.emplace(
"is_synchronized", sig);
 
  396       translate.compile(algos);
 
std::string type(const automaton &a)
The implementation type of a. 
std::ostream & print(const automaton &aut, std::ostream &out=std::cout, const std::string &format="default")
Print automaton a on out using format format. 
std::ostream & incendl(std::ostream &o)
Increment the indentation, print an end of line, and set the indentation. 
size_t size(const ExpSet &rs, const typename ExpSet::value_t &r)
std::string get_file_contents(const std::string &file)
Return the contents of file. 
std::ostream & iendl(std::ostream &o)
Print an end of line, then set the indentation. 
weightset_mixin< detail::log_impl > log
jit_error(const std::string &assert, const std::string &what)
std::ostream & decendl(std::ostream &o)
Decrement the indentation, print an end of line, and set the indentation. 
auto out(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions leaving state s. 
std::shared_ptr< ast_node > parse_type(const std::string &type)
Parse a type, and return its AST. 
ast::context_printer printer_
#define VCSN_REQUIRE(Cond,...)                              
A macro similar to require. 
Indentation relative functions. 
void compile(const std::string &ctx)
Compile, and load, a DSO with instantiations for ctx. 
Request the set implementation (bool weights). 
std::string to_string(identities i)
Wrapper around operator<<. 
std::shared_ptr< std::istream > open_input_file(const std::string &file)
Open file for reading and return its autoclosing stream. 
polynomial split(const expression &exp)
Break exp. 
Signature of a function call. 
std::ostringstream os
The output stream: the corresponding C++ snippet to compile. 
std::shared_ptr< ast_node > parse_context(const std::string &ctx)
Parse a context, and return its AST. 
std::ostream & print_context(const context &ctx, std::ostream &o, const std::string &fmt)
Bridge (print).