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 
32 #include <boost/mpl/begin.hpp>
33 #include <boost/mpl/end.hpp>
34 #include <boost/mpl/next.hpp>
35 #include <boost/mpl/deref.hpp>
36 
37 namespace fusion = boost::fusion;
38 namespace mpl = boost::mpl;
39 namespace bft = boost::function_types;
40 
41 namespace schnek {
42 
43 typedef std::list<ExpressionVariant> ExpressionList;
44 
45 template<typename vtype>
46 struct ExpressionConverterVisitor : public boost::static_visitor<ExpressionVariant>
47 {
48  typedef typename std::shared_ptr<Expression<vtype> > VarExpressionPointer;
49  ExpressionVariant operator()(VarExpressionPointer e)
50  {
51  return e;
52  }
53 
54  template<class ExpressionPointer>
55  ExpressionVariant operator()(ExpressionPointer e)
56  {
57  typedef typename ExpressionPointer::element_type::ValueType vtype_orig;
58  VarExpressionPointer vEP(new TypecastOp<vtype, vtype_orig, FastCast>(e));
59  return vEP;
60  }
61 };
62 
63 template<class vtype, typename func>
64 class FunctionExpression : public Expression<vtype>
65 {
66  public:
67  typedef typename bft::result_type<func>::type rtype;
68 
69 // template<
70 // typename from = typename mpl::begin< bft::parameter_types<func> >::type,
71 // typename to = typename mpl::end< bft::parameter_types<func> >::type
72 // >
73 // struct converter;
74 
75  private:
76  struct isConstantVisitor : public boost::static_visitor<bool>
77  {
78  template<class ExpressionPointer>
79  bool operator()(ExpressionPointer e) { return e->isConstant(); }
80  };
81 
82 
83  ExpressionList args;
84  func f;
85  bool updateAlways;
86  public:
87  FunctionExpression(func f_, ExpressionList &args_, bool updateAlways);
88 
90  vtype eval();
91 
92  bool isConstant();
93 
94  DependencyList getDependencies();
95 };
96 
97 template<
98  class vtype,
99  typename func,
100  typename from = typename mpl::begin< bft::parameter_types<func> >::type,
101  typename to = typename mpl::end< bft::parameter_types<func> >::type
102 >
104 
105 template<class vtype, typename func, typename to>
106 struct FunctionExpressionConverter<vtype, func, to, to>
107 {
108  typedef typename bft::result_type<func>::type rtype;
109  static void makeList(ExpressionList::iterator var, ExpressionList::iterator end, ExpressionList &)
110  {
111  if (var != end) throw WrongNumberOfArgsException();
112  }
113 
114  template<typename ArgType>
115  static rtype evaluate(func f, ExpressionList::iterator, ArgType const &sArgs)
116  {
117  return fusion::invoke(f, sArgs);
118  }
119 };
120 
121 template<class vtype, typename func, typename from, typename to>
123 {
124  typedef typename bft::result_type<func>::type rtype;
125  typedef typename mpl::deref<from>::type arg_type;
126  typedef typename mpl::next<from>::type next_type_iter;
127 
128  static void makeList(ExpressionList::iterator var, ExpressionList::iterator end, ExpressionList &args)
129  {
130  if (var == end) throw WrongNumberOfArgsException();
131 
133  args.push_back(boost::apply_visitor(visit, (*var)));
134  ++var;
136  Con::makeList(var, end, args);
137  // FunctionExpressionConverter<vtype, func, next_type_iter, to>::makeList(var, end, args);
138  }
139 
140  template<typename ArgType>
141  static rtype evaluate(func f, ExpressionList::iterator var, ArgType const &sArgs)
142  {
143  typedef std::shared_ptr< Expression<arg_type> > pExprType;
144  pExprType expr = boost::get<pExprType>(*var);
145  ++var;
146  return FunctionExpressionConverter<vtype, func, next_type_iter, to>::evaluate(f, var, fusion::push_back(sArgs, expr->eval()));
147  }
148 
149 };
150 
151 template<class vtype, typename func>
152 FunctionExpression<vtype, func>::FunctionExpression(func f_, ExpressionList &args_, bool updateAlways_)
153  : f(f_), updateAlways(updateAlways_)
154 {
155  FunctionExpressionConverter<vtype, func>::makeList(args_.begin(), args_.end(), args);
156 }
157 
158 template<class vtype, typename func>
160 {
161  return FunctionExpressionConverter<vtype, func>::evaluate(f, args.begin(), fusion::nil());
162 }
163 
164 template<class vtype, typename func>
166 {
167  if (updateAlways) return false;
168  bool result = true;
169  isConstantVisitor visit;
170  for (ExpressionVariant ex: args)
171  {
172  result = result && boost::apply_visitor(visit, ex);
173  }
174 
175  return result;
176 }
177 
178 template<class vtype, typename func>
180 {
181  DependencyList result;
182 
183  DependenciesGetter visit;
184  for (ExpressionVariant ex: args)
185  {
186  DependencyList dep = boost::apply_visitor(visit, ex);
187  result.insert(dep.begin(), dep.end());
188  }
189  if (updateAlways) result.insert(-1);
190  return result;
191 }
192 
194 {
195  private:
196 
197  class EntryBase
198  {
199  public:
200  virtual ~EntryBase() {}
201  virtual ExpressionVariant getExpression(ExpressionList &) = 0;
202  };
203 
204  typedef std::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  std::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  std::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:46
Definition: expression.hpp:73
Definition: function_expression.hpp:103
Definition: function_expression.hpp:64
Definition: algo.hpp:30
Definition: function_expression.hpp:193
Definition: expression.hpp:404
Definition: expression.hpp:96
Definition: expression.hpp:67
vtype eval()
Return the modified value.
Definition: function_expression.hpp:159
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:165
Definition: expression.hpp:436