Schnek
function_expression.hpp
1 /*
2  * function_expression.hpp
3  *
4  * Created on: 22 Mar 2012
5  * Author: Holger Schmitz
6  * Email: holger@notjustphysics.com
7  *
8  * Copyright 2012 Holger Schmitz
9  *
10  * This file is part of Schnek.
11  *
12  * Schnek is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * Schnek is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with Schnek. If not, see <http://www.gnu.org/licenses/>.
24  *
25  */
26 
27 #ifndef FUNCTION_EXPRESSION_HPP_
28 #define FUNCTION_EXPRESSION_HPP_
29 
30 #include "expression.hpp"
31 #include <boost/foreach.hpp>
32 
33 #include <boost/mpl/begin.hpp>
34 #include <boost/mpl/end.hpp>
35 #include <boost/mpl/next.hpp>
36 #include <boost/mpl/deref.hpp>
37 
38 namespace fusion = boost::fusion;
39 namespace mpl = boost::mpl;
40 namespace bft = boost::function_types;
41 
42 namespace schnek {
43 
44 typedef std::list<ExpressionVariant> ExpressionList;
45 
46 template<typename vtype>
47 struct ExpressionConverterVisitor : public boost::static_visitor<ExpressionVariant>
48 {
49  typedef typename boost::shared_ptr<Expression<vtype> > VarExpressionPointer;
50  ExpressionVariant operator()(VarExpressionPointer e)
51  {
52  return e;
53  }
54 
55  template<class ExpressionPointer>
56  ExpressionVariant operator()(ExpressionPointer e)
57  {
58  typedef typename ExpressionPointer::element_type::ValueType vtype_orig;
59  VarExpressionPointer vEP(new TypecastOp<vtype, vtype_orig, FastCast>(e));
60  return vEP;
61  }
62 };
63 
64 template<class vtype, typename func>
65 class FunctionExpression : public Expression<vtype>
66 {
67  public:
68  typedef typename bft::result_type<func>::type rtype;
69 
70 // template<
71 // typename from = typename mpl::begin< bft::parameter_types<func> >::type,
72 // typename to = typename mpl::end< bft::parameter_types<func> >::type
73 // >
74 // struct converter;
75 
76  private:
77  struct isConstantVisitor : public boost::static_visitor<bool>
78  {
79  template<class ExpressionPointer>
80  bool operator()(ExpressionPointer e) { return e->isConstant(); }
81  };
82 
83 
84  ExpressionList args;
85  func f;
86  bool updateAlways;
87  public:
88  FunctionExpression(func f_, ExpressionList &args_, bool updateAlways);
89 
91  vtype eval();
92 
93  bool isConstant();
94 
95  DependencyList getDependencies();
96 };
97 
98 template<
99  class vtype,
100  typename func,
101  typename from = typename mpl::begin< bft::parameter_types<func> >::type,
102  typename to = typename mpl::end< bft::parameter_types<func> >::type
103 >
105 
106 template<class vtype, typename func, typename to>
107 struct FunctionExpressionConverter<vtype, func, to, to>
108 {
109  typedef typename bft::result_type<func>::type rtype;
110  static void makeList(ExpressionList::iterator var, ExpressionList::iterator end, ExpressionList &args)
111  {
112  if (var != end) throw WrongNumberOfArgsException();
113  }
114 
115  template<typename ArgType>
116  static rtype evaluate(func f, ExpressionList::iterator var, ArgType const &sArgs)
117  {
118  return fusion::invoke(f, sArgs);
119  }
120 };
121 
122 template<class vtype, typename func, typename from, typename to>
124 {
125  typedef typename bft::result_type<func>::type rtype;
126  typedef typename mpl::deref<from>::type arg_type;
127  typedef typename mpl::next<from>::type next_type_iter;
128 
129  static void makeList(ExpressionList::iterator var, ExpressionList::iterator end, ExpressionList &args)
130  {
131  if (var == end) throw WrongNumberOfArgsException();
132 
134  args.push_back(boost::apply_visitor(visit, (*var)));
135  ++var;
137  Con::makeList(var, end, args);
138  // FunctionExpressionConverter<vtype, func, next_type_iter, to>::makeList(var, end, args);
139  }
140 
141  template<typename ArgType>
142  static rtype evaluate(func f, ExpressionList::iterator var, ArgType const &sArgs)
143  {
144  typedef boost::shared_ptr< Expression<arg_type> > pExprType;
145  pExprType expr = boost::get<pExprType>(*var);
146  ++var;
147  return FunctionExpressionConverter<vtype, func, next_type_iter, to>::evaluate(f, var, fusion::push_back(sArgs, expr->eval()));
148  }
149 
150 };
151 
152 template<class vtype, typename func>
153 FunctionExpression<vtype, func>::FunctionExpression(func f_, ExpressionList &args_, bool updateAlways_)
154  : f(f_), updateAlways(updateAlways_)
155 {
156  FunctionExpressionConverter<vtype, func>::makeList(args_.begin(), args_.end(), args);
157 }
158 
159 template<class vtype, typename func>
161 {
162  return FunctionExpressionConverter<vtype, func>::evaluate(f, args.begin(), fusion::nil());
163 }
164 
165 template<class vtype, typename func>
167 {
168  if (updateAlways) return false;
169  bool result = true;
170  isConstantVisitor visit;
171  BOOST_FOREACH(ExpressionVariant ex, args)
172  {
173  result = result && boost::apply_visitor(visit, ex);
174  }
175 
176  return result;
177 }
178 
179 template<class vtype, typename func>
181 {
182  DependencyList result;
183 
184  DependenciesGetter visit;
185  BOOST_FOREACH(ExpressionVariant ex, args)
186  {
187  DependencyList dep = boost::apply_visitor(visit, ex);
188  result.insert(dep.begin(), dep.end());
189  }
190  if (updateAlways) result.insert(-1);
191  return result;
192 }
193 
195 {
196  private:
197 
198  class EntryBase
199  {
200  public:
201  virtual ExpressionVariant getExpression(ExpressionList &) = 0;
202  };
203 
204  typedef boost::shared_ptr<EntryBase> pEntryBase;
205 
206  template<typename func>
207  class Entry : public EntryBase
208  {
209  private:
210  typedef typename bft::result_type<func>::type rtype;
211  typedef FunctionExpression<rtype, func> FExprType;
212 
213  func f;
214  bool updateAlways;
215  public:
216  Entry(func f_, bool updateAlways_) : f(f_), updateAlways(updateAlways_) {}
217 
218  ExpressionVariant getExpression(ExpressionList &args)
219  {
220  boost::shared_ptr<Expression<rtype> > eP(new FunctionExpression<rtype, func>(f, args, updateAlways));
221  return eP;
222  }
223  };
224 
225 
226  typedef std::map<std::string, pEntryBase> FExprMap;
227  boost::shared_ptr<FExprMap> funcs;
228 
229  public:
230  FunctionRegistry() : funcs(new FExprMap) {}
231  FunctionRegistry(const FunctionRegistry &reg) : funcs(reg.funcs) {}
232 
233  template<typename func>
234  void registerFunction(std::string fname, func f, bool updateAlways = false)
235  {
236  pEntryBase eB(new Entry<func>(f, updateAlways));
237  (*funcs)[fname] = eB;
238  }
239 
240  ExpressionVariant getExpression(std::string fname, ExpressionList &args)
241  {
242  if (funcs->count(fname) == 0) throw FunctionNotFoundException(fname);
243  return (*funcs)[fname]->getExpression(args);
244  }
245 
246 };
247 
255 void registerCMath(FunctionRegistry &freg);
256 
262 void registerUtilityFunctions(FunctionRegistry &freg);
263 
269 void registerSpecialFunctions(FunctionRegistry &freg);
270 void registerAllFunctions(FunctionRegistry &freg);
271 
272 } // namespace schnek
273 
274 #endif // FUNCTION_EXPRESSION_HPP_
Definition: function_expression.hpp:47
Definition: expression.hpp:68
Definition: function_expression.hpp:104
Definition: function_expression.hpp:65
Definition: algo.hpp:30
Definition: function_expression.hpp:194
Definition: expression.hpp:399
Definition: expression.hpp:91
Definition: expression.hpp:62
vtype eval()
Return the modified value.
Definition: function_expression.hpp:160
virtual bool isConstant()=0
Returns whether the expression can be evaluated, are all the references also constant.
bool isConstant()
Returns whether the expression can be evaluated, are all the references also constant.
Definition: function_expression.hpp:166
Definition: expression.hpp:431