Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
functions_grammar_def.hpp
Go to the documentation of this file.
1 #ifndef STAN__GM__PARSER__FUNCTIONS__GRAMMAR_DEF__HPP__
2 #define STAN__GM__PARSER__FUNCTIONS__GRAMMAR_DEF__HPP__
3 
4 #include <set>
5 #include <utility>
6 #include <vector>
7 
8 #include <boost/spirit/include/qi.hpp>
9 #include <boost/lexical_cast.hpp>
10 #include <boost/fusion/include/adapt_struct.hpp>
11 #include <boost/fusion/include/std_pair.hpp>
12 #include <boost/config/warning_disable.hpp>
13 #include <boost/spirit/include/qi_numeric.hpp>
14 #include <boost/spirit/include/phoenix_core.hpp>
15 #include <boost/spirit/include/phoenix_function.hpp>
16 #include <boost/spirit/include/phoenix_fusion.hpp>
17 #include <boost/spirit/include/phoenix_object.hpp>
18 #include <boost/spirit/include/phoenix_operator.hpp>
19 #include <boost/spirit/include/phoenix_stl.hpp>
20 #include <boost/spirit/include/support_multi_pass.hpp>
21 #include <boost/tuple/tuple.hpp>
22 #include <boost/variant/apply_visitor.hpp>
23 #include <boost/variant/recursive_variant.hpp>
24 
25 #include <boost/spirit/include/version.hpp>
26 #include <boost/spirit/include/support_line_pos_iterator.hpp>
27 
28 #include <stan/gm/ast.hpp>
32 
33 
35  (stan::gm::expr_type, return_type_)
36  (std::string, name_)
37  (std::vector<stan::gm::arg_decl>, arg_decls_)
38  (stan::gm::statement, body_) );
39 
41  (stan::gm::expr_type, arg_type_)
42  (std::string, name_)
43  (stan::gm::statement, body_) );
44 
45 namespace stan {
46 
47  namespace gm {
48 
50  template <typename T1, typename T2, typename T3>
51  struct result { typedef void type; };
52  void operator()(const expr_type& arg_type,
53  bool& pass,
54  std::ostream& error_msgs) const {
55  pass = !arg_type.is_void();
56  if (!pass)
57  error_msgs << "Functions cannot contain void argument types; "
58  << "found void argument."
59  << std::endl;
60  }
61  };
62  boost::phoenix::function<validate_non_void_arg_function> validate_non_void_arg_f;
63 
65  template <typename T1, typename T2, typename T3, typename T4>
66  struct result { typedef void type; };
68  var_origin& origin,
69  bool& pass,
70  std::ostream& error_msgs) const {
71  if (return_type.is_void() && return_type.num_dims() > 0) {
72  error_msgs << "Void return type may not have dimensions declared."
73  << std::endl;
74  pass = false;
75  return;
76  }
77  origin = return_type.is_void()
80  }
81  };
82  boost::phoenix::function<set_void_function> set_void_function_f;
83 
85  template <typename T1, typename T2, typename T3>
86  struct result { typedef void type; };
87  void operator()(const std::string& identifier,
88  bool& allow_sampling,
89  int& origin) const {
90  bool is_void_function_origin = (origin == void_function_argument_origin);
91  if (ends_with("_lp", identifier)) {
92  allow_sampling = true;
93  origin = is_void_function_origin
96  } else if (ends_with("_rng", identifier)) {
97  allow_sampling = false;
98  origin = is_void_function_origin
101  } else {
102  allow_sampling = false;
103  origin = is_void_function_origin
106  }
107  }
108  };
109  boost::phoenix::function<set_allows_sampling_origin> set_allows_sampling_origin_f;
110 
112  template <typename T1, typename T2, typename T3, typename T4>
113  struct result { typedef void type; };
114  void operator()(bool& pass,
115  std::set<std::pair<std::string,
116  function_signature_t> >& declared,
117  std::set<std::pair<std::string,
118  function_signature_t> >& defined,
119  std::ostream& error_msgs) const {
120  using std::set;
121  using std::string;
122  using std::pair;
123  typedef set<pair<string, function_signature_t> >::iterator iterator_t;
124  for (iterator_t it = declared.begin(); it != declared.end(); ++it) {
125  if (defined.find(*it) == defined.end()) {
126  error_msgs <<"Function declared, but not defined."
127  << " Function name=" << (*it).first
128  << std::endl;
129  pass = false;
130  return;
131  }
132  }
133  pass = true;
134  }
135  };
136  boost::phoenix::function<validate_declarations> validate_declarations_f;
137 
139  template <typename T1, typename T2, typename T3, typename T4, typename T5>
140  struct result { typedef void type; };
141  static bool fun_exists(const std::set<std::pair<std::string,
142  function_signature_t> >& existing,
143  const std::pair<std::string,function_signature_t>& name_sig) {
144  for (std::set<std::pair<std::string, function_signature_t> >::const_iterator it
145  = existing.begin();
146  it != existing.end();
147  ++it)
148  if (name_sig.first == (*it).first
149  && name_sig.second.second == (*it).second.second)
150  return true; // name and arg sequences match
151  return false;
152  }
153  void operator()(const function_decl_def& decl,
154  bool& pass,
155  std::set<std::pair<std::string,
156  function_signature_t> >& functions_declared,
157  std::set<std::pair<std::string,
158  function_signature_t> >& functions_defined,
159  std::ostream& error_msgs) const {
160 
161  // build up representations
162  expr_type result_type(decl.return_type_.base_type_,
163  decl.return_type_.num_dims_);
164  std::vector<expr_type> arg_types;
165  for (size_t i = 0; i < decl.arg_decls_.size(); ++i)
166  arg_types.push_back(expr_type(decl.arg_decls_[i].arg_type_.base_type_,
167  decl.arg_decls_[i].arg_type_.num_dims_));
168  function_signature_t sig(result_type, arg_types);
169  std::pair<std::string, function_signature_t> name_sig(decl.name_, sig);
170 
171  // check that not already declared if just declaration
172  if (decl.body_.is_no_op_statement()
173  && fun_exists(functions_declared,name_sig)) {
174  error_msgs << "Parse Error. Function already declared, name=" << decl.name_;
175  pass = false;
176  return;
177  }
178 
179  // check not already user defined
180  if (fun_exists(functions_defined, name_sig)) {
181  error_msgs << "Parse Error. Function already defined, name=" << decl.name_;
182  pass = false;
183  return;
184  }
185 
186  // check not already system defined
187  if (!fun_exists(functions_declared,name_sig)
189  error_msgs << "Parse Error. Function system defined, name=" << decl.name_;
190  pass = false;
191  return;
192  }
193 
194  // add declaration in local sets and in parser function sigs
195  if (functions_declared.find(name_sig) == functions_declared.end()) {
196  functions_declared.insert(name_sig);
198  .add(decl.name_,
199  result_type,arg_types);
201  .set_user_defined(name_sig);
202  }
203 
204  // add as definition if there's a body
205  if (!decl.body_.is_no_op_statement())
206  functions_defined.insert(name_sig);
207  pass = true;
208  }
209  };
210  boost::phoenix::function<add_function_signature> add_function_signature_f;
211 
213  template <typename T1, typename T2, typename T3>
214  struct result { typedef void type; };
216  bool& pass,
217  std::ostream& error_msgs) const {
218  pass = decl.body_.is_no_op_statement()
220  error_msgs);
221  if (!pass) {
222  error_msgs << "Improper return in body of function.";
223  return;
224  }
225 
226  if (ends_with("_log",decl.name_)
227  && !decl.return_type_.is_primitive_double()) {
228  pass = false;
229  error_msgs << "Require real return type for functions ending in _log.";
230  }
231  }
232  };
233  boost::phoenix::function<validate_return_type> validate_return_type_f;
234 
235  struct scope_lp {
236  template <typename T1>
237  struct result { typedef void type; };
238  void operator()(variable_map& vm) const {
239  vm.add("lp__", DOUBLE_T, local_origin);
240  }
241  };
242  boost::phoenix::function<scope_lp> scope_lp_f;
243 
244 
246  template <typename T1, typename T2>
247  struct result { typedef void type; };
249  variable_map& vm) const {
250  vm.remove("lp__");
251  for (size_t i = 0; i < decl.arg_decls_.size(); ++i)
252  vm.remove(decl.arg_decls_[i].name_);
253  }
254  };
255  boost::phoenix::function<unscope_variables> unscope_variables_f;
256 
257 
258  struct add_fun_var {
259  template <typename T1, typename T2, typename T3, typename T4>
260  struct result { typedef void type; };
261  // each type derived from base_var_decl gets own instance
262  void operator()(arg_decl& decl,
263  bool& pass,
264  variable_map& vm,
265  std::ostream& error_msgs) const {
266  if (vm.exists(decl.name_)) {
267  // variable already exists
268  pass = false;
269  error_msgs << "duplicate declaration of variable, name="
270  << decl.name_;
271 
272  error_msgs << "; attempt to redeclare as function argument";
273 
274  error_msgs << "; original declaration as ";
275  print_var_origin(error_msgs,vm.get_origin(decl.name_));
276 
277  error_msgs << std::endl;
278  return;
279  }
280 
281  pass = true;
282  vm.add(decl.name_,
285  }
286  };
287  boost::phoenix::function<add_fun_var> add_fun_var_f;
288 
289  template <typename Iterator>
291  std::stringstream& error_msgs)
292  : functions_grammar::base_type(functions_r),
293  var_map_(var_map),
294  functions_declared_(),
295  functions_defined_(),
296  error_msgs_(error_msgs),
297  statement_g(var_map_,error_msgs_),
298  bare_type_g(var_map_,error_msgs_)
299  {
300  using boost::spirit::qi::_1;
301  using boost::spirit::qi::char_;
302  using boost::spirit::qi::eps;
303  using boost::spirit::qi::lexeme;
304  using boost::spirit::qi::lit;
305  using boost::spirit::qi::no_skip;
306  using boost::spirit::qi::_pass;
307  using boost::spirit::qi::_val;
308 
309  using boost::spirit::qi::labels::_a;
310  using boost::spirit::qi::labels::_b;
311  using boost::spirit::qi::labels::_r1;
312  using boost::spirit::qi::labels::_r2;
313 
314  using boost::spirit::qi::on_error;
315  using boost::spirit::qi::fail;
316  using boost::spirit::qi::rethrow;
317  using namespace boost::spirit::qi::labels;
318 
319  functions_r.name("function declarations and definitions");
320  functions_r
321  %= lit("functions")
322  >> lit('{')
323  >> *function_r
324  >> lit('}')[ validate_declarations_f(_pass,
325  boost::phoenix::ref(functions_declared_),
326  boost::phoenix::ref(functions_defined_),
327  boost::phoenix::ref(error_msgs_) ) ]
328  ;
329  // locals: _a = allow sampling, _b = origin (function, rng/lp)
330  function_r.name("function declaration or definition");
331  function_r
332  %= bare_type_g[ set_void_function_f(_1,_b, _pass,
333  boost::phoenix::ref(error_msgs_)) ]
335  > lit('(')
336  > arg_decls_r
337  > lit(')')
338  > eps [ scope_lp_f(boost::phoenix::ref(var_map_)) ]
339  > statement_g(_a,_b,true)
340  > eps [ unscope_variables_f(_val,
341  boost::phoenix::ref(var_map_)) ]
342  > eps [ validate_return_type_f(_val,_pass,
343  boost::phoenix::ref(error_msgs_)) ]
344  > eps [ add_function_signature_f(_val,_pass,
345  boost::phoenix::ref(functions_declared_),
346  boost::phoenix::ref(functions_defined_),
347  boost::phoenix::ref(error_msgs_) ) ]
348  ;
349 
350  arg_decls_r.name("function argument declaration sequence");
352  %= arg_decl_r % ','
353  | eps
354  ;
355 
356  arg_decl_r.name("function argument declaration");
357  arg_decl_r
358  %= bare_type_g [ validate_non_void_arg_f(_1, _pass,
359  boost::phoenix::ref(error_msgs_)) ]
360  > identifier_r
361  > eps[ add_fun_var_f(_val,_pass,
362  boost::phoenix::ref(var_map_),
363  boost::phoenix::ref(error_msgs_)) ]
364  ;
365 
366  identifier_r.name("identifier");
368  %= lexeme[char_("a-zA-Z")
369  >> *char_("a-zA-Z0-9_.")];
370 
371  }
372 
373  }
374 }
375 #endif
376 
bare_type_grammar< Iterator > bare_type_g
bool is_no_op_statement() const
Definition: ast_def.cpp:1286
bool ends_with(const std::string &suffix, const std::string &s)
Definition: ast_def.cpp:1477
boost::spirit::qi::rule< Iterator, std::vector< arg_decl >), whitespace_grammar< Iterator > > arg_decls_r
void add(const std::string &name, const expr_type &result_type, const std::vector< expr_type > &arg_types)
Definition: ast_def.cpp:171
base_expr_type base_type_
Definition: ast.hpp:75
void add(const std::string &name, const base_var_decl &base_decl, const var_origin &vo)
Definition: ast_def.cpp:1007
bool is_defined(const std::string &name, const function_signature_t &sig)
Definition: ast_def.cpp:163
const int DOUBLE_T
Definition: ast.hpp:66
std::string name_
Definition: ast.hpp:769
static function_signatures & instance()
Definition: ast_def.cpp:143
const int local_origin
Definition: ast.hpp:418
void set_user_defined(const std::pair< std::string, function_signature_t > &name_sig)
Definition: ast_def.cpp:150
boost::phoenix::function< validate_declarations > validate_declarations_f
bool is_primitive_double() const
Definition: ast_def.cpp:101
void operator()(function_decl_def &decl, variable_map &vm) const
void print_var_origin(std::ostream &o, const var_origin &vo)
Definition: ast_def.cpp:944
const int function_argument_origin
Definition: ast.hpp:419
static bool fun_exists(const std::set< std::pair< std::string, function_signature_t > > &existing, const std::pair< std::string, function_signature_t > &name_sig)
void operator()(bool &pass, std::set< std::pair< std::string, function_signature_t > > &declared, std::set< std::pair< std::string, function_signature_t > > &defined, std::ostream &error_msgs) const
Metaprogram to calculate the base scalar return type resulting from promoting all the scalar types of...
Definition: traits.hpp:398
const int void_function_argument_origin_rng
Definition: ast.hpp:424
const int function_argument_origin_rng
Definition: ast.hpp:421
boost::phoenix::function< set_void_function > set_void_function_f
boost::phoenix::function< add_fun_var > add_fun_var_f
boost::phoenix::function< unscope_variables > unscope_variables_f
size_t num_dims_
Definition: ast.hpp:76
boost::spirit::qi::rule< Iterator, arg_decl(), whitespace_grammar< Iterator > > arg_decl_r
void operator()(variable_map &vm) const
boost::phoenix::function< set_allows_sampling_origin > set_allows_sampling_origin_f
void operator()(const function_decl_def &decl, bool &pass, std::set< std::pair< std::string, function_signature_t > > &functions_declared, std::set< std::pair< std::string, function_signature_t > > &functions_defined, std::ostream &error_msgs) const
const int void_function_argument_origin_lp
Definition: ast.hpp:423
boost::phoenix::function< validate_return_type > validate_return_type_f
size_t num_dims() const
Definition: ast_def.cpp:114
boost::spirit::qi::rule< Iterator, boost::spirit::qi::locals< bool, int >, function_decl_def(), whitespace_grammar< Iterator > > function_r
BOOST_FUSION_ADAPT_STRUCT(stan::gm::function_decl_def,(stan::gm::expr_type, return_type_)(std::string, name_)(std::vector< stan::gm::arg_decl >, arg_decls_)(stan::gm::statement, body_))
void operator()(const expr_type &return_type, var_origin &origin, bool &pass, std::ostream &error_msgs) const
std::vector< arg_decl > arg_decls_
Definition: ast.hpp:784
functions_grammar(variable_map &var_map, std::stringstream &error_msgs)
statement_grammar< Iterator > statement_g
const int void_function_argument_origin
Definition: ast.hpp:422
std::set< std::pair< std::string, function_signature_t > > functions_declared_
boost::spirit::qi::rule< Iterator, std::vector< function_decl_def >), whitespace_grammar< Iterator > > functions_r
void operator()(arg_decl &decl, bool &pass, variable_map &vm, std::ostream &error_msgs) const
boost::spirit::qi::rule< Iterator, std::string(), whitespace_grammar< Iterator > > identifier_r
boost::phoenix::function< add_function_signature > add_function_signature_f
std::set< std::pair< std::string, function_signature_t > > functions_defined_
void remove(const std::string &name)
Definition: ast_def.cpp:1012
base_var_decl base_variable_declaration()
Definition: ast_def.cpp:403
const int function_argument_origin_lp
Definition: ast.hpp:420
boost::phoenix::function< scope_lp > scope_lp_f
std::stringstream & error_msgs_
void operator()(const expr_type &arg_type, bool &pass, std::ostream &error_msgs) const
bool exists(const std::string &name) const
Definition: ast_def.cpp:988
void operator()(const std::string &identifier, bool &allow_sampling, int &origin) const
void operator()(function_decl_def &decl, bool &pass, std::ostream &error_msgs) const
boost::phoenix::function< validate_non_void_arg_function > validate_non_void_arg_f
bool returns_type(const expr_type &return_type, const statement &statement, std::ostream &error_msgs)
Definition: ast_def.cpp:515
int var_origin
Definition: ast.hpp:411
var_origin get_origin(const std::string &name) const
Definition: ast_def.cpp:1002
bool is_void() const
Definition: ast_def.cpp:108
std::pair< expr_type, std::vector< expr_type > > function_signature_t
Definition: ast.hpp:104

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