Stan  2.14.0
probability, sampling & optimization
stanc_helper.hpp
Go to the documentation of this file.
1 #ifndef STAN_COMMAND_STANC_HELPER_HPP
2 #define STAN_COMMAND_STANC_HELPER_HPP
3 
4 #include <stan/version.hpp>
5 #include <stan/lang/compiler.hpp>
6 #include <stan/io/cmd_line.hpp>
7 #include <exception>
8 #include <fstream>
9 #include <iostream>
10 #include <stdexcept>
11 #include <string>
12 
18 void print_version(std::ostream* out_stream) {
19  if (!out_stream) return;
20  *out_stream << "stanc version "
22  << "."
24  << "."
26  << std::endl;
27 }
28 
34 void print_stanc_help(std::ostream* out_stream) {
36 
37  if (!out_stream) return;
38 
39  *out_stream << std::endl;
40  print_version(out_stream);
41  *out_stream << std::endl;
42 
43  *out_stream << "USAGE: " << "stanc [options] <model_file>" << std::endl;
44  *out_stream << std::endl;
45 
46  *out_stream << "OPTIONS:" << std::endl;
47  *out_stream << std::endl;
48 
49  print_help_option(out_stream, "help", "", "Display this information");
50 
51  print_help_option(out_stream, "version", "", "Display stanc version number");
52 
53  print_help_option(out_stream, "name", "string",
54  "Model name",
55  "default = \"$model_filename_model\"");
56 
57  print_help_option(out_stream, "o", "file",
58  "Output file for generated C++ code",
59  "default = \"$name.cpp\"");
60 
61  print_help_option(out_stream, "allow_undefined", "",
62  "Do not fail if a function is declared but not defined");
63 }
64 
74 void delete_file(std::ostream* err_stream,
75  const std::string& file_name) {
76  if (file_name.size() == 0)
77  return;
78  int return_code = std::remove(file_name.c_str());
79  if (return_code != 0)
80  if (err_stream)
81  *err_stream << "Could not remove output file=" << file_name
82  << std::endl;
83 }
84 
100 int stanc_helper(int argc, const char* argv[],
101  std::ostream* out_stream, std::ostream* err_stream) {
102  static const int SUCCESS_RC = 0;
103  static const int EXCEPTION_RC = -1;
104  static const int PARSE_FAIL_RC = -2;
105  static const int INVALID_ARGUMENT_RC = -3;
106 
107  std::string out_file_name; // declare outside of try to delete in catch
108 
109  try {
110  stan::io::cmd_line cmd(argc, argv);
111 
112  if (cmd.has_flag("help")) {
113  print_stanc_help(out_stream);
114  return SUCCESS_RC;
115  }
116 
117  if (cmd.has_flag("version")) {
118  print_version(out_stream);
119  return SUCCESS_RC;
120  }
121 
122  if (cmd.bare_size() != 1) {
123  std::string msg("Require model file as argument. ");
124  throw std::invalid_argument(msg);
125  }
126  std::string in_file_name;
127  cmd.bare(0, in_file_name);
128  std::ifstream in(in_file_name.c_str());
129 
130  std::string model_name;
131  if (cmd.has_key("name")) {
132  cmd.val("name", model_name);
133  } else {
134  size_t slashInd = in_file_name.rfind('/');
135  size_t ptInd = in_file_name.rfind('.');
136  if (ptInd == std::string::npos)
137  ptInd = in_file_name.length();
138  if (slashInd == std::string::npos) {
139  slashInd = in_file_name.rfind('\\');
140  }
141  if (slashInd == std::string::npos) {
142  slashInd = 0;
143  } else {
144  slashInd++;
145  }
146  model_name = in_file_name.substr(slashInd, ptInd - slashInd) + "_model";
147  for (std::string::iterator strIt = model_name.begin();
148  strIt != model_name.end(); strIt++) {
149  if (!isalnum(*strIt) && *strIt != '_') {
150  *strIt = '_';
151  }
152  }
153  }
154 
155  if (cmd.has_key("o")) {
156  cmd.val("o", out_file_name);
157  } else {
158  out_file_name = model_name;
159  // TODO(carpenter): shouldn't this be .hpp without a main()?
160  out_file_name += ".cpp";
161  }
162 
163  if (!isalpha(model_name[0]) && model_name[0] != '_') {
164  std::string msg("model_name must not start with a "
165  "number or symbol other than _");
166  throw std::invalid_argument(msg);
167  }
168  for (std::string::iterator strIt = model_name.begin();
169  strIt != model_name.end(); strIt++) {
170  if (!isalnum(*strIt) && *strIt != '_') {
171  std::string msg("model_name must contain only letters, numbers and _");
172  throw std::invalid_argument(msg);
173  }
174  }
175 
176  bool allow_undefined = cmd.has_flag("allow_undefined");
177 
178  std::fstream out(out_file_name.c_str(), std::fstream::out);
179  if (out_stream) {
180  *out_stream << "Model name=" << model_name << std::endl;
181  *out_stream << "Input file=" << in_file_name << std::endl;
182  *out_stream << "Output file=" << out_file_name << std::endl;
183  }
184 
185  bool valid_model
186  = stan::lang::compile(err_stream, in, out, model_name, allow_undefined);
187 
188  out.close();
189  if (!valid_model) {
190  if (err_stream)
191  *err_stream << "PARSING FAILED." << std::endl;
192  // FIXME: how to remove triple cut-and-paste?
193  delete_file(out_stream, out_file_name);
194  return PARSE_FAIL_RC;
195  }
196  } catch (const std::invalid_argument& e) {
197  if (err_stream) {
198  *err_stream << std::endl
199  << e.what()
200  << std::endl;
201  delete_file(out_stream, out_file_name);
202  }
203  return INVALID_ARGUMENT_RC;
204  } catch (const std::exception& e) {
205  if (err_stream) {
206  *err_stream << std::endl
207  << e.what()
208  << std::endl;
209  }
210  delete_file(out_stream, out_file_name);
211  return EXCEPTION_RC;
212  }
213  return SUCCESS_RC;
214 }
215 
216 #endif
bool compile(std::ostream *msgs, std::istream &stan_lang_in, std::ostream &cpp_out, const std::string &model_name, const bool allow_undefined=false)
Read a Stan model specification from the specified input, parse it, and write the C++ code for it to ...
Definition: compiler.hpp:29
void delete_file(std::ostream *err_stream, const std::string &file_name)
Delte the file at the specified path, writing messages to error stream if not possible.
Parses and stores command-line arguments.
Definition: cmd_line.hpp:113
void print_version(std::ostream *out_stream)
Print the version of stanc with major, minor and patch.
bool has_flag(const std::string &flag) const
Return true if the specified flag is defined.
Definition: cmd_line.hpp:204
bool bare(size_t n, T &x) const
Returns the bare argument.
Definition: cmd_line.hpp:231
int stanc_helper(int argc, const char *argv[], std::ostream *out_stream, std::ostream *err_stream)
Invoke the stanc command on the specified argument list, writing output and error messages to the spe...
const std::string MINOR_VERSION
Minor version number for Stan package.
Definition: version.hpp:24
bool has_key(const std::string &key) const
Return true if the specified key is defined.
Definition: cmd_line.hpp:166
bool val(const std::string &key, T &x) const
Returns the value for the key provided.
Definition: cmd_line.hpp:190
const std::string PATCH_VERSION
Patch version for Stan package.
Definition: version.hpp:27
void print_stanc_help(std::ostream *out_stream)
Prints the Stan compiler (stanc) help.
void print_help_option(std::ostream *o, const std::string &key, const std::string &value_type, const std::string &msg, const std::string &note="")
Prints single print option to output ptr if non-null.
Definition: cmd_line.hpp:74
size_t bare_size() const
Return the number of bare arguments.
Definition: cmd_line.hpp:213
const std::string MAJOR_VERSION
Major version number for Stan package.
Definition: version.hpp:21

     [ Stan Home Page ] © 2011–2016, Stan Development Team.