KSeExpr 6.0.0.0
Expression.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 <cmath>
8#include <cstdio>
9#include <iostream>
10#include <sstream>
11#include <stack>
12#include <typeinfo>
13
14#include "Evaluator.h"
15#include "ExprConfig.h"
16#include "ExprEnv.h"
17#include "ExprFunc.h"
18#include "ExprNode.h"
19#include "ExprParser.h"
20#include "ExprType.h"
21#include "ExprWalker.h"
22#include "Expression.h"
23#include "TypePrinter.h"
24
25namespace KSeExpr {
26
27// Get debugging flag from environment
28bool Expression::debugging = getenv("SE_EXPR_DEBUG") != nullptr;
29// Choose the defeault strategy based on what we've compiled with (SEEXPR_ENABLE_LLVM)
30// And the environment variables SE_EXPR_DEBUG
33 std::cerr << "KSeExpr Debug Mode Enabled " <<
34#if defined(_MSC_VER)
36#else
38#endif
39 << std::endl;
40 }
41#if defined(SEEXPR_ENABLE_LLVM)
42 if (char* env = getenv("SE_EXPR_EVAL")) {
43 if (Expression::debugging) std::cerr << "Overriding SeExpr Evaluation Default to be " << env << std::endl;
44 return !strcmp(env, "LLVM") ? Expression::UseLLVM : !strcmp(env, "INTERPRETER") ? Expression::UseInterpreter
46 } else
48#else
50#endif
51}
53
55 : _wantVec(true), _expression(""), _evaluationStrategy(evaluationStrategy), _context(&Context::global()),
56 _desiredReturnType(ExprType().FP(3).Varying()), _parseTree(nullptr), _isValid(false), _parsed(false), _prepped(false),
57 _interpreter(nullptr), _llvmEvaluator(new LLVMEvaluator()) {
59}
60
61Expression::Expression(const std::string& e,
62 const ExprType& type,
64 const Context& context)
65 : _wantVec(true), _expression(e), _evaluationStrategy(evaluationStrategy), _context(&context),
66 _desiredReturnType(type), _parseTree(nullptr), _isValid(false), _parsed(false), _prepped(false), _interpreter(nullptr),
67 _llvmEvaluator(new LLVMEvaluator()) {
69}
70
75
77 if (_interpreter) {
79 std::cerr << "return slot " << _returnSlot << std::endl;
80 }
81}
82
84
86 if (_parseTree) {
87 // print the parse tree
88 std::cerr << "Parse tree desired type " << _desiredReturnType.toString() << " actual "
89 << _parseTree->type().toString() << std::endl;
90 TypePrintExaminer _examiner;
91 KSeExpr::ConstWalker _walker(&_examiner);
92 _walker.walk(_parseTree);
93 }
94}
95
97 delete _llvmEvaluator;
99 delete _parseTree;
100 _parseTree = nullptr;
102 delete _interpreter;
103 _interpreter = nullptr;
104 }
105 _isValid = 0;
106 _parsed = 0;
107 _prepped = 0;
109 _parseErrorIds.clear();
110 _vars.clear();
111 _funcs.clear();
112 //_localVars.clear();
113 _errors.clear();
116 _comments.clear();
117}
118
119void Expression::setContext(const Context& context) {
120 reset();
121 _context = &context;
122}
123
125 reset();
126 _desiredReturnType = type;
127}
128
133
134void Expression::setExpr(const std::string& e) {
135 if (_expression != "") reset();
136 _expression = e;
137}
138
141 return _isValid;
142}
143
146 return returnType().isLifetimeConstant();
147}
148
149bool Expression::usesVar(const std::string& name) const {
151 return _vars.find(name) != _vars.end();
152}
153
154bool Expression::usesFunc(const std::string& name) const {
156 return _funcs.find(name) != _funcs.end();
157}
158
168
169void Expression::prep() const {
170 if (_prepped) return;
171#ifdef SEEXPR_PERFORMANCE
172 PerformanceTimer timer("[ PREP ] v2 prep time: ");
173#endif
174 _prepped = true;
176
177 bool error = false;
178 std::string _parseError;
179
180 if (!_parseTree) {
181 // parse error
182 error = true;
183 } else if (!_parseTree->prep(_desiredReturnType.isFP(1), _envBuilder).isValid()) {
184 // prep error
185 error = true;
187 // incompatible type error
188 error = true;
190 } else {
191 _isValid = true;
192
194 if (debugging) {
196 std::cerr << "Eval strategy is interpreter" << std::endl;
197 }
201 if (_desiredReturnType.isFP()) {
203 int dimHave = _parseTree->type().dim();
204 if (dimWanted > dimHave) {
211 }
212 }
214 } else { // useLLVM
215 if (debugging) {
216 std::cerr << "Eval strategy is llvm" << std::endl;
218 }
220 error = true;
221 }
222 }
223
224 // TODO: need promote
226 }
227
228 if (error) {
229 _isValid = false;
231
232 // build line lookup table
233 std::vector<int> lines;
234 const char* start = _expression.c_str();
235 const char* p = _expression.c_str();
236 while (*p != 0) {
237 if (*p == '\n') lines.push_back(static_cast<int>(p - start));
238 p++;
239 }
240 lines.push_back(static_cast<int>(p - start));
241
242 std::stringstream sstream;
243 for (unsigned int i = 0; i < _errors.size(); i++) {
244 int* bound = std::lower_bound(&*lines.begin(), &*lines.end(), _errors[i].startPos);
245 int line = static_cast<int>(bound - &*lines.begin() + 1);
246 int lineStart = line == 1 ? 0 : lines[line - 1];
247 int col = _errors[i].startPos - lineStart;
248 sstream << " Line " << line << " Col " << col << " - " << _errors[i].error << std::endl;
249 }
250 _parseError = std::string(sstream.str());
251 }
252
253 if (debugging) {
254 std::cerr << "ending with isValid " << _isValid << std::endl;
255 std::cerr << "parse error \n" << _parseError << std::endl;
256 }
257}
258
259bool Expression::isVec() const {
260 prepIfNeeded();
261 return _isValid ? _parseTree->isVec() : _wantVec;
262}
263
265 prepIfNeeded();
266 return _returnType;
267}
268
269const double* Expression::evalFP(VarBlock* varBlock) const {
270 prepIfNeeded();
271 if (_isValid) {
274 return (varBlock && varBlock->threadSafe) ? &(varBlock->d[_returnSlot]) : &_interpreter->d[_returnSlot];
275 } else { // useLLVM
277 }
278 }
279 static double noCrash[16] = {};
280 return noCrash;
281}
282
284 prepIfNeeded();
285 if (_isValid) {
287 // TODO: need strings to work
288 int dim = _desiredReturnType.dim();
289 // double* iHack=reinterpret_cast<double**>(varBlock->data())[outputVarBlockOffset];
290 double* destBase = reinterpret_cast<double**>(varBlock->data())[outputVarBlockOffset];
291 for (size_t i = rangeStart; i < rangeEnd; i++) {
292 varBlock->indirectIndex = static_cast<int>(i);
293 const double* f = evalFP(varBlock);
294 for (int k = 0; k < dim; k++) {
295 destBase[dim * i + k] = f[k];
296 }
297 }
298 } else { // useLLVM
300 }
301 }
302}
303
305 prepIfNeeded();
306 if (_isValid) {
309 return (varBlock && varBlock->threadSafe) ? varBlock->s[_returnSlot] : _interpreter->s[_returnSlot];
310 } else { // useLLVM
312 }
313 }
314 return nullptr;
315}
316
317} // end namespace KSeExpr/
static constexpr std::array< int, 514 > p
Definition NoiseTables.h:10
static void init()
call to define built-in funcs
Definition ExprFunc.cpp:104
virtual ExprType prep(bool dontNeedScalar, ExprVarEnvBuilder &envBuilder)
Definition ExprNode.cpp:121
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
const ExprType & type() const
The type of the node.
Definition ExprNode.h:150
void addError(const ErrorCode error, const std::vector< std::string > &ids={}) const
Register error. This will allow users and sophisticated editors to highlight where in code problem wa...
Definition ExprNode.h:182
bool isVec() const
True if node has a vector result.
Definition ExprNode.h:83
int dim() const
Definition ExprType.h:180
std::string toString() const
Stringify the type into a printable string.
Definition ExprType.h:253
ExprType & Error()
Mutate this into an error type.
Definition ExprType.h:111
bool isFP() const
Direct is predicate checks.
Definition ExprType.h:190
static bool valuesCompatible(const ExprType &a, const ExprType &b)
Checks if value types are compatible.
Definition ExprType.h:220
void reset()
Reset to factory state (one empty environment that is current)
Definition ExprEnv.h:189
const VarBlockCreator * _varBlockCreator
Definition Expression.h:318
void evalMultiple(VarBlock *varBlock, int outputVarBlockOffset, size_t rangeStart, size_t rangeEnd) const
Evaluate multiple blocks.
ErrorCode _parseErrorCode
Definition Expression.h:287
void setExpr(const std::string &e)
bool syntaxOK() const
static bool debugging
Whether to debug expressions.
Definition Expression.h:77
std::set< std::string > _vars
Definition Expression.h:299
bool usesFunc(const std::string &name) const
const Context * _context
Definition Expression.h:264
bool isConstant() const
void parseIfNeeded() const
Definition Expression.h:244
EvaluationStrategy _evaluationStrategy
Definition Expression.h:261
Expression(EvaluationStrategy be=Expression::defaultEvaluationStrategy)
void addError(const ErrorCode error, const std::vector< std::string > ids, const int startPos, const int endPos) const
Definition Expression.h:207
std::set< std::string > _funcs
Definition Expression.h:302
bool usesVar(const std::string &name) const
ExprNode * _parseTree
Definition Expression.h:273
Interpreter * _interpreter
Definition Expression.h:311
std::vector< std::string > _parseErrorIds
Definition Expression.h:290
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
void debugPrintParseTree() const
void setContext(const Context &context)
ExprVarEnvBuilder _envBuilder
Definition Expression.h:271
void debugPrintInterpreter() const
const ExprType & returnType() const
std::vector< std::pair< int, int > > _comments
Definition Expression.h:296
const Context & context() const
Definition Expression.h:218
const char * evalStr(VarBlock *varBlock=nullptr) const
std::vector< Error > _errors
Definition Expression.h:293
void setVarBlockCreator(const VarBlockCreator *varBlockCreator)
ExprType _desiredReturnType
Definition Expression.h:268
std::vector< std::string > _threadUnsafeFunctionCalls
Definition Expression.h:308
void setDesiredReturnType(const ExprType &type)
static EvaluationStrategy defaultEvaluationStrategy
What evaluation strategy to use by default.
Definition Expression.h:75
std::string _expression
Definition Expression.h:259
void debugPrintLLVM() const
LLVMEvaluator * _llvmEvaluator
Definition Expression.h:315
std::vector< double > d
Double data (constants and evaluated)
Definition Interpreter.h:33
int addOp(OpF op)
! adds an operator to the program (pointing to the data at the current location)
Definition Interpreter.h:63
void eval(VarBlock *varBlock, bool debug=false)
Evaluate program.
void endOp(bool execute=true)
Definition Interpreter.h:73
std::vector< char * > s
constant and evaluated pointer data
Definition Interpreter.h:35
int allocFP(int n)
! Allocate a floating point set of data of dimension n
Definition Interpreter.h:94
int addOperand(int param)
! Adds an operand. Note this should be done after doing the addOp!
Definition Interpreter.h:86
void print(int pc=-1) const
Debug by printing program.
static bool prepLLVM(ExprNode *, ExprType)
Definition Evaluator.h:466
static const double * evalFP(VarBlock *)
Definition Evaluator.h:461
static const char * evalStr(VarBlock *)
Definition Evaluator.h:456
static void evalMultiple(VarBlock *, int, size_t, size_t)
Definition Evaluator.h:471
A class that lets you register for the variables used by one or more expressions.
Definition VarBlock.h:90
A thread local evaluation context. Just allocate and fill in with data.
Definition VarBlock.h:22
static Expression::EvaluationStrategy chooseDefaultEvaluationStrategy()
bool ExprParse(KSeExpr::ExprNode *&parseTree, KSeExpr::ErrorCode &errorCode, std::vector< std::string > &errorIds, int &errorStart, int &errorEnd, std::vector< std::pair< int, int > > &_comments, const KSeExpr::Expression *expr, const char *str, bool wantVec=true)
@ None
OK.
Definition ErrorCode.h:9
@ ExpressionIncompatibleTypes
"Expression generated type " << _parseTree->type() << " incompatible with desired type " << _desiredR...
Definition ErrorCode.h:50