Functions
stanc_helper.hpp File Reference
#include <stan/version.hpp>
#include <stan/lang/compiler.hpp>
#include <stan/lang/compile_functions.hpp>
#include <stan/io/cmd_line.hpp>
#include <exception>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>

Go to the source code of this file.

Functions

void print_version (std::ostream *out_stream)
 
void print_stanc_help (std::ostream *out_stream)
 
void delete_file (std::ostream *err_stream, const std::string &file_name)
 
std::string identifier_from_file_name (const std::string &in_file_name)
 
bool has_extension (const std::string &file_name, const std::string &extension)
 
void check_identifier (const std::string &identifier, const std::string &identifier_type)
 
int stanc_helper (int argc, const char *argv[], std::ostream *out_stream, std::ostream *err_stream)
 

Function Documentation

void check_identifier ( const std::string identifier,
const std::string identifier_type 
)
inline

Test whether a given string is a valid C++ identifier and throw an exception when it is not.

Parameters
[in]identifierthe identifier to be checked
[in]identifier_typethe type of the identifier to be reported in error messages

Definition at line 148 of file stanc_helper.hpp.

References stan::math::invalid_argument(), lem_server::msg, and string.

Referenced by stanc_helper().

149  {
150  if (!isalpha(identifier[0]) && identifier[0] != '_') {
151  std::string msg(identifier_type + " must not start with a "
152  "number or symbol other than _");
153  throw std::invalid_argument(msg);
154  }
155  for (std::string::const_iterator strIt = identifier.begin();
156  strIt != identifier.end(); strIt++) {
157  if (!isalnum(*strIt) && *strIt != '_') {
158  std::string msg(identifier_type
159  + " must contain only letters, numbers and _");
160  throw std::invalid_argument(msg);
161  }
162  }
163 }
void invalid_argument(const char *function, const char *name, const T &y, const char *msg1, const char *msg2)
enum BeamMode string
void delete_file ( std::ostream *  err_stream,
const std::string file_name 
)
inline

Delte the file at the specified path, writing messages to error stream if not possible. Do nothing on zero size file name input. Only write to error stream if it is non-null.

Parameters
[in,out]err_streamstream to which error messages are written
[in]file_namepath of file

Definition at line 78 of file stanc_helper.hpp.

References allTimeWatchdog::endl, and makeTestPickles::return_code.

Referenced by stanc_helper(), and TEST().

79  {
80  if (file_name.size() == 0)
81  return;
82  int return_code = std::remove(file_name.c_str());
83  if (return_code != 0)
84  if (err_stream)
85  *err_stream << "Could not remove output file=" << file_name
86  << std::endl;
87 }
bool has_extension ( const std::string file_name,
const std::string extension 
)
inline

Check whether a given file has the specified extension.

Parameters
[in]file_nameThe name of the file
[in]extensionThe extension (WITHOUT dot)- e.g. "stan".
Returns
true if the file has the extension

Definition at line 127 of file stanc_helper.hpp.

Referenced by stanc_helper().

128  {
129  if (file_name.length() >= extension.length() + 1) { // +1 for the dot
130  if (0 == file_name.compare (file_name.length() - extension.length(),
131  extension.length(), extension)
132  && file_name[file_name.length() - extension.length() - 1] == '.')
133  return true;
134  else
135  return false;
136  } else {
137  return false;
138  }
139 }
std::string identifier_from_file_name ( const std::string in_file_name)
inline

Transform a provided input file name into a valid C++ identifier

Parameters
[in]in_file_namethe name of the input file
Returns
a valid C++ identifier based on the file name.

Definition at line 94 of file stanc_helper.hpp.

References fillBadChanDBTables::result, and string.

Referenced by stanc_helper().

94  {
95  size_t slashInd = in_file_name.rfind('/');
96  size_t ptInd = in_file_name.rfind('.');
97  if (ptInd == std::string::npos)
98  ptInd = in_file_name.length();
99  if (slashInd == std::string::npos) {
100  slashInd = in_file_name.rfind('\\');
101  }
102  if (slashInd == std::string::npos) {
103  slashInd = 0;
104  } else {
105  slashInd++;
106  }
108  in_file_name.substr(slashInd, ptInd - slashInd);
109  for (std::string::iterator strIt = result.begin();
110  strIt != result.end(); strIt++) {
111  if (!isalnum(*strIt) && *strIt != '_') {
112  *strIt = '_';
113  }
114  }
115 
116  return result;
117 }
enum BeamMode string
void print_stanc_help ( std::ostream *  out_stream)
inline

Prints the Stan compiler (stanc) help.

Parameters
[in,out]out_streamstream to which help is written

Definition at line 37 of file stanc_helper.hpp.

References allTimeWatchdog::endl, stan::io::print_help_option(), and print_version().

Referenced by stanc_helper(), and TEST().

