Minsky
userFunction_units.cc
Go to the documentation of this file.
1 /*
2  @copyright Steve Keen 2020
3  @author Russell Standish
4  This file is part of Minsky.
5 
6  Minsky is free software: you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Minsky is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with Minsky. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef NO_EXPRTK
21 #include "minsky.h"
22 #include "expressionWalker.h"
23 #include "userFunction.h"
24 #include "minsky_epilogue.h"
25 using namespace std;
26 namespace minsky
27 {
28  namespace {
29  exprtk::parser<UnitsExpressionWalker> unitsParser;
30 
31  struct ExprTkCallableFunction: public exprtk::ivararg_function<UnitsExpressionWalker>
32  {
33  std::weak_ptr<CallableFunction> f;
34  ExprTkCallableFunction(const std::weak_ptr<CallableFunction>& f): f(f) {}
35  UnitsExpressionWalker operator()(const std::vector<UnitsExpressionWalker>&) {
36  // TODO (#1290) Actually call units checking on callable function
37  return {};
38  }
39  };
40  }
41 
43  bool UnitsExpressionWalker::check=true;
44  Units UserFunction::units(bool check) const
45  {
46  UnitsExpressionWalker::check=check;
47  vector<UnitsExpressionWalker> args(argNames.size());
48  if (!args.empty()) args[0].units=m_ports[1]->units(check);
49  if (args.size()>1) args[1].units=m_ports[2]->units(check);
50 
52 
53  vector<UnitsExpressionWalker> externalUnits;
54  exprtk::symbol_table<UnitsExpressionWalker> symbolTable, unknownVariables;
55  exprtk::expression<UnitsExpressionWalker> compiled;
56  compiled.register_symbol_table(unknownVariables);
57  compiled.register_symbol_table(symbolTable);
58  for (size_t i=0; i<args.size(); ++i)
59  {
60  args[i].check=check;
61  symbolTable.add_variable(argNames[i],args[i]);
62  }
63 
64  const std::vector<std::string> externalIds=symbolNames();
65  vector<ExprTkCallableFunction> externalFunctions;
66 
67  externalUnits.reserve(externalIds.size());
68  for (auto& i: externalIds)
69  {
70  if (find(argNames.begin(), argNames.end(), i)!=argNames.end()) continue; // skip arguments
71  auto id=valueIdFromScope(group.lock(),canonicalName(i));
72  auto v=minsky().variableValues.find(id);
73  if (v!=minsky().variableValues.end())
74  {
75  externalUnits.emplace_back();
76  externalUnits.back().units=v->second->units;
77  externalUnits.back().check=check;
78  unknownVariables.add_variable(i, externalUnits.back());
79  continue;
80  }
81  auto f=minsky().userFunctions.find(id);
82  if (f!=minsky().userFunctions.end())
83  {
84  externalFunctions.emplace_back(f->second);
85  unknownVariables.add_function(i,externalFunctions.back());
86  }
87  }
88  unknownVariables.add_variable("time",minsky::timeUnit);
89 
90  try
91  {
92  unitsParser.compile(expression, compiled);
93  return compiled.value().units;
94  }
95  catch (const std::exception& ex)
96  {
97  if (check)
98  throw_error(ex.what());
99  else
100  return {};
101  }
102  }
103 }
104 #endif
UnitsExpressionWalker operator()(const std::vector< UnitsExpressionWalker > &)
function f
Definition: canvas.m:1
VariableValues variableValues
Definition: minsky.h:200
minsky::Minsky minsky
Definition: pyminsky.cc:28
STL namespace.
Creation and access to the minskyTCL_obj object, which has code to record whenever Minsky&#39;s state cha...
Definition: constMap.h:22
represents the units (in sense of dimensional analysis) of a variable.
Definition: units.h:34
const Minsky & cminsky()
const version to help in const correctness
Definition: minsky.h:549
string canonicalName(const string &name)
convert a raw name into a canonical name - this is not idempotent.
Definition: valueId.cc:63
Exclude< std::map< std::string, std::shared_ptr< CallableFunction > > > userFunctions
Definition: minsky.h:253
string valueIdFromScope(const GroupPtr &scope, const std::string &name)
value Id from scope and canonical name name
Definition: valueId.cc:128
exprtk::parser< UnitsExpressionWalker > unitsParser
UnitsExpressionWalker timeUnit
Definition: group.tcl:84