10 #include <boost/filesystem.hpp>
17 #include <vcsn/config.hh>
32 : std::runtime_error(what)
40 xgetenv(
const std::string& var,
const std::string& val =
"")
42 const char* cp = getenv(var.c_str());
48 std::string expand_tilda(std::string res)
50 if (!res.empty() && res[0] ==
'~')
52 assert(res.size() == 1 || res[1] ==
'/');
53 auto home = xgetenv(
"HOME", xgetenv(
"USERPROFILE"));
54 char const *hdrive = getenv(
"HOMEDRIVE");
55 char const *hres = getenv(
"HOMERES");
57 res.replace(0, 1, home);
58 else if (hdrive && hres)
59 res.replace(0, 1, std::string(hdrive) + hres);
61 res.replace(0, 1, xgetenv(
"VCSN_TMPDIR",
"/tmp"));
67 void ensure_parent_directory(
const std::string& path)
69 boost::filesystem::path p(path);
70 boost::filesystem::create_directories(p.parent_path());
74 std::string tmpname(std::string res)
89 while ((c =
is.get()) != EOF)
90 if (c ==
'<' || c ==
',' || c ==
'_' || c ==
'>')
111 void print(
const std::string& base)
113 ensure_parent_directory(base);
116 auto tmp = tmpname(base);
118 std::ofstream o{tmp +
".cc"};
121 boost::filesystem::rename(tmp +
".cc", base +
".cc");
126 void print_context(
const std::string& ctx)
130 auto ast =
parser_.parse_context();
135 void print_type(
const std::string&
type)
148 void cxx(std::string cmd,
const std::string& tmp)
150 auto err = tmp +
".err";
153 cmd =
"LC_ALL=C " + cmd;
155 if (getenv(
"VCSN_DEBUG"))
156 std::cerr <<
"run: " << cmd << std::endl;
157 std::string assertions;
158 if (system((cmd + +
" 2>'" + err +
"'").c_str()))
173 static std::regex r1(
"error: static assertion failed: (.*)$",
174 std::regex::extended);
175 static std::regex r2(
"error: static_assert failed \"(.*)\"$",
176 std::regex::extended);
179 while (std::getline(*
is, line))
181 if (std::regex_search(line, smatch, r1)
182 || std::regex_search(line, smatch, r2))
183 assertions += std::string(smatch[1]) +
"\n";
185 throw jit_error(assertions,
" failed command:\n " + cmd);
187 else if (!getenv(
"VCSN_DEBUG"))
188 boost::filesystem::remove(err);
194 void cxx_compile(
const std::string& base)
196 auto tmp = tmpname(base);
197 auto cmd = (xgetenv(
"VCSN_CCACHE", VCSN_CCACHE)
198 +
" " + xgetenv(
"VCSN_CXX", VCSN_CXX)
199 +
" " + xgetenv(
"VCSN_CXXFLAGS", VCSN_CXXFLAGS)
200 +
" " + xgetenv(
"VCSN_CPPFLAGS", VCSN_CPPFLAGS)
201 +
" -fPIC '" + base +
".cc' -c"
202 +
" -o '" + tmp +
".o'");
209 void cxx_link(
const std::string& base)
211 auto tmp = tmpname(base);
212 auto cmd = (xgetenv(
"VCSN_CXX", VCSN_CXX)
213 +
" " + xgetenv(
"VCSN_CXXFLAGS", VCSN_CXXFLAGS)
214 +
" " + xgetenv(
"VCSN_LDFLAGS", VCSN_LDFLAGS)
215 +
" -fPIC -lvcsn '" + tmp +
".o' -shared"
216 +
" -o '" + tmp +
".so'"
222 std::string plugindir()
const
224 auto res = xgetenv(
"VCSN_PLUGINDIR",
225 xgetenv(
"VCSN_HOME",
"~/.vcsn") +
"/plugins");
226 res = expand_tilda(res);
232 std::string
split(
const std::string& s)
const
235 const size_t size = 200;
236 for (
unsigned i = 0; i < s.length(); i += size)
240 res += s.substr(i, size);
253 void jit(
const std::string& base)
257 auto tmp = tmpname(base);
258 boost::filesystem::rename(tmp +
".so", base +
".so");
259 static bool first =
true;
265 lt_dlhandle lib = lt_dlopen((base +
".so").c_str());
266 require(lib,
"cannot load lib: ", base,
".so: ", lt_dlerror());
271 if (!getenv(
"VCSN_DEBUG"))
273 boost::filesystem::remove(tmp +
".cc");
274 boost::filesystem::remove(tmp +
".o");
279 void compile(
const std::string& ctx)
281 printer_.header(
"vcsn/ctx/instantiate.hh");
291 " VCSN_CTX_INSTANTIATE(ctx_t);\n"
299 void compile(
const std::string& name,
const signature& sig)
301 printer_.header(
"vcsn/misc/name.hh");
304 plugindir() +
"algos/" + name +
"/" +
split(sig.to_string());
307 for (
const auto& s: sig)
314 types += (count ?
", " :
"") + t;
320 <<
"vcsn::dyn::detail::" << name <<
"_register(" <<
incendl
321 <<
"vcsn::ssignature<" << types <<
">()," <<
iendl
322 <<
"vcsn::dyn::detail::" << name <<
"<" << types <<
">" <<
decendl
329 std::istringstream
is;
331 std::ostringstream
os;
339 translation translate;
340 translate.compile(ctx);
345 translation translate;
346 translate.compile(algo, sig);
std::ostream & iendl(std::ostream &o)
Print an end of line, then set the indentation.
Indentation relative functions.
std::string to_string(identities i)
std::ostream & print(const automaton &a, std::ostream &o, const std::string &format="default")
Print automaton a on o using format format.
std::ostream & incendl(std::ostream &o)
Increment the indentation, print an end of line, and set the indentation.
void compile(const std::string &ctx)
Compile, and load, a DSO with instantiations for ctx.
polynomial split(const polynomial &p)
Break all the expressions in p.
Signature of a function call.
std::ostream & decendl(std::ostream &o)
Decrement the indentation, print an end of line, and set the indentation.
static std::string sname(const std::string &vname)
Convert a dynamic name into a static one.
std::istringstream is
The input stream: the specification to translate.
jit_error(const std::string &assert, const std::string &what)
std::ostringstream os
The output stream: the corresponding C++ snippet to compile.
std::shared_ptr< std::istream > open_input_file(const std::string &file)
Open file for reading and return its autoclosing stream.
ast::context_printer printer_
ast::context_parser parser_
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.