37  {
39 
40  if (!out_stream) return;
41 
42  *out_stream << std::endl;
43  print_version(out_stream);
44  *out_stream << std::endl;
45 
46  *out_stream << "USAGE: " << "stanc [options] <model_file>" << std::endl;
47  *out_stream << std::endl;
48 
49  *out_stream << "OPTIONS:" << std::endl;
50  *out_stream << std::endl;
51 
52  print_help_option(out_stream, "help", "", "Display this information");
53 
54  print_help_option(out_stream, "version", "", "Display stanc version number");
55 
56  print_help_option(out_stream, "name", "string",
57  "Model name",
58  "default = \"$model_filename_model\"");
59 
60  print_help_option(out_stream, "o", "file",
61  "Output file for generated C++ code",
62  "default = \"$name.cpp\"");
63 
64  print_help_option(out_stream, "allow_undefined", "",
65  "Do not fail if a function is declared but not defined");
66  // TODO(martincerny) help for standalone function compilation
67 }
void print_version(std::ostream *out_stream)
void print_help_option(std::ostream *o, const std::string &key, const std::string &value_type, const std::string &msg, const std::string &note="")
Definition: cmd_line.hpp:74
void print_version ( std::ostream *  out_stream)
inline

Print the version of stanc with major, minor and patch.

Parameters
[in,out]out_streamstream to which version is written.

Definition at line 21 of file stanc_helper.hpp.

References allTimeWatchdog::endl, stan::MAJOR_VERSION, stan::MINOR_VERSION, and stan::PATCH_VERSION.

Referenced by print_stanc_help(), stanc_helper(), and TEST().

21  {
22  if (!out_stream) return;
23  *out_stream << "stanc version "
25  << "."
27  << "."
29  << std::endl;
30 }
const std::string MINOR_VERSION
Definition: version.hpp:24
const std::string PATCH_VERSION
Definition: version.hpp:27
const std::string MAJOR_VERSION
Definition: version.hpp:21
int stanc_helper ( int  argc,
const char *  argv[],
std::ostream *  out_stream,
std::ostream *  err_stream 
)
inline

Invoke the stanc command on the specified argument list, writing output and error messages to the specified streams, return a return code.

The return codes are: 0 for success, -1 for an exception, -2 is parsing failed, and -3 if there are invalid arguments.

Parameters
[in]argcnumber of arguments
[in]argvarguments
[in,out]out_streamstream to which output is written
[in,out]err_streamstream to which error messages are written
Returns
return code

Definition at line 180 of file stanc_helper.hpp.

References ana::assert(), stan::io::cmd_line::bare(), stan::io::cmd_line::bare_size(), check_identifier(), run_hadd::cmd, stan::lang::compile(), stan::lang::compile_functions(), delete_file(), e, allTimeWatchdog::endl, has_extension(), stan::io::cmd_line::has_flag(), stan::io::cmd_line::has_key(), identifier_from_file_name(), in, stan::math::invalid_argument(), lem_server::msg, ns, confusionMatrixTree::out, print_stanc_help(), print_version(), string, and stan::io::cmd_line::val().

Referenced by main(), run_helper(), and TEST().

