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 
36 #include <cstdio>
37 #include <typeinfo>
38 #include <ExprWalker.h>
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 " << __VERSION__ << " built " << __DATE__ << " " << __TIME__
49  << std::endl;
50  }
51 #ifdef SEEXPR_ENABLE_LLVM
52  if (char* env = getenv("SE_EXPR_EVAL")) {
53  if (Expression::debugging) std::cerr << "Overriding SeExpr Evaluation Default to be " << env << std::endl;
54  return !strcmp(env, "LLVM") ? Expression::UseLLVM : !strcmp(env, "INTERPRETER") ? Expression::UseInterpreter
56  } else
57  return Expression::UseLLVM;
58 #else
60 #endif
61 }
63 
64 class TypePrintExaminer : public SeExpr2::Examiner<true> {
65  public:
66  virtual bool examine(const SeExpr2::ExprNode* examinee);
67  virtual void reset() {};
68 };
69 
70 bool TypePrintExaminer::examine(const ExprNode* examinee) {
71  const ExprNode* curr = examinee;
72  int depth = 0;
73  char buf[1024];
74  while (curr != 0) {
75  depth++;
76  curr = curr->parent();
77  }
78  sprintf(buf, "%*s", depth * 2, " ");
79  std::cout << buf << "'" << examinee->toString() << "' " << typeid(*examinee).name()
80  << " type=" << examinee->type().toString() << std::endl;
81 
82  return true;
83 };
84 
86  : _wantVec(true), _expression(""), _evaluationStrategy(evaluationStrategy), _context(&Context::global()),
87  _desiredReturnType(ExprType().FP(3).Varying()), _parseTree(0), _isValid(0), _parsed(0), _prepped(0),
88  _interpreter(0), _llvmEvaluator(new LLVMEvaluator()) {
90 }
91 
92 Expression::Expression(const std::string& e,
93  const ExprType& type,
94  EvaluationStrategy evaluationStrategy,
95  const Context& context)
96  : _wantVec(true), _expression(e), _evaluationStrategy(evaluationStrategy), _context(&context),
97  _desiredReturnType(type), _parseTree(0), _isValid(0), _parsed(0), _prepped(0), _interpreter(0),
98  _llvmEvaluator(new LLVMEvaluator()) {
100 }
101 
103  reset();
104  delete _llvmEvaluator;
105 }
106 
108  if (_interpreter) {
109  _interpreter->print();
110  std::cerr << "return slot " << _returnSlot << std::endl;
111  }
112 }
113 
115 
117  if (_parseTree) {
118  // print the parse tree
119  std::cerr << "Parse tree desired type " << _desiredReturnType.toString() << " actual "
120  << _parseTree->type().toString() << std::endl;
121  TypePrintExaminer _examiner;
122  SeExpr2::ConstWalker _walker(&_examiner);
123  _walker.walk(_parseTree);
124  }
125 }
126 
128  delete _llvmEvaluator;
130  delete _parseTree;
131  _parseTree = 0;
133  delete _interpreter;
134  _interpreter = 0;
135  }
136  _isValid = 0;
137  _parsed = 0;
138  _prepped = 0;
139  _parseError = "";
140  _vars.clear();
141  _funcs.clear();
142  //_localVars.clear();
143  _errors.clear();
144  _envBuilder.reset();
146  _comments.clear();
147 }
148 
150  reset();
151  _context = &context;
152 }
153 
155  reset();
156  _desiredReturnType = type;
157 }
158 
160  reset();
161  _varBlockCreator = creator;
162 }
163 
164 void Expression::setExpr(const std::string& e) {
165  if (_expression != "") reset();
166  _expression = e;
167 }
168 
169 bool Expression::syntaxOK() const {
170  parseIfNeeded();
171  return _isValid;
172 }
173 
175  parseIfNeeded();
176  return returnType().isLifetimeConstant();
177 }
178 
179 bool Expression::usesVar(const std::string& name) const {
180  parseIfNeeded();
181  return _vars.find(name) != _vars.end();
182 }
183 
184 bool Expression::usesFunc(const std::string& name) const {
185  parseIfNeeded();
186  return _funcs.find(name) != _funcs.end();
187 }
188 
189 void Expression::parse() const {
190  if (_parsed) return;
191  _parsed = true;
192  int tempStartPos, tempEndPos;
193  ExprParse(_parseTree, _parseError, tempStartPos, tempEndPos, _comments, this, _expression.c_str(), _wantVec);
194  if (!_parseTree) {
195  addError(_parseError, tempStartPos, tempEndPos);
196  }
197 }
198 
199 void Expression::prep() const {
200  if (_prepped) return;
201 #ifdef SEEXPR_PERFORMANCE
202  PrintTiming timer("[ PREP ] v2 prep time: ");
203 #endif
204  _prepped = true;
205  parseIfNeeded();
206 
207  bool error = false;
208 
209  if (!_parseTree) {
210  // parse error
211  error = true;
213  // prep error
214  error = true;
216  // incompatible type error
217  error = true;
218  _parseTree->addError("Expression generated type " + _parseTree->type().toString() +
219  " incompatible with desired type " + _desiredReturnType.toString());
220  } else {
221  _isValid = true;
222 
224  if (debugging) {
226  std::cerr << "Eval strategy is interpreter" << std::endl;
227  }
228  assert(!_interpreter);
231  if (_desiredReturnType.isFP()) {
232  int dimWanted = _desiredReturnType.dim();
233  int dimHave = _parseTree->type().dim();
234  if (dimWanted > dimHave) {
235  _interpreter->addOp(getTemplatizedOp<Promote>(dimWanted));
236  int finalOp = _interpreter->allocFP(dimWanted);
238  _interpreter->addOperand(finalOp);
239  _returnSlot = finalOp;
240  _interpreter->endOp();
241  }
242  }
243  if (debugging) _interpreter->print();
244  } else { // useLLVM
245  if (debugging) {
246  std::cerr << "Eval strategy is llvm" << std::endl;
248  }
250  error=true;
251  }
252  }
253 
254  // TODO: need promote
256  }
257 
258  if (error) {
259  _isValid = false;
260  _returnType = ExprType().Error();
261 
262  // build line lookup table
263  std::vector<int> lines;
264  const char* start = _expression.c_str();
265  const char* p = _expression.c_str();
266  while (*p != 0) {
267  if (*p == '\n') lines.push_back(p - start);
268  p++;
269  }
270  lines.push_back(p - start);
271 
272  std::stringstream sstream;
273  for (unsigned int i = 0; i < _errors.size(); i++) {
274  int* bound = std::lower_bound(&*lines.begin(), &*lines.end(), _errors[i].startPos);
275  int line = bound - &*lines.begin() + 1;
276  int lineStart = line == 1 ? 0 : lines[line-1];
277  int col = _errors[i].startPos - lineStart;
278  sstream << " Line " << line << " Col " << col << _errors[i].error << std::endl;
279  }
280  _parseError = std::string(sstream.str());
281  }
282 
283  if (debugging){
284  std::cerr << "ending with isValid " << _isValid << std::endl;
285  std::cerr << "parse error \n" << parseError()<<std::endl;
286  }
287 }
288 
289 bool Expression::isVec() const {
290  prepIfNeeded();
291  return _isValid ? _parseTree->isVec() : _wantVec;
292 }
293 
295  prepIfNeeded();
296  return _returnType;
297 }
298 
299 const double* Expression::evalFP(VarBlock* varBlock) const {
300  prepIfNeeded();
301  if (_isValid) {
303  _interpreter->eval(varBlock);
304  return &_interpreter->d[_returnSlot];
305  } else { // useLLVM
306  return _llvmEvaluator->evalFP(varBlock);
307  }
308  }
309  static double noCrash[16]={};
310  return noCrash;
311 }
312 
313 void Expression::evalMultiple(VarBlock* varBlock, int outputVarBlockOffset, size_t rangeStart, size_t rangeEnd)
314  const {
315  prepIfNeeded();
316  if (_isValid) {
318  // TODO: need strings to work
319  int dim = _desiredReturnType.dim();
320  // double* iHack=reinterpret_cast<double**>(varBlock->data())[outputVarBlockOffset];
321  double* destBase = reinterpret_cast<double**>(varBlock->data())[outputVarBlockOffset];
322  for (size_t i = rangeStart; i < rangeEnd; i++) {
323  varBlock->indirectIndex = i;
324  const double* f = evalFP(varBlock);
325  for (int k = 0; k < dim; k++) {
326  destBase[dim * i + k] = f[k];
327  }
328  }
329  } else { // useLLVM
330  _llvmEvaluator->evalMultiple(varBlock, outputVarBlockOffset, rangeStart, rangeEnd);
331  }
332  }
333 }
334 
335 const char* Expression::evalStr(VarBlock* varBlock) const {
336  prepIfNeeded();
337  if (_isValid) {
339  _interpreter->eval(varBlock);
340  return _interpreter->s[_returnSlot];
341  } else { // useLLVM
342  _llvmEvaluator->evalStr(varBlock);
343  }
344  }
345  return 0;
346 }
347 
348 } // end namespace SeExpr2/
int allocFP(int n)
! Allocate a floating point set of data of dimension n
Definition: Interpreter.h:104
void prepIfNeeded() const
Definition: Expression.h:274
bool usesVar(const std::string &name) const
Definition: Expression.cpp:179
A thread local evaluation context. Just allocate and fill in with data.
Definition: VarBlock.h:35
EvaluationStrategy
Types of evaluation strategies that are available.
Definition: Expression.h:79
const ExprType & type() const
The type of the node.
Definition: ExprNode.h:145
void setContext(const Context &context)
Definition: Expression.cpp:149
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
int dim() const
Definition: ExprType.h:160
std::vector< std::string > _threadUnsafeFunctionCalls
Definition: Expression.h:303
void addError(const std::string &error, const int startPos, const int endPos) const
Definition: Expression.h:205
void walk(T_NODE *examinee)
Preorder walk.
Definition: ExprWalker.cpp:30
std::vector< char * > s
constant and evaluated pointer data
Definition: Interpreter.h:45
char ** data()
Raw data of the data block pointer (used by compiler)
Definition: VarBlock.h:61
bool isFP() const
Direct is predicate checks.
Definition: ExprType.h:164
void setDesiredReturnType(const ExprType &type)
Definition: Expression.cpp:154
bool usesFunc(const std::string &name) const
Definition: Expression.cpp:184
void print(int pc=-1) const
Debug by printing program.
Definition: Interpreter.cpp:48
std::string toString() const
Stringify the type into a printable string.
Definition: ExprType.h:191
void evalMultiple(VarBlock *varBlock, int outputVarBlockOffset, size_t rangeStart, size_t rangeEnd) const
Evaluate multiple blocks.
Definition: Expression.cpp:313
void debugPrintLLVM() const
Definition: Expression.cpp:114
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)
ExprType _returnType
Definition: Expression.h:254
const std::string & parseError() const
Definition: Expression.h:140
EvaluationStrategy _evaluationStrategy
Definition: Expression.h:259
bool isVec() const
Definition: Expression.cpp:289
virtual ExprType prep(bool dontNeedScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:102
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
void evalMultiple(VarBlock *varBlock, int outputVarBlockOffset, size_t rangeStart, size_t rangeEnd)
Definition: Evaluator.h:357
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
std::set< std::string > _funcs
Definition: Expression.h:297
const Context & context() const
Definition: Expression.h:216
ExprType _desiredReturnType
Definition: Expression.h:266
static bool debugging
Whether to debug expressions.
Definition: Expression.h:86
A class that lets you register for the variables used by one or more expressions. ...
Definition: VarBlock.h:71
void eval(VarBlock *varBlock, bool debug=false)
Evaluate program.
Definition: Interpreter.cpp:27
void debugPrintParseTree() const
Definition: Expression.cpp:116
int addOperand(int param)
! Adds an operand. Note this should be done after doing the addOp!
Definition: Interpreter.h:96
const ExprNode * parent() const
Access parent node - root node has no parent.
Definition: ExprNode.h:112
static const int p[514]
Definition: NoiseTables.h:20
bool isLifetimeConstant() const
validity check: type is not an error
Definition: ExprType.h:183
int addOp(OpF op)
! adds an operator to the program (pointing to the data at the current location)
Definition: Interpreter.h:73
const VarBlockCreator * _varBlockCreator
Definition: Expression.h:313
void reset()
Reset to factory state (one empty environment that is current)
Definition: ExprEnv.h:159
bool syntaxOK() const
Definition: Expression.cpp:169
std::vector< Error > _errors
Definition: Expression.h:288
static bool valuesCompatible(const ExprType &a, const ExprType &b)
Checks if value types are compatible.
Definition: ExprType.h:173
std::vector< double > d
Double data (constants and evaluated)
Definition: Interpreter.h:43
void debugPrintInterpreter() const
Definition: Expression.cpp:107
void endOp(bool execute=true)
Definition: Interpreter.h:83
bool prepLLVM(ExprNode *parseTree, ExprType desiredReturnType)
Definition: Evaluator.h:356
If a scalar is used in a vector context
Definition: userdoc.txt:456
const double * evalFP(VarBlock *varBlock=nullptr) const
Definition: Expression.cpp:299
const char * evalStr(VarBlock *varBlock)
Definition: Evaluator.h:351
const char * evalStr(VarBlock *varBlock=nullptr) const
Definition: Expression.cpp:335
bool isValid() const
Definition: Expression.h:133
std::string _parseError
Definition: Expression.h:285
void prep() const
Definition: Expression.cpp:199
std::set< std::string > _vars
Definition: Expression.h:294
void setVarBlockCreator(const VarBlockCreator *varBlockCreator)
Definition: Expression.cpp:159
int indirectIndex
indirect index to add to pointer based data
Definition: VarBlock.h:58
std::string _expression
Definition: Expression.h:257
void setExpr(const std::string &e)
Definition: Expression.cpp:164
bool isConstant() const
Definition: Expression.cpp:174
ExprVarEnvBuilder _envBuilder
Definition: Expression.h:269
std::vector< std::pair< int, int > > _comments
Definition: Expression.h:291
static Expression::EvaluationStrategy chooseDefaultEvaluationStrategy()
Definition: Expression.cpp:46
void parseIfNeeded() const
Definition: Expression.h:242
bool isVec() const
True if node has a vector result.
Definition: ExprNode.h:99
const ExprType & returnType() const
Definition: Expression.cpp:294
Interpreter * _interpreter
Definition: Expression.h:306
std::string toString() const
Access to original string representation of current expression.
Definition: ExprNode.h:105
virtual bool examine(const SeExpr2::ExprNode *examinee)
Definition: Expression.cpp:70
const double * evalFP(VarBlock *varBlock)
Definition: Evaluator.h:355
static void init()
call to define built-in funcs and load standard plugins
Definition: ExprFunc.cpp:110
static EvaluationStrategy defaultEvaluationStrategy
What evaluation strategy to use by default.
Definition: Expression.h:84
const Context * _context
Definition: Expression.h:262
void parse() const
Definition: Expression.cpp:189
LLVMEvaluator * _llvmEvaluator
Definition: Expression.h:310
Expression(EvaluationStrategy be=Expression::defaultEvaluationStrategy)
Definition: Expression.cpp:85
ExprType & Error()
Mutate this into an error type.
Definition: ExprType.h:102
Platform-specific classes, functions, and includes.
ExprNode * _parseTree
Definition: Expression.h:271