SeExpr
Expression.cpp
Go to the documentation of this file.
1/*
2 Copyright Disney Enterprises, Inc. All rights reserved.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License
6 and the following modification to it: Section 6 Trademarks.
7 deleted and replaced with:
8
9 6. Trademarks. This License does not grant permission to use the
10 trade names, trademarks, service marks, or product names of the
11 Licensor and its affiliates, except as required for reproducing
12 the content of the NOTICE file.
13
14 You may obtain a copy of the License at
15 http://www.apache.org/licenses/LICENSE-2.0
16*/
17#ifndef MAKEDEPEND
18#include <iostream>
19#include <math.h>
20#include <stack>
21#include <algorithm>
22#include <sstream>
23#endif
24
25#include "ExprConfig.h"
26#include "ExprNode.h"
27#include "ExprParser.h"
28#include "ExprFunc.h"
29#include "Expression.h"
30#include "ExprType.h"
31#include "ExprEnv.h"
32#include "Platform.h"
33
34#include "Evaluator.h"
35#include "ExprWalker.h"
36
37#include <cstdio>
38#include <typeinfo>
39
40namespace SeExpr2 {
41
42// Get debugging flag from environment
43bool Expression::debugging = getenv("SE_EXPR_DEBUG") != 0;
44// Choose the defeault strategy based on what we've compiled with (SEEXPR_ENABLE_LLVM)
45// And the environment variables SE_EXPR_DEBUG
48 std::cerr << "SeExpr2 Debug Mode Enabled " <<
49#if defined(WINDOWS)
50 _MSC_FULL_VER
51#else
52 __VERSION__
53#endif
54 << std::endl;
55 }
56#ifdef SEEXPR_ENABLE_LLVM
57 if (char* env = getenv("SE_EXPR_EVAL")) {
58 if (Expression::debugging) std::cerr << "Overriding SeExpr Evaluation Default to be " << env << std::endl;
59 return !strcmp(env, "LLVM") ? Expression::UseLLVM : !strcmp(env, "INTERPRETER") ? Expression::UseInterpreter
61 } else
63#else
65#endif
66}
68
70 public:
71 virtual bool examine(const SeExpr2::ExprNode* examinee);
72 virtual void reset() {};
73};
74
75bool TypePrintExaminer::examine(const ExprNode* examinee) {
76 const ExprNode* curr = examinee;
77 int depth = 0;
78 char buf[1024];
79 while (curr != 0) {
80 depth++;
81 curr = curr->parent();
82 }
83 sprintf(buf, "%*s", depth * 2, " ");
84 std::cout << buf << "'" << examinee->toString() << "' " << typeid(*examinee).name()
85 << " type=" << examinee->type().toString() << std::endl;
86
87 return true;
88};
89
91 : _wantVec(true), _expression(""), _evaluationStrategy(evaluationStrategy), _context(&Context::global()),
92 _desiredReturnType(ExprType().FP(3).Varying()), _parseTree(0), _isValid(0), _parsed(0), _prepped(0),
93 _interpreter(0), _llvmEvaluator(new LLVMEvaluator()) {
95}
96
97Expression::Expression(const std::string& e,
98 const ExprType& type,
99 EvaluationStrategy evaluationStrategy,
100 const Context& context)
101 : _wantVec(true), _expression(e), _evaluationStrategy(evaluationStrategy), _context(&context),
102 _desiredReturnType(type), _parseTree(0), _isValid(0), _parsed(0), _prepped(0), _interpreter(0),
103 _llvmEvaluator(new LLVMEvaluator()) {
105}
106
108 reset();
109 delete _llvmEvaluator;
110}
111
113 if (_interpreter) {
115 std::cerr << "return slot " << _returnSlot << std::endl;
116 }
117}
118
120
122 if (_parseTree) {
123 // print the parse tree
124 std::cerr << "Parse tree desired type " << _desiredReturnType.toString() << " actual "
125 << _parseTree->type().toString() << std::endl;
126 TypePrintExaminer _examiner;
127 SeExpr2::ConstWalker _walker(&_examiner);
128 _walker.walk(_parseTree);
129 }
130}
131
133 delete _llvmEvaluator;
135 delete _parseTree;
136 _parseTree = 0;
138 delete _interpreter;
139 _interpreter = 0;
140 }
141 _isValid = 0;
142 _parsed = 0;
143 _prepped = 0;
144 _parseError = "";
145 _vars.clear();
146 _funcs.clear();
147 //_localVars.clear();
148 _errors.clear();
151 _comments.clear();
152}
153
155 reset();
156 _context = &context;
157}
158
160 reset();
161 _desiredReturnType = type;
162}
163
165 reset();
166 _varBlockCreator = creator;
167}
168
169void Expression::setExpr(const std::string& e) {
170 if (_expression != "") reset();
171 _expression = e;
172}
173
176 return _isValid;
177}
178
182}
183
184bool Expression::usesVar(const std::string& name) const {
186 return _vars.find(name) != _vars.end();
187}
188
189bool Expression::usesFunc(const std::string& name) const {
191 return _funcs.find(name) != _funcs.end();
192}
193
194void Expression::parse() const {
195 if (_parsed) return;
196 _parsed = true;
197 int tempStartPos, tempEndPos;
198 ExprParse(_parseTree, _parseError, tempStartPos, tempEndPos, _comments, this, _expression.c_str(), _wantVec);
199 if (!_parseTree) {
200 addError(_parseError, tempStartPos, tempEndPos);
201 }
202}
203
204void Expression::prep() const {
205 if (_prepped) return;
206#ifdef SEEXPR_PERFORMANCE
207 PrintTiming timer("[ PREP ] v2 prep time: ");
208#endif
209 _prepped = true;
211
212 bool error = false;
213
214 if (!_parseTree) {
215 // parse error
216 error = true;
218 // prep error
219 error = true;
221 // incompatible type error
222 error = true;
223 _parseTree->addError("Expression generated type " + _parseTree->type().toString() +
224 " incompatible with desired type " + _desiredReturnType.toString());
225 } else {
226 _isValid = true;
227
229 if (debugging) {
231 std::cerr << "Eval strategy is interpreter" << std::endl;
232 }
233 assert(!_interpreter);
236 if (_desiredReturnType.isFP()) {
237 int dimWanted = _desiredReturnType.dim();
238 int dimHave = _parseTree->type().dim();
239 if (dimWanted > dimHave) {
240 _interpreter->addOp(getTemplatizedOp<Promote>(dimWanted));
241 int finalOp = _interpreter->allocFP(dimWanted);
243 _interpreter->addOperand(finalOp);
244 _returnSlot = finalOp;
246 }
247 }
249 } else { // useLLVM
250 if (debugging) {
251 std::cerr << "Eval strategy is llvm" << std::endl;
253 }
255 error = true;
256 }
257 }
258
259 // TODO: need promote
261 }
262
263 if (error) {
264 _isValid = false;
266
267 // build line lookup table
268 std::vector<int> lines;
269 const char* start = _expression.c_str();
270 const char* p = _expression.c_str();
271 while (*p != 0) {
272 if (*p == '\n') lines.push_back(static_cast<int>(p - start));
273 p++;
274 }
275 lines.push_back(static_cast<int>(p - start));
276
277 std::stringstream sstream;
278 for (unsigned int i = 0; i < _errors.size(); i++) {
279 int* bound = std::lower_bound(&*lines.begin(), &*lines.end(), _errors[i].startPos);
280 int line = static_cast<int>(bound - &*lines.begin() + 1);
281 int lineStart = line == 1 ? 0 : lines[line - 1];
282 int col = _errors[i].startPos - lineStart;
283 sstream << " Line " << line << " Col " << col << " - " << _errors[i].error << std::endl;
284 }
285 _parseError = std::string(sstream.str());
286 }
287
288 if (debugging) {
289 std::cerr << "ending with isValid " << _isValid << std::endl;
290 std::cerr << "parse error \n" << parseError() << std::endl;
291 }
292}
293
294bool Expression::isVec() const {
295 prepIfNeeded();
296 return _isValid ? _parseTree->isVec() : _wantVec;
297}
298
300 prepIfNeeded();
301 return _returnType;
302}
303
304const double* Expression::evalFP(VarBlock* varBlock) const {
305 prepIfNeeded();
306 if (_isValid) {
308 _interpreter->eval(varBlock);
309 return (varBlock && varBlock->threadSafe) ? &(varBlock->d[_returnSlot]) : &_interpreter->d[_returnSlot];
310 } else { // useLLVM
311 return _llvmEvaluator->evalFP(varBlock);
312 }
313 }
314 static double noCrash[16] = {};
315 return noCrash;
316}
317
318void Expression::evalMultiple(VarBlock* varBlock, int outputVarBlockOffset, size_t rangeStart, size_t rangeEnd) const {
319 prepIfNeeded();
320 if (_isValid) {
322 // TODO: need strings to work
323 int dim = _desiredReturnType.dim();
324 // double* iHack=reinterpret_cast<double**>(varBlock->data())[outputVarBlockOffset];
325 double* destBase = reinterpret_cast<double**>(varBlock->data())[outputVarBlockOffset];
326 for (size_t i = rangeStart; i < rangeEnd; i++) {
327 varBlock->indirectIndex = static_cast<int>(i);
328 const double* f = evalFP(varBlock);
329 for (int k = 0; k < dim; k++) {
330 destBase[dim * i + k] = f[k];
331 }
332 }
333 } else { // useLLVM
334 _llvmEvaluator->evalMultiple(varBlock, outputVarBlockOffset, rangeStart, rangeEnd);
335 }
336 }
337}
338
339const char* Expression::evalStr(VarBlock* varBlock) const {
340 prepIfNeeded();
341 if (_isValid) {
343 _interpreter->eval(varBlock);
344 return (varBlock && varBlock->threadSafe) ? varBlock->s[_returnSlot] : _interpreter->s[_returnSlot];
345 } else { // useLLVM
346 return _llvmEvaluator->evalStr(varBlock);
347 }
348 }
349 return 0;
350}
351
352} // end namespace SeExpr2/
static const int p[514]
Definition: NoiseTables.h:20
Platform-specific classes, functions, and includes.
static void init()
call to define built-in funcs and load standard plugins
Definition: ExprFunc.cpp:112
bool isVec() const
True if node has a vector result.
Definition: ExprNode.h:99
void addError(const std::string &error) const
Register error. This will allow users and sophisticated editors to highlight where in code problem wa...
Definition: ExprNode.h:168
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
const ExprNode * parent() const
Access parent node - root node has no parent.
Definition: ExprNode.h:112
std::string toString() const
Access to original string representation of current expression.
Definition: ExprNode.h:105
const ExprType & type() const
The type of the node.
Definition: ExprNode.h:145
virtual ExprType prep(bool dontNeedScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:104
static bool valuesCompatible(const ExprType &a, const ExprType &b)
Checks if value types are compatible.
Definition: ExprType.h:173
std::string toString() const
Stringify the type into a printable string.
Definition: ExprType.h:191
bool isValid() const
Definition: ExprType.h:167
bool isFP() const
Direct is predicate checks.
Definition: ExprType.h:164
int dim() const
Definition: ExprType.h:160
ExprType & Error()
Mutate this into an error type.
Definition: ExprType.h:102
bool isLifetimeConstant() const
validity check: type is not an error
Definition: ExprType.h:183
void reset()
Reset to factory state (one empty environment that is current)
Definition: ExprEnv.h:153
bool isVec() const
Definition: Expression.cpp:294
void parseIfNeeded() const
Definition: Expression.h:242
bool usesVar(const std::string &name) const
Definition: Expression.cpp:184
const Context & context() const
Definition: Expression.h:216
void setDesiredReturnType(const ExprType &type)
Definition: Expression.cpp:159
ExprType _returnType
Definition: Expression.h:254
Interpreter * _interpreter
Definition: Expression.h:306
const VarBlockCreator * _varBlockCreator
Definition: Expression.h:313
std::vector< std::pair< int, int > > _comments
Definition: Expression.h:291
EvaluationStrategy
Types of evaluation strategies that are available.
Definition: Expression.h:79
Expression(EvaluationStrategy be=Expression::defaultEvaluationStrategy)
Definition: Expression.cpp:90
std::vector< Error > _errors
Definition: Expression.h:288
const char * evalStr(VarBlock *varBlock=nullptr) const
Definition: Expression.cpp:339
std::set< std::string > _funcs
Definition: Expression.h:297
EvaluationStrategy _evaluationStrategy
Definition: Expression.h:259
const ExprType & returnType() const
Definition: Expression.cpp:299
void setExpr(const std::string &e)
Definition: Expression.cpp:169
void addError(const std::string &error, const int startPos, const int endPos) const
Definition: Expression.h:205
void prep() const
Definition: Expression.cpp:204
LLVMEvaluator * _llvmEvaluator
Definition: Expression.h:310
bool usesFunc(const std::string &name) const
Definition: Expression.cpp:189
std::set< std::string > _vars
Definition: Expression.h:294
bool syntaxOK() const
Definition: Expression.cpp:174
bool isConstant() const
Definition: Expression.cpp:179
void setVarBlockCreator(const VarBlockCreator *varBlockCreator)
Definition: Expression.cpp:164
void evalMultiple(VarBlock *varBlock, int outputVarBlockOffset, size_t rangeStart, size_t rangeEnd) const
Evaluate multiple blocks.
Definition: Expression.cpp:318
const double * evalFP(VarBlock *varBlock=nullptr) const
Definition: Expression.cpp:304
void debugPrintLLVM() const
Definition: Expression.cpp:119
const std::string & parseError() const
Definition: Expression.h:140
std::string _parseError
Definition: Expression.h:285
const Context * _context
Definition: Expression.h:262
ExprNode * _parseTree
Definition: Expression.h:271
std::string _expression
Definition: Expression.h:257
void setContext(const Context &context)
Definition: Expression.cpp:154
ExprType _desiredReturnType
Definition: Expression.h:266
static EvaluationStrategy defaultEvaluationStrategy
What evaluation strategy to use by default.
Definition: Expression.h:84
void debugPrintInterpreter() const
Definition: Expression.cpp:112
static bool debugging
Whether to debug expressions.
Definition: Expression.h:86
void prepIfNeeded() const
Definition: Expression.h:274
std::vector< std::string > _threadUnsafeFunctionCalls
Definition: Expression.h:303
void debugPrintParseTree() const
Definition: Expression.cpp:121
void parse() const
Definition: Expression.cpp:194
ExprVarEnvBuilder _envBuilder
Definition: Expression.h:269
int allocFP(int n)
! Allocate a floating point set of data of dimension n
Definition: Interpreter.h:104
int addOp(OpF op)
! adds an operator to the program (pointing to the data at the current location)
Definition: Interpreter.h:73
void eval(VarBlock *varBlock, bool debug=false)
Evaluate program.
Definition: Interpreter.cpp:31
int addOperand(int param)
! Adds an operand. Note this should be done after doing the addOp!
Definition: Interpreter.h:96
void endOp(bool execute=true)
Definition: Interpreter.h:83
std::vector< double > d
Double data (constants and evaluated)
Definition: Interpreter.h:43
std::vector< char * > s
constant and evaluated pointer data
Definition: Interpreter.h:45
void print(int pc=-1) const
Debug by printing program.
Definition: Interpreter.cpp:69
const char * evalStr(VarBlock *varBlock)
Definition: Evaluator.h:391
void evalMultiple(VarBlock *varBlock, int outputVarBlockOffset, size_t rangeStart, size_t rangeEnd)
Definition: Evaluator.h:403
bool prepLLVM(ExprNode *parseTree, ExprType desiredReturnType)
Definition: Evaluator.h:399
const double * evalFP(VarBlock *varBlock)
Definition: Evaluator.h:395
virtual bool examine(const SeExpr2::ExprNode *examinee)
Definition: Expression.cpp:75
A class that lets you register for the variables used by one or more expressions.
Definition: VarBlock.h:84
A thread local evaluation context. Just allocate and fill in with data.
Definition: VarBlock.h:33
std::vector< double > d
copy of Interpreter's double data
Definition: VarBlock.h:68
int indirectIndex
indirect index to add to pointer based data
Definition: VarBlock.h:62
char ** data()
Raw data of the data block pointer (used by compiler)
Definition: VarBlock.h:74
bool threadSafe
if true, interpreter's data will be copied to this instance before evaluation.
Definition: VarBlock.h:65
std::vector< char * > s
copy of Interpreter's str data
Definition: VarBlock.h:71
void walk(T_NODE *examinee)
Preorder walk.
Definition: ExprWalker.cpp:30
SeExpr2::SPrintFuncX sprintf
static Expression::EvaluationStrategy chooseDefaultEvaluationStrategy()
Definition: Expression.cpp:46
bool ExprParse(SeExpr2::ExprNode *&parseTree, std::string &error, int &errorStart, int &errorEnd, std::vector< std::pair< int, int > > &_comments, const SeExpr2::Expression *expr, const char *str, bool wantVec=true)
If a scalar is used in a vector context
Definition: userdoc.txt:436
with numParticles numAttributes A variable block contains variable names and types but doesn t care what the values are< pre > void f(const std::string &s, MyParticleData *p, int outputDim=3)
Definition: varblocks.txt:35