181  {
182  enum CompilationType {
183  kModel,
184  kStandaloneFunctions
185  };
186  static const int SUCCESS_RC = 0;
187  static const int EXCEPTION_RC = -1;
188  static const int PARSE_FAIL_RC = -2;
189  static const int INVALID_ARGUMENT_RC = -3;
190 
191  std::string out_file_name; // declare outside of try to delete in catch
192 
193  try {
194  stan::io::cmd_line cmd(argc, argv);
195 
196  if (cmd.has_flag("help")) {
197  print_stanc_help(out_stream);
198  return SUCCESS_RC;
199  }
200 
201  if (cmd.has_flag("version")) {
202  print_version(out_stream);
203  return SUCCESS_RC;
204  }
205 
206  if (cmd.bare_size() != 1) {
207  std::string msg("Require model file as argument. ");
208  throw std::invalid_argument(msg);
209  }
210  std::string in_file_name;
211  cmd.bare(0, in_file_name);
212 
213  CompilationType compilation_type;
214  if (has_extension(in_file_name, "stanfuncs")) {
215  compilation_type = kStandaloneFunctions;
216  } else {
217  compilation_type = kModel;
218  }
219 
220  std::ifstream in(in_file_name.c_str());
221  if (!in.is_open()) {
222  std::stringstream msg;
223  msg << "Failed to open model file "
224  << in_file_name.c_str();
225  throw std::invalid_argument(msg.str());
226  }
227 
228  std::vector<std::string> include_paths;
229  include_paths.push_back("");
230 
231  bool allow_undefined = cmd.has_flag("allow_undefined");
232 
233  bool valid_input = false;
234 
235  switch (compilation_type) {
236  case kModel: {
237  std::string model_name;
238  if (cmd.has_key("name")) {
239  cmd.val("name", model_name);
240  } else {
241  model_name = identifier_from_file_name(in_file_name) + "_model";
242  }
243 
244  // TODO(martincerny) Check that the -namespace flag is not set
245 
246  if (cmd.has_key("o")) {
247  cmd.val("o", out_file_name);
248  } else {
249  out_file_name = model_name;
250  // TODO(carpenter): shouldn't this be .hpp without a main()?
251  out_file_name += ".cpp";
252  }
253 
254  check_identifier(model_name, "model_name");
255 
256  std::fstream out(out_file_name.c_str(), std::fstream::out);
257  if (out_stream) {
258  *out_stream << "Model name=" << model_name << std::endl;
259  *out_stream << "Input file=" << in_file_name << std::endl;
260  *out_stream << "Output file=" << out_file_name << std::endl;
261  }
262  if (!out.is_open()) {
263  std::stringstream msg;
264  msg << "Failed to open output file "
265  << out_file_name.c_str();
266  throw std::invalid_argument(msg.str());
267  }
268 
269  valid_input = stan::lang::compile(err_stream, in, out, model_name,
270  allow_undefined, in_file_name,
271  include_paths);
272  out.close();
273  break;
274  }
275  case kStandaloneFunctions: {
276  if (cmd.has_key("o")) {
277  cmd.val("o", out_file_name);
278  } else {
279  out_file_name = identifier_from_file_name(in_file_name);
280  out_file_name += ".hpp";
281  }
282 
283  // TODO(martincerny) Allow multiple namespaces
284  // (split namespace argument by "::")
285  std::vector<std::string> namespaces;
286  if (cmd.has_key("namespace")) {
287  std::string ns;
288  cmd.val("namespace", ns);
289  namespaces.push_back(ns);
290  } else {
291  namespaces.push_back(identifier_from_file_name(in_file_name)
292  + "_functions");
293  }
294 
295  // TODO(martincerny) Check that the -name flag is not set
296 
297  for (size_t namespace_i = 0;
298  namespace_i < namespaces.size(); ++namespace_i) {
299  check_identifier(namespaces[namespace_i], "namespace");
300  }
301 
302  std::fstream out(out_file_name.c_str(), std::fstream::out);
303  if (out_stream) {
304  *out_stream << "Parsing a fuctions-only file" << std::endl;
305 
306  *out_stream << "Target namespace= ";
307  for (size_t namespace_i = 0;
308  namespace_i < namespaces.size(); ++namespace_i) {
309  *out_stream << "::" << namespaces[namespace_i];
310  }
311  *out_stream << std::endl;
312 
313  *out_stream << "Input file=" << in_file_name << std::endl;
314  *out_stream << "Output file=" << out_file_name << std::endl;
315  }
316 
317  valid_input = stan::lang::compile_functions(err_stream, in, out,
318  namespaces, allow_undefined);
319 
320  out.close();
321  break;
322  }
323  default: {
324  assert(false);
325  }
326  }
327 
328  if (!valid_input) {
329  if (err_stream)
330  *err_stream << "PARSING FAILED." << std::endl;
331  // FIXME: how to remove triple cut-and-paste?
332  delete_file(out_stream, out_file_name);
333  return PARSE_FAIL_RC;
334  }
335  } catch (const std::invalid_argument& e) {
336  if (err_stream) {
337  *err_stream << std::endl
338  << e.what()
339  << std::endl;
340  delete_file(out_stream, out_file_name);
341  }
342  return INVALID_ARGUMENT_RC;
343  } catch (const std::exception& e) {
344  if (err_stream) {
345  *err_stream << std::endl
346  << e.what()
347  << std::endl;
348  }
349  delete_file(out_stream, out_file_name);
350  return EXCEPTION_RC;
351  }
352  return SUCCESS_RC;
353 }
bool compile(std::ostream *msgs, std::istream &in, std::ostream &out, const std::string &name, const bool allow_undefined=false, const std::string &filename="unknown file name", const std::vector< std::string > &include_paths=std::vector< std::string >())
Definition: compiler.hpp:35
std::string identifier_from_file_name(const std::string &in_file_name)
void check_identifier(const std::string &identifier, const std::string &identifier_type)
::xsd::cxx::tree::exception< char > exception
Definition: Database.h:225
void delete_file(std::ostream *err_stream, const std::string &file_name)
bool has_extension(const std::string &file_name, const std::string &extension)
void print_version(std::ostream *out_stream)
string cmd
Definition: run_hadd.py:52
bool compile_functions(std::ostream *msgs, std::istream &stan_funcs_in, std::ostream &cpp_out, const std::vector< std::string > &namespaces, const bool allow_undefined=false, const std::string &filename="unknown file name", const std::vector< std::string > &include_paths=std::vector< std::string >())
void invalid_argument(const char *function, const char *name, const T &y, const char *msg1, const char *msg2)
static const double ns
Module that plots metrics from reconstructed cosmic ray data.
ifstream in
Definition: comparison.C:7
void print_stanc_help(std::ostream *out_stream)
assert(nhit_max >=nhit_nbins)
Float_t e
Definition: plot.C:35
enum BeamMode string