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 
40 namespace SeExpr2 {
41 
42 // Get debugging flag from environment
43 bool 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
62  return Expression::UseLLVM;
63 #else
65 #endif
66 }
68 
69 class TypePrintExaminer : public SeExpr2::Examiner<true> {
70  public:
71  virtual bool examine(const SeExpr2::ExprNode* examinee);
72  virtual void reset() {};
73 };
74 
75 bool 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 
97 Expression::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()) {
104  ExprFunc::init();
105 }
106 
108  reset();
109  delete _llvmEvaluator;
110 }
111 
113  if (_interpreter) {
114  _interpreter->print();
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();
149  _envBuilder.reset();
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 
169 void Expression::setExpr(const std::string& e) {
170  if (_expression != "") reset();
171  _expression = e;
172 }
173 
174 bool Expression::syntaxOK() const {
175  parseIfNeeded();
176  return _isValid;
177 }
178 
180  parseIfNeeded();
181  return returnType().isLifetimeConstant();
182 }
183 
184 bool Expression::usesVar(const std::string& name) const {
185  parseIfNeeded();
186  return _vars.find(name) != _vars.end();
187 }
188 
189 bool Expression::usesFunc(const std::string& name) const {
190  parseIfNeeded();
191  return _funcs.find(name) != _funcs.end();
192 }
193 
194 void 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 
204 void Expression::prep() const {
205  if (_prepped) return;
206 #ifdef SEEXPR_PERFORMANCE
207  PrintTiming timer("[ PREP ] v2 prep time: ");
208 #endif
209  _prepped = true;
210  parseIfNeeded();
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;
245  _interpreter->endOp();
246  }
247  }
248  if (debugging) _interpreter->print();
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;
265  _returnType = ExprType().Error();
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 
294 bool Expression::isVec() const {
295  prepIfNeeded();
296  return _isValid ? _parseTree->isVec() : _wantVec;
297 }
298 
300  prepIfNeeded();
301  return _returnType;
302 }
303 
304 const 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 
318 void 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 
339 const 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/
SeExpr2::Expression::debugPrintInterpreter
void debugPrintInterpreter() const
Definition: Expression.cpp:112
SeExpr2::Expression::usesVar
bool usesVar(const std::string &name) const
Definition: Expression.cpp:184
SeExpr2::Expression::debugging
static bool debugging
Whether to debug expressions.
Definition: Expression.h:86
SeExpr2::Expression::context
const Context & context() const
Definition: Expression.h:216
SeExpr2::Expression::_threadUnsafeFunctionCalls
std::vector< std::string > _threadUnsafeFunctionCalls
Definition: Expression.h:303
SeExpr2::Expression::isValid
bool isValid() const
Definition: Expression.h:133
SeExpr2::Expression::parseError
const std::string & parseError() const
Definition: Expression.h:140
SeExpr2::LLVMEvaluator::evalFP
const double * evalFP(VarBlock *varBlock)
Definition: Evaluator.h:395
SeExpr2::Interpreter::eval
void eval(VarBlock *varBlock, bool debug=false)
Evaluate program.
Definition: Interpreter.cpp:31
SeExpr2::Expression::_parseTree
ExprNode * _parseTree
Definition: Expression.h:271
SeExpr2::Expression::parseIfNeeded
void parseIfNeeded() const
Definition: Expression.h:242
f
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
SeExpr2::Expression::setVarBlockCreator
void setVarBlockCreator(const VarBlockCreator *varBlockCreator)
Definition: Expression.cpp:164
SeExpr2::Interpreter::endOp
void endOp(bool execute=true)
Definition: Interpreter.h:83
SeExpr2::VarBlock
A thread local evaluation context. Just allocate and fill in with data.
Definition: VarBlock.h:33
SeExpr2::Expression::UseInterpreter
Definition: Expression.h:80
SeExpr2::ExprNode::type
const ExprType & type() const
The type of the node.
Definition: ExprNode.h:145
SeExpr2::Interpreter::addOp
int addOp(OpF op)
! adds an operator to the program (pointing to the data at the current location)
Definition: Interpreter.h:73
SeExpr2::Expression::evalMultiple
void evalMultiple(VarBlock *varBlock, int outputVarBlockOffset, size_t rangeStart, size_t rangeEnd) const
Evaluate multiple blocks.
Definition: Expression.cpp:318
SeExpr2::Expression::_prepped
bool _prepped
Definition: Expression.h:282
SeExpr2::Expression::reset
void reset()
Definition: Expression.cpp:132
SeExpr2::ExprNode::addError
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
SeExpr2::LLVMEvaluator::debugPrint
void debugPrint()
Definition: Evaluator.h:406
SeExpr2::LLVMEvaluator::evalMultiple
void evalMultiple(VarBlock *varBlock, int outputVarBlockOffset, size_t rangeStart, size_t rangeEnd)
Definition: Evaluator.h:403
SeExpr2::Interpreter::d
std::vector< double > d
Double data (constants and evaluated)
Definition: Interpreter.h:43
SeExpr2::VarBlockCreator
A class that lets you register for the variables used by one or more expressions.
Definition: VarBlock.h:84
SeExpr2::Expression::_comments
std::vector< std::pair< int, int > > _comments
Definition: Expression.h:291
SeExpr2::ExprNode
Definition: ExprNode.h:72
SeExpr2::PrintTiming
Definition: Platform.h:150
SeExpr2::Expression::evalStr
const char * evalStr(VarBlock *varBlock=nullptr) const
Definition: Expression.cpp:339
SeExpr2::Expression::setExpr
void setExpr(const std::string &e)
Definition: Expression.cpp:169
SeExpr2::ExprFunc::init
static void init()
call to define built-in funcs and load standard plugins
Definition: ExprFunc.cpp:112
SeExpr2::Expression::_vars
std::set< std::string > _vars
Definition: Expression.h:294
SeExpr2::Expression::_expression
std::string _expression
Definition: Expression.h:257
SeExpr2::Expression::debugPrintParseTree
void debugPrintParseTree() const
Definition: Expression.cpp:121
SeExpr2::Expression::_wantVec
bool _wantVec
Definition: Expression.h:251
SeExpr2::Expression::_isValid
bool _isValid
Definition: Expression.h:280
SeExpr2::ExprNode::toString
std::string toString() const
Access to original string representation of current expression.
Definition: ExprNode.h:105
SeExpr2::Expression::_returnSlot
int _returnSlot
Definition: Expression.h:307
SeExpr2::ExprParse
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)
ExprParser.h
SeExpr2::ExprType::dim
int dim() const
Definition: ExprType.h:160
ExprFunc.h
SeExpr2::ExprType
Definition: ExprType.h:39
SeExpr2::VarBlock::d
std::vector< double > d
copy of Interpreter's double data
Definition: VarBlock.h:68
SeExpr2::Context
Definition: Context.h:24
Platform.h
Platform-specific classes, functions, and includes.
SeExpr2::ExprNode::isVec
bool isVec() const
True if node has a vector result.
Definition: ExprNode.h:99
SeExpr2::Expression::_desiredReturnType
ExprType _desiredReturnType
Definition: Expression.h:266
SeExpr2::Examiner
Definition: ExprWalker.h:33
SeExpr2::TypePrintExaminer::examine
virtual bool examine(const SeExpr2::ExprNode *examinee)
Definition: Expression.cpp:75
SeExpr2::Expression::prepIfNeeded
void prepIfNeeded() const
Definition: Expression.h:274
SeExpr2::Expression::Expression
Expression(EvaluationStrategy be=Expression::defaultEvaluationStrategy)
Definition: Expression.cpp:90
SeExpr2
Definition: Context.h:22
SeExpr2::ExprVarEnvBuilder::reset
void reset()
Reset to factory state (one empty environment that is current)
Definition: ExprEnv.h:153
Evaluator.h
SeExpr2::ExprType::isLifetimeConstant
bool isLifetimeConstant() const
validity check: type is not an error
Definition: ExprType.h:183
ExprType.h
SeExpr2::Expression::_errors
std::vector< Error > _errors
Definition: Expression.h:288
ExprNode.h
SeExpr2::Expression::isConstant
bool isConstant() const
Definition: Expression.cpp:179
SeExpr2::Expression::_evaluationStrategy
EvaluationStrategy _evaluationStrategy
Definition: Expression.h:259
ExprWalker.h
SeExpr2::Expression::_funcs
std::set< std::string > _funcs
Definition: Expression.h:297
SeExpr2::Expression::setContext
void setContext(const Context &context)
Definition: Expression.cpp:154
SeExpr2::ExprNode::buildInterpreter
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
Definition: Interpreter.cpp:538
SeExpr2::Expression::parse
void parse() const
Definition: Expression.cpp:194
SeExpr2::ExprNode::parent
const ExprNode * parent() const
Access parent node - root node has no parent.
Definition: ExprNode.h:112
SeExpr2::LLVMEvaluator::prepLLVM
bool prepLLVM(ExprNode *parseTree, ExprType desiredReturnType)
Definition: Evaluator.h:399
SeExpr2::ExprType::Error
ExprType & Error()
Mutate this into an error type.
Definition: ExprType.h:102
SeExpr2::Interpreter::allocFP
int allocFP(int n)
! Allocate a floating point set of data of dimension n
Definition: Interpreter.h:104
SeExpr2::Expression::~Expression
virtual ~Expression()
Definition: Expression.cpp:107
SeExpr2::Walker
Definition: ExprWalker.h:43
SeExpr2::ExprType::isFP
bool isFP() const
Direct is predicate checks.
Definition: ExprType.h:164
SeExpr2::TypePrintExaminer
Definition: Expression.cpp:69
SeExpr2::VarBlock::indirectIndex
int indirectIndex
indirect index to add to pointer based data
Definition: VarBlock.h:62
SeExpr2::Interpreter::s
std::vector< char * > s
constant and evaluated pointer data
Definition: Interpreter.h:45
SeExpr2::Expression::_parseError
std::string _parseError
Definition: Expression.h:285
ExprEnv.h
SeExpr2::ExprNode::prep
virtual ExprType prep(bool dontNeedScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:104
SeExpr2::ExprType::toString
std::string toString() const
Stringify the type into a printable string.
Definition: ExprType.h:191
SeExpr2::Expression::_parsed
bool _parsed
Definition: Expression.h:282
SeExpr2::Expression::returnType
const ExprType & returnType() const
Definition: Expression.cpp:299
SeExpr2::Expression::_envBuilder
ExprVarEnvBuilder _envBuilder
Definition: Expression.h:269
SeExpr2::Expression::_interpreter
Interpreter * _interpreter
Definition: Expression.h:306
SeExpr2::chooseDefaultEvaluationStrategy
static Expression::EvaluationStrategy chooseDefaultEvaluationStrategy()
Definition: Expression.cpp:46
SeExpr2::Expression::setDesiredReturnType
void setDesiredReturnType(const ExprType &type)
Definition: Expression.cpp:159
SeExpr2::Expression::EvaluationStrategy
EvaluationStrategy
Types of evaluation strategies that are available.
Definition: Expression.h:79
SeExpr2::VarBlock::threadSafe
bool threadSafe
if true, interpreter's data will be copied to this instance before evaluation.
Definition: VarBlock.h:65
SeExpr2::LLVMEvaluator
Definition: Evaluator.h:388
SeExpr2::Expression::defaultEvaluationStrategy
static EvaluationStrategy defaultEvaluationStrategy
What evaluation strategy to use by default.
Definition: Expression.h:84
SeExpr2::Expression::_context
const Context * _context
Definition: Expression.h:262
SeExpr2::Expression::_llvmEvaluator
LLVMEvaluator * _llvmEvaluator
Definition: Expression.h:310
p
static const int p[514]
Definition: NoiseTables.h:20
SeExpr2::ExprType::valuesCompatible
static bool valuesCompatible(const ExprType &a, const ExprType &b)
Checks if value types are compatible.
Definition: ExprType.h:173
SeExpr2::Expression::evalFP
const double * evalFP(VarBlock *varBlock=nullptr) const
Definition: Expression.cpp:304
SeExpr2::Expression::_returnType
ExprType _returnType
Definition: Expression.h:254
SeExpr2::VarBlock::s
std::vector< char * > s
copy of Interpreter's str data
Definition: VarBlock.h:71
SeExpr2::Expression::addError
void addError(const std::string &error, const int startPos, const int endPos) const
Definition: Expression.h:205
SeExpr2::VarBlock::data
char ** data()
Raw data of the data block pointer (used by compiler)
Definition: VarBlock.h:74
SeExpr2::Expression::_varBlockCreator
const VarBlockCreator * _varBlockCreator
Definition: Expression.h:313
SeExpr2::Expression::prep
void prep() const
Definition: Expression.cpp:204
context
If a scalar is used in a vector context
Definition: userdoc.txt:436
SeExpr2::TypePrintExaminer::reset
virtual void reset()
Definition: Expression.cpp:72
SeExpr2::Expression::syntaxOK
bool syntaxOK() const
Definition: Expression.cpp:174
Expression.h
SeExpr2::Interpreter
Definition: Interpreter.h:40
SeExpr2::LLVMEvaluator::evalStr
const char * evalStr(VarBlock *varBlock)
Definition: Evaluator.h:391
SeExpr2::Expression::debugPrintLLVM
void debugPrintLLVM() const
Definition: Expression.cpp:119
SeExpr2::Expression::UseLLVM
Definition: Expression.h:81
SeExpr2::Interpreter::print
void print(int pc=-1) const
Debug by printing program.
Definition: Interpreter.cpp:69
SeExpr2::Interpreter::addOperand
int addOperand(int param)
! Adds an operand. Note this should be done after doing the addOp!
Definition: Interpreter.h:96
SeExpr2::Expression::usesFunc
bool usesFunc(const std::string &name) const
Definition: Expression.cpp:189
SeExpr2::Walker::walk
void walk(T_NODE *examinee)
Preorder walk.
Definition: ExprWalker.cpp:30
SeExpr2::Expression::isVec
bool isVec() const
Definition: Expression.cpp:294