KSeExpr 6.0.0.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
11namespace KSeExpr
12{
13class GlobalVal : public ExprVarRef
14{
15public:
16 GlobalVal(const std::string &varName, const KSeExpr::ExprType &et)
17 : ExprVarRef(et)
19 {
20 }
21 std::set<DExpression *> users;
22 std::string varName;
23};
24
25struct 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
48struct 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
70namespace
71{
72std::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
87std::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
103std::set<KSeExpr::DExpression *> tmpOperandExprs;
104std::set<KSeExpr::GlobalVal *> tmpOperandVars;
105} // namespace
106
107namespace KSeExpr
108{
109DExpression::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();
125}
126
127const std::string &DExpression::name() const
128{
129 return val->varName;
130}
131
132ExprVarRef *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) {
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) {
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
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
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
193ExprHandle 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
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
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
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
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
295const 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
const std::string & name() const
std::set< GlobalVal * > operandVars
std::set< DExpression * > operandExprs
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
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
ExprType _desiredReturnType
Definition Expression.h:268
std::set< DExpression * > exprEvaled
void setLoopVariable(VariableSetHandle handle, double *values, unsigned dim)
std::set< DExpression * > AllExprs
const std::vector< double > & evalFP(ExprEvalHandle eeh)
std::set< GlobalVal * > AllExternalVars
std::set< DExpression * > exprToEval
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
std::set< GlobalVal * >::iterator VariableHandle
@ UndeclaredVariable
Definition ErrorCode.h:35
std::set< DExpression * >::iterator ExprHandle
std::set< GlobalVal * >::iterator VariableSetHandle
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