KSeExpr  4.0.4.0
ExprMultiExpr.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2011-2019 Disney Enterprises, Inc.
2 // SPDX-License-Identifier: LicenseRef-Apache-2.0
3 // SPDX-FileCopyrightText: 2020 L. E. Segovia <amy@amyspark.me>
4 // SPDX-License-Identifier: GPL-3.0-or-later
5 
6 #include <algorithm>
7 #include <set>
8 
9 #include "ExprMultiExpr.h"
10 
11 namespace KSeExpr
12 {
13 class GlobalVal : public ExprVarRef
14 {
15 public:
16  GlobalVal(const std::string &varName, const KSeExpr::ExprType &et)
17  : ExprVarRef(et)
18  , varName(varName)
19  {
20  }
21  std::set<DExpression *> users;
22  std::string varName;
23 };
24 
25 struct GlobalFP : public GlobalVal {
26  GlobalFP(const std::string &varName, int dim)
27  : GlobalVal(varName, ExprType().FP(dim).Varying())
28  {
29  val.assign(dim, 0);
30  }
31 
32  std::vector<double> val;
33  void eval(double *result) override
34  {
35  for (int i = 0; i < type().dim(); i++)
36  result[i] = val[i];
37  }
38  void eval(const char **) override
39  {
40  assert(false);
41  }
42  bool isVec()
43  {
44  return type().dim() > 1;
45  }
46 };
47 
48 struct GlobalStr : public GlobalVal {
49  GlobalStr(const std::string &varName)
50  : GlobalVal(varName, ExprType().String().Varying())
51  {
52  }
53 
54  const char *val{nullptr};
55  void eval(double *) override
56  {
57  assert(false);
58  }
59  void eval(const char **result) override
60  {
61  *result = val;
62  }
63  bool isVec()
64  {
65  return false;
66  }
67 };
68 } // namespace KSeExpr
69 
70 namespace
71 {
72 std::set<KSeExpr::DExpression *> getAffectedExpr(KSeExpr::GlobalVal *gv)
73 {
74  std::set<KSeExpr::DExpression *> ret;
75 
76  std::set<KSeExpr::DExpression *> workList = gv->users;
77  while (!workList.empty()) {
78  KSeExpr::DExpression *de = *workList.begin();
79  workList.erase(de);
80  ret.insert(de);
81  workList.insert(de->val->users.begin(), de->val->users.end());
82  }
83 
84  return ret;
85 }
86 
87 std::set<KSeExpr::DExpression *> getTransitiveOperandExpr(KSeExpr::DExpression *expr)
88 {
89  std::set<KSeExpr::DExpression *> ret;
90 
91  std::set<KSeExpr::DExpression *> workList;
92  workList.insert(expr);
93  while (!workList.empty()) {
94  KSeExpr::DExpression *de = *workList.begin();
95  workList.erase(de);
96  ret.insert(de);
97  workList.insert(de->operandExprs.begin(), de->operandExprs.end());
98  }
99 
100  return ret;
101 }
102 
103 std::set<KSeExpr::DExpression *> tmpOperandExprs;
104 std::set<KSeExpr::GlobalVal *> tmpOperandVars;
105 } // namespace
106 
107 namespace KSeExpr
108 {
109 DExpression::DExpression(const std::string &varName, Expressions &context, const std::string &e, const ExprType &type, EvaluationStrategy be)
110  : Expression(e, type, be)
111  , dContext(context)
112 {
113  if (type.isFP())
114  val = new GlobalFP(varName, type.dim());
115  else if (type.isString())
116  val = new GlobalStr(varName);
117  else
118  assert(false);
119 
122  prepIfNeeded();
123  operandExprs = tmpOperandExprs;
124  operandVars = tmpOperandVars;
125 }
126 
127 const std::string &DExpression::name() const
128 {
129  return val->varName;
130 }
131 
132 ExprVarRef *DExpression::resolveVar(const std::string &name) const
133 {
134  // first time resolve var from all exprs & vars
135  // then resolve var from used exprs & vars
136  for (auto *operandExpr : operandExprs) {
137  if (operandExpr->name() == name) {
138  tmpOperandExprs.insert(operandExpr);
139  operandExpr->val->users.insert(const_cast<DExpression *>(this));
140  return operandExpr->val;
141  }
142  }
143 
144  for (auto *operandVar : operandVars) {
145  if (operandVar->varName == name) {
146  tmpOperandVars.insert(operandVar);
147  operandVar->users.insert(const_cast<DExpression *>(this));
148  return operandVar;
149  }
150  }
151 
153  return nullptr;
154 }
155 
157 {
158  if (_desiredReturnType.isFP()) {
159  const double *ret = evalFP();
160  auto *fpVal = dynamic_cast<GlobalFP *>(val);
161  fpVal->val.assign(ret, ret + fpVal->val.size());
162  return;
163  }
164 
165  assert(_desiredReturnType.isString());
166  auto *strVal = dynamic_cast<GlobalStr *>(val);
167  strVal->val = evalStr();
168 }
169 
171 {
172  for (auto *AllExpr : AllExprs)
173  delete AllExpr;
174 
175  for (auto *AllExternalVar : AllExternalVars)
176  delete AllExternalVar;
177 }
178 
179 VariableHandle Expressions::addExternalVariable(const std::string &variableName, ExprType seTy)
180 {
181  std::pair<std::set<GlobalVal *>::iterator, bool> ret;
182 
183  if (seTy.isFP())
184  ret = AllExternalVars.insert(new GlobalFP(variableName, seTy.dim()));
185  else if (seTy.isString())
186  ret = AllExternalVars.insert(new GlobalStr(variableName));
187  else
188  assert(false);
189 
190  return ret.first;
191 }
192 
193 ExprHandle Expressions::addExpression(const std::string &varName, ExprType seTy, const std::string &expr)
194 {
195  std::pair<std::set<DExpression *>::iterator, bool> ret;
196  ret = AllExprs.insert(new DExpression(varName, *this, expr, seTy));
197  return ret.first;
198 }
199 
201 {
202  GlobalVal *thisvar = *vh;
203  auto initSize = static_cast<unsigned>(thisvar->users.size());
204  if (!initSize)
205  return AllExternalVars.end();
206 
207  std::set<DExpression *> ret = getAffectedExpr(thisvar);
208  exprToEval.insert(ret.begin(), ret.end());
209  // std::cout << "exprToEval size is " << exprToEval.size() << std::endl;
210  return vh;
211 }
212 
213 void Expressions::setLoopVariable(VariableSetHandle handle, double *values, unsigned dim)
214 {
215  if (handle == AllExternalVars.end())
216  return;
217 
218  auto *thisvar = dynamic_cast<GlobalFP *>(*handle);
219  assert(thisvar && "set value to variable with incompatible types.");
220 
221  assert(dim == thisvar->val.size());
222  for (unsigned i = 0; i < dim; ++i)
223  thisvar->val[i] = values[i];
224 }
225 
226 void Expressions::setLoopVariable(VariableSetHandle handle, const char *values)
227 {
228  if (handle == AllExternalVars.end())
229  return;
230 
231  auto *thisvar = dynamic_cast<GlobalStr *>(*handle);
232  assert(thisvar && "set value to variable with incompatible types.");
233  thisvar->val = values;
234 }
235 
236 void Expressions::setVariable(VariableHandle handle, double *values, unsigned dim)
237 {
238  auto *thisvar = dynamic_cast<GlobalFP *>(*handle);
239  assert(thisvar && "set value to variable with incompatible types.");
240 
241  assert(dim == thisvar->val.size());
242  for (unsigned i = 0; i < dim; ++i)
243  thisvar->val[i] = values[i];
244 
245  // eval loop invariant now.
246  std::set<DExpression *> ret = getAffectedExpr(thisvar);
247  for (auto *I : ret)
248  I->eval();
249 }
250 
251 void Expressions::setVariable(VariableHandle handle, const char *values)
252 {
253  auto *thisvar = dynamic_cast<GlobalStr *>(*handle);
254  assert(thisvar && "set value to variable with incompatible types.");
255  thisvar->val = values;
256 
257  // eval loop invariant now.
258  std::set<DExpression *> ret = getAffectedExpr(thisvar);
259  for (auto *I : ret)
260  I->eval();
261 }
262 
264 {
265  bool ret = true;
266  for (auto *AllExpr : AllExprs)
267  ret &= AllExpr->isValid();
268  return ret;
269 }
270 
272 {
273  // std::cout << "exprToEval size is " << exprToEval.size() << std::endl;
274 
275  DExpression *de = *eh;
276  std::set<DExpression *> all = getTransitiveOperandExpr(de);
277  // std::cout << "all size is " << all.size() << std::endl;
278 
279  std::vector<DExpression *>::iterator it;
280 
281  std::vector<DExpression *> ret1(all.size());
282  it = std::set_intersection(all.begin(), all.end(), exprToEval.begin(), exprToEval.end(), ret1.begin());
283  ret1.resize(it - ret1.begin());
284 
285  std::vector<DExpression *> ret2(ret1.size());
286  it = std::set_difference(ret1.begin(), ret1.end(), exprEvaled.begin(), exprEvaled.end(), ret2.begin());
287  ret2.resize(it - ret2.begin());
288 
289  exprEvaled.insert(ret2.begin(), ret2.end());
290 
291  // std::cout << "ret2 size is " << ret2.size() << std::endl;
292  return std::make_pair(eh, ret2);
293 }
294 
295 const std::vector<double> &Expressions::evalFP(ExprEvalHandle eeh)
296 {
297  // std::cout << "eeh.second.size() is " << eeh.second.size() << std::endl;
298  for (auto & I : eeh.second)
299  I->eval();
300 
301  auto *thisvar = dynamic_cast<GlobalFP *>((*eeh.first)->val);
302 
303  // std::cout << thisvar->val[0] << ","
304  // << thisvar->val[1] << ","
305  // << thisvar->val[2] << std::endl;
306  return thisvar->val;
307 }
308 
310 {
311  for (auto & I : eeh.second)
312  I->eval();
313 
314  auto *thisvar = dynamic_cast<GlobalStr *>((*eeh.first)->val);
315  return thisvar->val;
316 }
317 } // namespace KSeExpr
Expressions & dContext
Definition: ExprMultiExpr.h:21
const std::string & name() const
std::set< GlobalVal * > operandVars
Definition: ExprMultiExpr.h:27
std::set< DExpression * > operandExprs
Definition: ExprMultiExpr.h:26
ExprVarRef * resolveVar(const std::string &name) const override
DExpression(const std::string &varName, Expressions &context, const std::string &e, const ExprType &type=ExprType().FP(3), EvaluationStrategy be=defaultEvaluationStrategy)
int dim() const
Definition: ExprType.h:180
bool isString() const
Definition: ExprType.h:210
bool isFP() const
Direct is predicate checks.
Definition: ExprType.h:190
abstract class for implementing variable references
Definition: Expression.h:36
virtual ExprType type() const
returns (current) type
Definition: Expression.h:50
main expression class
Definition: Expression.h:67
void addError(const ErrorCode error, const std::vector< std::string > ids, const int startPos, const int endPos) const
Definition: Expression.h:207
const double * evalFP(VarBlock *varBlock=nullptr) const
Definition: Expression.cpp:269
void prepIfNeeded() const
Definition: Expression.h:276
EvaluationStrategy
Types of evaluation strategies that are available.
Definition: Expression.h:70
const char * evalStr(VarBlock *varBlock=nullptr) const
Definition: Expression.cpp:304
ExprType _desiredReturnType
Definition: Expression.h:268
std::set< DExpression * > exprEvaled
Definition: ExprMultiExpr.h:38
void setLoopVariable(VariableSetHandle handle, double *values, unsigned dim)
std::set< DExpression * > AllExprs
Definition: ExprMultiExpr.h:41
const std::vector< double > & evalFP(ExprEvalHandle eeh)
std::set< GlobalVal * > AllExternalVars
Definition: ExprMultiExpr.h:42
std::set< DExpression * > exprToEval
Definition: ExprMultiExpr.h:37
VariableHandle addExternalVariable(const std::string &variableName, ExprType seTy)
VariableSetHandle getLoopVarSetHandle(VariableHandle vh)
ExprHandle addExpression(const std::string &varName, ExprType seTy, const std::string &expr)
const char * evalStr(ExprEvalHandle eeh)
void setVariable(VariableHandle handle, double *values, unsigned dim)
ExprEvalHandle getExprEvalHandle(ExprHandle eh)
GlobalVal(const std::string &varName, const KSeExpr::ExprType &et)
std::set< DExpression * > users
std::pair< ExprHandle, std::vector< DExpression * > > ExprEvalHandle
Definition: ExprMultiExpr.h:17
std::set< GlobalVal * >::iterator VariableHandle
Definition: ExprMultiExpr.h:14
@ UndeclaredVariable
Definition: ErrorCode.h:35
std::set< DExpression * >::iterator ExprHandle
Definition: ExprMultiExpr.h:16
std::set< GlobalVal * >::iterator VariableSetHandle
Definition: ExprMultiExpr.h:15
void eval(const char **) override
void eval(double *result) override
returns this variable's value by setting result
std::vector< double > val
GlobalFP(const std::string &varName, int dim)
GlobalStr(const std::string &varName)
void eval(const char **result) override
void eval(double *) override
returns this variable's value by setting result