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)
51#else
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
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,
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
168
169void Expression::setExpr(const std::string& e) {
170 if (_expression != "") reset();
171 _expression = e;
172}
173
176 return _isValid;
177}
178
181 return returnType().isLifetimeConstant();
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;
199 if (!_parseTree) {
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;
217 } else if (!_parseTree->prep(_desiredReturnType.isFP(1), _envBuilder).isValid()) {
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 }
236 if (_desiredReturnType.isFP()) {
238 int dimHave = _parseTree->type().dim();
239 if (dimWanted > dimHave) {
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) {
309 return (varBlock && varBlock->threadSafe) ? &(varBlock->d[_returnSlot]) : &_interpreter->d[_returnSlot];
310 } else { // useLLVM
312 }
313 }
314 static double noCrash[16] = {};
315 return noCrash;
316}
317
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
335 }
336 }
337}
338
340 prepIfNeeded();
341 if (_isValid) {
344 return (varBlock && varBlock->threadSafe) ? varBlock->s[_returnSlot] : _interpreter->s[_returnSlot];
345 } else { // useLLVM
347 }
348 }
349 return 0;
350}
351
352} // end namespace SeExpr2/
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 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 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
void reset()
Reset to factory state (one empty environment that is current)
Definition ExprEnv.h:153
void parseIfNeeded() const
Definition Expression.h:242
bool usesVar(const std::string &name) const
const Context & context() const
Definition Expression.h:216
void setDesiredReturnType(const ExprType &type)
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)
std::vector< Error > _errors
Definition Expression.h:288
const char * evalStr(VarBlock *varBlock=nullptr) const
std::set< std::string > _funcs
Definition Expression.h:297
EvaluationStrategy _evaluationStrategy
Definition Expression.h:259
const ExprType & returnType() const
void setExpr(const std::string &e)
void addError(const std::string &error, const int startPos, const int endPos) const
Definition Expression.h:205
LLVMEvaluator * _llvmEvaluator
Definition Expression.h:310
bool usesFunc(const std::string &name) const
std::set< std::string > _vars
Definition Expression.h:294
bool syntaxOK() const
bool isConstant() const
void setVarBlockCreator(const VarBlockCreator *varBlockCreator)
void evalMultiple(VarBlock *varBlock, int outputVarBlockOffset, size_t rangeStart, size_t rangeEnd) const
Evaluate multiple blocks.
const double * evalFP(VarBlock *varBlock=nullptr) const
void debugPrintLLVM() const
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)
ExprType _desiredReturnType
Definition Expression.h:266
static EvaluationStrategy defaultEvaluationStrategy
What evaluation strategy to use by default.
Definition Expression.h:84
void debugPrintInterpreter() const
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
ExprVarEnvBuilder _envBuilder
Definition Expression.h:269
int allocFP(int n)
! Allocate a floating point set of data of dimension n
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.
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.
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)
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
SeExpr2::SPrintFuncX sprintf
static Expression::EvaluationStrategy chooseDefaultEvaluationStrategy()
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