/* * representation of l-systems and their evaluation * * the order of definitions here is the most crucial I've ever encountered * => maybe this indicates design problem? */ #ifndef lsys_h #define lsys_h #include #include #include #include #include #include #include #include #include "util.h" //#include #if 0 template<> struct hash { size_t operator()(const string &s) const t_no { size_t h = 0; for(string::const_iterator i = s.begin (); i != s.end (); ++i) h = h*5 + *i; return h; } }; #endif #define hash_map map struct file_pos { string path; int line; int col; file_pos (const string &p = string (), int l = -1, int c = -1) t_no : path(p), line(l), col(c) {}; }; template struct auto_vec : shared_vector { const T &first () const t_no { return shared< vector >::obj->front (); }; const T &second() const t_no { return shared< vector >::obj->operator[](1); }; const T &third () const t_no { return shared< vector >::obj->operator[](2); }; const T &fourth() const t_no { return shared< vector >::obj->operator[](3); }; }; typedef auto_vec module_vec; struct module : module_vec { double num; string str; int is_expr:1; int is_num:1; file_pos where; module() t_no : is_expr(0), is_num(0) { }; module(double d) t_no : num(d), is_expr(0), is_num(1) { char s[79]; sprintf (s, "%g", d); str = s; }; module(const string &n) t_no : str(n), is_expr(0), is_num(0) { }; module(const string &n, const module &arg1) t_no : str(n), is_expr(0), is_num(0) { push_back (arg1); }; module(const string &n, const module &arg1, const module &arg2) t_no : str(n), is_expr(0), is_num(0) { push_back (arg1); push_back (arg2); }; module_vec wrap () const t_no { module_vec w; w.push_back (*this); return w; }; void erase () t_no { str = ""; num = 0; is_expr = is_num = 0; module_vec::erase (); }; bool is_func (const string &func) const t_no; bool is_func (const string &func, double &arg1) const t_no; bool is_func (const string &func, string &arg1, double &arg2) const t_no; bool is_func (const string &func, string &arg1, string &arg2) const t_no; bool is_func (const string &func, string &arg1, module &arg2) const t_no; operator double() const t_err; operator const string &() const t_no { return str; }; operator string () t_no { return str; }; bool match (const module &m) const { return m.str == str && m.size () == size (); }; friend bool operator <(const module &a, const module &b) t_no; }; bool operator <(const module &a, const module &b) t_no; typedef map module_map; typedef map module_ref_map; typedef module_vec::const_iterator module_pos; struct rule : public module { module_vec pre; module_vec post; module constraint; module_vec repl; module iterations; }; typedef hash_map > rule_map; struct lsys : public module { lsys *parent; hash_map sub_lsys; // "local" lsystems set ignore_module; rule_map rules; module_map defines; struct arg_spec { string str; int nargs; int arg; }; set arg_is_numeric; lsys () t_no; ~lsys () t_no; bool match_rule (const rule &r, const module_vec &v, module_pos i, module_map &vars) const t_err; private:void mark_numeric (const map &which, const module &v) t_no; public: void add_rule (rule r) t_err; void add_lsys (lsys *l) t_err; module expand (const module_map &c, const module &v) const t_err; bool eval (module_vec &v) const t_err; // true, if changed module_vec operator ()(const module_vec &v) const t_no { module_vec res (v); eval (res); return res; }; public: double eval_numeric (const module &expr, module_map context) const t_err; }; bool operator <(const lsys::arg_spec &a, const lsys::arg_spec &b) t_no; double eval_expr (const module &expr, const module_map &locals = module_map (), const module_map &globals = module_map ()) t_err; // otherwise needed a forward reference; inline module::operator double() const t_err { return eval_expr (*this); } ostream &operator <<(ostream &o, const file_pos &p) t_no; ostream &operator <<(ostream &o, const module_vec &v) t_no; ostream &operator <<(ostream &o, const module &m) t_no; ostream &operator <<(ostream &o, const rule &r) t_no; ostream &operator <<(ostream &o, const lsys &l) t_no; #endif