SeExpr
ExprNode.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
18#ifndef MAKEDEPEND
19#include <math.h>
20#include <sstream>
21#include <algorithm>
22#endif
23#include "Vec.h"
24#include "ExprType.h"
25#include "Expression.h"
26#include "ExprEnv.h"
27#include "ExprNode.h"
28#include "ExprFunc.h"
29#include "VarBlock.h"
30#include "StringUtils.h"
31
32// TODO: add and other binary op demote to scalar if wantScalar
33// TODO: logical operations like foo<bar should they do vector returns... right now no... implicit demote
34// TODO: local function evaluation
35// TODO: buildInterpreter for higher level nodes so the return location can be routed back
36// TODO: ExprFuncNode interpreter stuff
37// TODO: check each node for possibility of strings
38
39namespace SeExpr2 {
40
41ExprNode::ExprNode(const Expression* expr) : _expr(expr), _parent(0), _isVec(0) {}
42
43ExprNode::ExprNode(const Expression* expr, const ExprType& type) : _expr(expr), _parent(0), _isVec(0), _type(type) {}
44
45ExprNode::ExprNode(const Expression* expr, ExprNode* a) : _expr(expr), _parent(0), _isVec(0) {
46 _children.reserve(1);
47 addChild(a);
48}
49
51 : _expr(expr), _parent(0), _isVec(0), _type(type) {
52 _children.reserve(1);
53 addChild(a);
54}
55
56ExprNode::ExprNode(const Expression* expr, ExprNode* a, ExprNode* b) : _expr(expr), _parent(0), _isVec(0) {
57 _children.reserve(2);
58 addChild(a);
59 addChild(b);
60}
61
63 : _expr(expr), _parent(0), _isVec(0), _type(type) {
64 _children.reserve(2);
65 addChild(a);
66 addChild(b);
67}
68
69ExprNode::ExprNode(const Expression* expr, ExprNode* a, ExprNode* b, ExprNode* c) : _expr(expr), _parent(0), _isVec(0) {
70 _children.reserve(3);
71 addChild(a);
72 addChild(b);
73 addChild(c);
74}
75
77 : _expr(expr), _parent(0), _isVec(0), _type(type) {
78 _children.reserve(3);
79 addChild(a);
80 addChild(b);
81 addChild(c);
82}
83
85 // delete children
86 std::vector<ExprNode*>::iterator iter;
87 for (iter = _children.begin(); iter != _children.end(); iter++) delete *iter;
88}
89
91 _children.push_back(child);
92 child->_parent = this;
93}
94
96 std::vector<ExprNode*>::iterator iter;
97 for (iter = surrogate->_children.begin(); iter != surrogate->_children.end(); iter++) {
98 addChild(*iter);
99 }
100 surrogate->_children.clear();
101 delete surrogate;
102}
103
104ExprType ExprNode::prep(bool wantScalar, ExprVarEnvBuilder& envBuilder) {
110 bool error = false;
111
112 _maxChildDim = 0;
113 for (int c = 0; c < numChildren(); c++) {
114 error |= !child(c)->prep(false, envBuilder).isValid();
115 int childDim = child(c)->type().isFP() ? child(c)->type().dim() : 0;
116 if (childDim > _maxChildDim) _maxChildDim = childDim;
117 }
118
119 if (error)
120 setType(ExprType().Error());
121 else
123
124 return _type;
125}
126
127ExprType ExprModuleNode::prep(bool wantScalar, ExprVarEnvBuilder& envBuilder) {
128 bool error = false;
129
130 for (int c = 0; c < numChildren(); c++) error |= !child(c)->prep(false, envBuilder).isValid();
131 if (error)
132 setType(ExprType().Error());
133 else
134 setType(child(numChildren() - 1)->type());
135
136 return _type;
137}
138
140 bool error = false;
141
142#if 0 // TODO: implement prototype
143 if (_retTypeSet) checkCondition(returnType().isValid(), "Function has bad return type", error);
144
145 _argTypes.clear();
146 for (int c = 0; c < numChildren(); c++) {
147 ExprType type = child(c)->type();
148 checkCondition(type.isValid(), "Function has a parameter with a bad type", error);
149 _argTypes.push_back(type);
150 ExprLocalVar* localVar = new ExprLocalVar(type);
151 envBuilder.current()->add(((ExprVarNode*)child(c))->name(), localVar);
152 std::cerr << "after create localvar phi " << localVar->getPhi() << std::endl;
153 child(c)->prep(wantScalar, envBuilder);
154 }
155#else
156 checkCondition(false, "Prototypes are currently not supported", error);
157#endif
158 if (error)
159 setType(ExprType().Error());
160 else
161 setType(ExprType().None().Varying());
162
163 return _type;
164}
165
167 ExprNode::addChildren(surrogate);
168
170 for (int i = 0; i < numChildren(); i++) _argTypes.push_back(child(i)->type());
171}
172
174 ExprNode::addChildren(surrogate);
175#if 0
176 ExprNode * child;
178 for(int i = 0; i < numChildren(); i++) {
179 child = this->child(i);
180 type = child->type();
181
182 _argTypes.push_back(type);
183 _env.add(((ExprVarNode*)child)->name(), new ExprLocalVar(type));
184 }
185#endif
186}
187
189 bool error = false;
190
191#if 0 // TODO: no local functions for now
192
193 // prep prototype and check for errors
195 ExprVarEnv functionEnv;
196 functionEnv.resetAndSetParent(&env);
197 if (!prototype->prep(false, functionEnv).isValid()) error = true;
198
199 // decide what return type we want
200 bool returnWantsScalar = false;
201 if (!error && prototype->isReturnTypeSet()) returnWantsScalar = prototype->returnType().isFP(1);
202
203 // prep block and check for errors
204 ExprNode* block = child(1);
205 ExprType blockType = block->prep(returnWantsScalar, functionEnv);
206
207 if (!error && blockType.isValid()) {
208 if (prototype->isReturnTypeSet()) {
209 if (blockType != prototype->returnType()) {
210 checkCondition(false,
211 "In function result of block '" + blockType.toString() +
212 "' does not match given return type " + prototype->returnType().toString(),
213 error);
214 }
215
216 } else
217 prototype->setReturnType(blockType);
218 // register the function in the symbol table
219
220 env.addFunction(prototype->name(), this);
221 } else {
222 checkCondition(false, "Invalid type for blockType is " + blockType.toString(), error);
223 error = true;
224 }
225#else
226 checkCondition(false, "Local functions are currently not supported.", error);
227#endif
228
229 if (error)
230 setType(ExprType().Error());
231 else
232 setType(ExprType().None().Varying());
233
234 return _type;
235}
236
237// TODO: write buildInterpreter for local function node
238ExprType ExprLocalFunctionNode::prep(ExprFuncNode* callerNode, bool scalarWanted, ExprVarEnvBuilder& envBuilder) const {
239#if 0
240 bool error = false;
241 callerNode->checkCondition(callerNode->numChildren() == prototype()->numChildren(),
242 "Incorrect number of arguments to function call",
243 error);
244 for (int i = 0; i < callerNode->numChildren(); i++) {
245 // TODO: is this right?
246 // bool compatible=ExprType::valuesCompatible(callerNode->child(i)->prep(false,env), prototype()->argType(i));
247 if (!callerNode->checkArg(i, prototype()->argType(i), envBuilder)) error = true;
248 // callerNode->child(i)->checkCondition(compatible,"Incorrect type for argument",error);
249 }
250 return error ? ExprType().Error() : prototype()->returnType();
251#else
252 bool error = false;
253 callerNode->checkCondition(false, "Local functions are currently not supported.", error);
254 return ExprType().Error();
255#endif
256}
257
258ExprType ExprBlockNode::prep(bool wantScalar, ExprVarEnvBuilder& envBuilder) {
259 ExprType assignType = child(0)->prep(false, envBuilder);
260 ExprType resultType = child(1)->prep(wantScalar, envBuilder);
261
262 if (!assignType.isValid())
263 setType(ExprType().Error());
264 else
265 setType(resultType);
266
267 return _type;
268}
269
271 ExprType condType, thenType, elseType;
272
273 bool error = false;
274
275 condType = child(0)->prep(true, envBuilder);
276 checkIsFP(condType, error);
277
278 ExprVarEnv* parentEnv = envBuilder.current();
279 ExprVarEnv* thenEnv = envBuilder.createDescendant(parentEnv);
280 ExprVarEnv* elseEnv = envBuilder.createDescendant(parentEnv);
281 envBuilder.setCurrent(thenEnv);
282 thenType = child(1)->prep(false, envBuilder);
283 thenEnv = envBuilder.current();
284 envBuilder.setCurrent(elseEnv);
285 elseType = child(2)->prep(false, envBuilder);
286 elseEnv = envBuilder.current();
287
288 if (!error && thenType.isValid() && elseType.isValid()) {
289 ExprVarEnv* newEnv = envBuilder.createDescendant(parentEnv);
290 _varEnvMergeIndex = newEnv->mergeBranches(condType, *thenEnv, *elseEnv);
291 envBuilder.setCurrent(newEnv);
292 // TODO: aselle insert the phi nodes!
293 } else {
294 envBuilder.setCurrent(parentEnv); // since the conditionals broke don't include them in new environment
295 error = true;
296 }
297 _varEnv = envBuilder.current();
298
299 if (error)
300 setType(ExprType().Error());
301 else
302 setType(ExprType().None().setLifetime(condType, thenType, elseType));
303
304 return _type;
305}
306
307ExprType ExprAssignNode::prep(bool wantScalar, ExprVarEnvBuilder& envBuilder) {
308 _assignedType = child(0)->prep(false, envBuilder);
309
310 std::unique_ptr<ExprLocalVar> localVar(new ExprLocalVar(child(0)->type()));
311 _localVar = localVar.get();
312 envBuilder.current()->add(_name, std::move(localVar));
313 bool error = false;
315 _assignedType.isValid(), std::string("Assignment operation has bad type: ") + _type.toString(), error);
316
317 if (error)
318 setType(ExprType().Error());
319 else
321 return _type;
322}
323
324ExprType ExprVecNode::prep(bool wantScalar, ExprVarEnvBuilder& envBuilder) {
325 bool error = false;
326
327 int max_child_d = 0;
328 for (int c = 0; c < numChildren(); c++) {
329 ExprType childType = child(c)->prep(true, envBuilder);
330 // TODO: add way to tell what element of vector has the type mismatch
331 checkIsFP(childType, error);
332 max_child_d = std::max(max_child_d, childType.dim());
333 }
334
335 if (error)
336 setType(ExprType().Error());
337 else
339 return _type;
340}
341
343 if (const ExprNumNode* f = dynamic_cast<const ExprNumNode*>(child(0))) {
344 double first = f->value();
345 if (const ExprNumNode* s = dynamic_cast<const ExprNumNode*>(child(1))) {
346 double second = s->value();
347 if (const ExprNumNode* t = dynamic_cast<const ExprNumNode*>(child(2))) {
348 double third = t->value();
349 return Vec3d(first, second, third);
350 };
351 };
352 };
353
354 return Vec3d(0.0);
355};
356
357ExprType ExprUnaryOpNode::prep(bool wantScalar, ExprVarEnvBuilder& envBuilder) {
358 bool error = false;
359
360 // TODO: aselle may want to implicitly demote to FP[1] if wantScalar is true!
361 ExprType childType = child(0)->prep(wantScalar, envBuilder);
362 checkIsFP(childType, error);
363 if (error)
364 setType(ExprType().Error());
365 else
366 setType(childType);
367 return _type;
368}
369
370ExprType ExprCondNode::prep(bool wantScalar, ExprVarEnvBuilder& envBuilder) {
371 // TODO: determine if extra environments are necessary, currently not included
372 ExprType condType, thenType, elseType;
373
374 bool error = false;
375
376 condType = child(0)->prep(true, envBuilder);
377
378 checkIsFP(condType, error);
379
380 thenType = child(1)->prep(wantScalar, envBuilder);
381 elseType = child(2)->prep(wantScalar, envBuilder);
382
383 checkIsValue(thenType, error);
384 checkIsValue(elseType, error);
385 checkCondition(ExprType::valuesCompatible(thenType, elseType), "Types of conditional are not compatible", error);
386
387 if (error)
388 setType(ExprType().Error());
389 else {
390 if (thenType.isString())
391 setType(thenType);
392 else
393 setType(thenType.isFP(1) ? elseType : thenType);
394 _type.setLifetime(condType, thenType, elseType);
395 }
396
397 return _type;
398}
399
401 // TODO: double-check order of evaluation - order MAY effect environment evaluation (probably not, though)
402 ExprType vecType, scriptType;
403
404 bool error = false;
405
406 vecType = child(0)->prep(false, envBuilder); // want scalar is false because we aren't just doing foo[0]
407 checkIsFP(vecType, error);
408
409 scriptType = child(1)->prep(true, envBuilder);
410 checkIsFP(scriptType, error);
411
412 if (error)
413 setType(ExprType().Error());
414 else
415 setType(ExprType().FP(1).setLifetime(vecType, scriptType));
416
417 return _type;
418}
419
421 // TODO: double-check order of evaluation - order MAY effect environment evaluation (probably not, though)
422 ExprType firstType, secondType;
423
424 bool error = false;
425
426 firstType = child(0)->prep(false, envBuilder);
427 checkIsValue(firstType, error);
428 secondType = child(1)->prep(false, envBuilder);
429 checkIsValue(secondType, error);
430
431 if (firstType.isValid() && secondType.isValid()) checkTypesCompatible(firstType, secondType, error);
432
433 if (error)
434 setType(ExprType().Error());
435 else
436 setType(ExprType().FP(1).setLifetime(firstType, secondType));
437
438 return _type;
439}
440
441ExprType ExprCompareNode::prep(bool wantScalar, ExprVarEnvBuilder& envBuilder) {
442 // TODO: assume we want scalar
443 // TODO: double-check order of evaluation - order MAY effect environment evaluation (probably not, though)
444 ExprType firstType, secondType;
445
446 bool error = false;
447
448 firstType = child(0)->prep(true, envBuilder);
449 checkIsFP(firstType, error);
450 secondType = child(1)->prep(true, envBuilder);
451 checkIsFP(secondType, error);
452
453 if (firstType.isValid() && secondType.isValid()) checkTypesCompatible(firstType, secondType, error);
454
455 if (error)
456 setType(ExprType().Error());
457 else
458 setType(ExprType().FP(1).setLifetime(firstType, secondType));
459
460 return _type;
461}
462
463ExprType ExprBinaryOpNode::prep(bool wantScalar, ExprVarEnvBuilder& envBuilder) {
464 // TODO: aselle this probably should set the type to be FP1 if wantScalar is true!
465 // TODO: double-check order of evaluation - order MAY effect environment evaluation (probably not, though)
466 ExprType firstType, secondType;
467
468 bool error = false;
469
470 // prep children and get their types
471 firstType = child(0)->prep(false, envBuilder);
472 secondType = child(1)->prep(false, envBuilder);
473
474 // check compatibility and get return type
475 // TODO: handle string + fp or fp + string, the same as in Python or equivalent
476 checkTypesCompatible(firstType, secondType, error);
477 if (error)
478 setType(ExprType().Error());
479 else
480 setType((firstType.isFP(1) ? secondType : firstType).setLifetime(firstType, secondType));
481
482 return _type;
483}
484
485ExprType ExprVarNode::prep(bool wantScalar, ExprVarEnvBuilder& envBuilder) {
486 // ask expression to resolve var
487 bool error = false;
488 if ((_localVar = envBuilder.current()->find(name()))) {
489 if (_localVar->type().isError()) {
491 if (ExprLocalVarPhi* phi = dynamic_cast<ExprLocalVarPhi*>(_localVar)) {
492 if (!phi->_thenVar->type().isError() && !phi->_elseVar->type().isError()) {
493 addError(std::string("Variable ") + name() + " defined in conditionals inconsistently.");
494 }
495 }
496 }
498 return _type;
499 } else {
500 // user defined external variable
502 if (!_var) {
503 if (const VarBlockCreator* creator = _expr->varBlockCreator()) {
504 // data block defined external var
505 _var = creator->resolveVar(name());
506 }
507 }
508 if (_var) {
509 _expr->addVar(name()); // register used variable so _expr->usedVar() works
510 setType(_var->type());
511 return _type;
512 }
513 }
514 // If we get here we do not have a variable!
515 checkCondition(_var || _localVar, std::string("No variable named ''") + name() + "'", error);
516 setType(ExprType().Error());
517 return _type;
518}
519
520ExprType ExprNumNode::prep(bool wantScalar, ExprVarEnvBuilder& envBuilder) {
521 _type = ExprType().FP(1).Constant();
522 return _type;
523}
524
525ExprStrNode::ExprStrNode(const Expression* expr, const char* str) : ExprNode(expr), _str(unescapeString(str)) {
526}
527
528ExprType ExprStrNode::prep(bool wantScalar, ExprVarEnvBuilder& envBuilder) {
530 return _type;
531}
532
533ExprType ExprFuncNode::prep(bool wantScalar, ExprVarEnvBuilder& envBuilder) {
534 bool error = false;
535
536 int nargs = numChildren();
537 _promote.resize(nargs, 0);
538
539 // find function using per-expression callback and then global table
540 // TODO: put lookup of local functions here
541 _func = 0;
542 if (ExprLocalFunctionNode* localFunction = envBuilder.current()->findFunction(_name)) {
543 _localFunc = localFunction;
544 setTypeWithChildLife(localFunction->prep(this, wantScalar, envBuilder));
545 // TODO: we need to type check arguments here
546 } else {
549
550 // check that function exists and that the function has the right number of arguments
551 if (checkCondition(_func, "Function " + _name + " has no definition", error) &&
552 checkCondition(nargs >= _func->minArgs(), "Too few args for function " + _name, error) &&
554 nargs <= _func->maxArgs() || _func->maxArgs() < 0, "Too many args for function " + _name, error)) {
555
556 const ExprFuncX* funcx = _func->funcx();
557 ExprType type = funcx->prep(this, wantScalar, envBuilder);
559 } else { // didn't match num args or function not found
560 ExprNode::prep(false, envBuilder); // prep arguments anyways to catch as many errors as possible!
562 }
563 }
564
565 return _type;
566}
567
569 if (_localFunc)
570 return _localFunc->buildInterpreterForCall(this, interpreter);
571 else if (_func)
572 return _func->funcx()->buildInterpreter(this, interpreter);
573
574 assert(false);
575 return 0;
576}
577
578bool ExprFuncNode::checkArg(int arg, ExprType type, ExprVarEnvBuilder& envBuilder) {
579 ExprType childType = child(arg)->prep(type.isFP(1), envBuilder);
580 _promote[arg] = 0;
581 if (ExprType::valuesCompatible(type, childType) && type.isLifeCompatible(childType)) {
582 if (type.isFP() && type.dim() > childType.dim()) {
583 _promote[arg] = type.dim();
584 }
585 return true;
586 }
587 child(arg)->addError("Expected " + type.toString() + " for argument, got " + childType.toString());
588 return false;
589}
590}
std::string unescapeString(const std::string &string)
Definition: StringUtils.h:24
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:307
ExprLocalVar * _localVar
Definition: ExprNode.h:375
const ExprLocalVar * localVar() const
Definition: ExprNode.h:371
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:463
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:258
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:420
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:441
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:370
Node that calls a function.
Definition: ExprNode.h:517
std::string _name
Definition: ExprNode.h:596
const ExprLocalFunctionNode * _localFunc
Definition: ExprNode.h:598
std::vector< int > _promote
Definition: ExprNode.h:602
const ExprFunc * _func
Definition: ExprNode.h:597
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:533
bool checkArg(int argIndex, ExprType type, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:578
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
Definition: ExprNode.cpp:568
Extension function spec, used for complicated argument custom functions.
Definition: ExprFuncX.h:35
virtual ExprType prep(ExprFuncNode *node, bool scalarWanted, ExprVarEnvBuilder &env) const =0
virtual int buildInterpreter(const ExprFuncNode *node, Interpreter *interpreter) const =0
Build an interpreter to evaluate the expression.
int maxArgs() const
return the maximum number of acceptable arguments
Definition: ExprFunc.h:123
const ExprFuncX * funcx() const
return pointer to the funcx
Definition: ExprFunc.h:125
static const ExprFunc * lookup(const std::string &name)
Lookup a builtin function by name.
Definition: ExprFunc.cpp:130
int minArgs() const
return the minimum number of acceptable arguments
Definition: ExprFunc.h:121
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:270
Node that contains local function.
Definition: ExprNode.h:307
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Preps the definition of this site.
Definition: ExprNode.cpp:188
const ExprPrototypeNode * prototype() const
TODO: Accessor for prototype (probably not needed when we use prep right)
Definition: ExprNode.h:317
int buildInterpreterForCall(const ExprFuncNode *callerNode, Interpreter *interpreter) const
Build interpreter if we are called.
ExprLocalVar join (merge) references. Remembers which variables are possible assigners to this.
Definition: ExprEnv.h:67
ExprLocalVar reference, all local variables in seexpr are subclasses of this or this itself.
Definition: ExprEnv.h:37
const ExprLocalVar * getPhi() const
get the primary representative phi node (i.e. the global parent of a dependent phi node)
Definition: ExprEnv.h:49
ExprType type() const
returns type of the variable
Definition: ExprEnv.h:51
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:127
void setTypeWithChildLife(const ExprType &t)
Set's the type to the argument but uses the children to determine lifetime.
Definition: ExprNode.h:176
std::vector< ExprNode * > _children
List of children.
Definition: ExprNode.h:231
bool checkIsValue(const ExprType &type, bool &error)
Checks if the type is a value (i.e. string or float[d])
Definition: ExprNode.h:198
void addChildren(ExprNode *surrogate)
Transfer children from surrogate parent (for parser use only)
Definition: ExprNode.cpp:95
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
void addChild(ExprNode *child)
Add a child to the child list (for parser use only)
Definition: ExprNode.cpp:90
void setType(const ExprType &t)
Set type of parameter.
Definition: ExprNode.h:172
int numChildren() const
Number of children.
Definition: ExprNode.h:114
ExprNode * _parent
Parent node (null if this the the root)
Definition: ExprNode.h:228
bool checkTypesCompatible(const ExprType &first, const ExprType &second, bool &error)
types match (true if they do)
Definition: ExprNode.h:215
ExprNode(const Expression *expr)
Definition: ExprNode.cpp:41
const ExprNode * child(size_t i) const
Get 0 indexed child.
Definition: ExprNode.h:117
ExprType _type
Definition: ExprNode.h:237
const ExprType & type() const
The type of the node.
Definition: ExprNode.h:145
const Expression * _expr
Owning expression (node can't modify)
Definition: ExprNode.h:225
bool checkIsFP(const ExprType &type, bool &error)
Checks if the type is a float[d] for any d.
Definition: ExprNode.h:202
bool checkCondition(bool check, const std::string &message, bool &error)
Checks the boolean value and records an error string with node if it is false.
Definition: ExprNode.h:190
virtual ~ExprNode()
Definition: ExprNode.cpp:84
virtual ExprType prep(bool dontNeedScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:104
Node that stores a numeric constant.
Definition: ExprNode.h:486
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:520
Node that contains prototype of function.
Definition: ExprNode.h:255
ExprType returnType() const
Definition: ExprNode.h:277
void addArgs(ExprNode *surrogate)
Definition: ExprNode.cpp:173
void addArgTypes(ExprNode *surrogate)
Definition: ExprNode.cpp:166
void setReturnType(const ExprType &type)
Definition: ExprNode.h:268
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:139
bool isReturnTypeSet() const
Definition: ExprNode.h:273
std::vector< ExprType > _argTypes
Definition: ExprNode.h:300
const std::string & name() const
Definition: ExprNode.h:288
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:528
ExprStrNode(const Expression *expr, const char *str)
Definition: ExprNode.cpp:525
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:400
static bool valuesCompatible(const ExprType &a, const ExprType &b)
Checks if value types are compatible.
Definition: ExprType.h:173
ExprType & FP(int d)
Mutate this into a floating point type of dimension d.
Definition: ExprType.h:90
std::string toString() const
Stringify the type into a printable string.
Definition: ExprType.h:191
bool isString() const
Definition: ExprType.h:169
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 & String()
Mutate this into a string type.
Definition: ExprType.h:96
ExprType & setLifetime(const ExprType &a)
Assign the lifetime from type a to be my type.
Definition: ExprType.h:136
bool isLifeCompatible(const ExprType &o) const
Definition: ExprType.h:188
ExprType & Error()
Mutate this into an error type.
Definition: ExprType.h:102
ExprType & Constant()
Mutate this into a constant lifetime.
Definition: ExprType.h:112
bool isError() const
Definition: ExprType.h:168
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:357
Variable scope builder is used by the type checking and code gen to track visiblity of variables and ...
Definition: ExprEnv.h:148
void setCurrent(ExprVarEnv *env)
Set a new current variable scope.
Definition: ExprEnv.h:161
ExprVarEnv * current()
Return the current variable scope.
Definition: ExprEnv.h:159
ExprVarEnv * createDescendant(ExprVarEnv *parent)
Create a descendant scope from the provided parent, does not clobber current.
Definition: ExprEnv.h:163
Variable scope for tracking variable lookup.
Definition: ExprEnv.h:94
void add(const std::string &name, std::unique_ptr< ExprLocalVar > var)
Add a variable refernece.
Definition: ExprEnv.cpp:71
ExprLocalVar * find(const std::string &name)
Find a variable name by name (recursive to parents)
Definition: ExprEnv.cpp:29
void resetAndSetParent(ExprVarEnv *parent)
Resets the scope (deletes all variables) and sets parent.
Definition: ExprEnv.cpp:27
ExprLocalFunctionNode * findFunction(const std::string &name)
Find a function by name (recursive to parents)
Definition: ExprEnv.cpp:39
size_t mergeBranches(const ExprType &type, ExprVarEnv &env1, ExprVarEnv &env2)
Add all variables into scope by name, but modify their lifetimes to the given type's lifetime.
Definition: ExprEnv.cpp:81
Node that references a variable.
Definition: ExprNode.h:465
ExprLocalVar * _localVar
Definition: ExprNode.h:481
ExprVarRef * _var
Definition: ExprNode.h:482
const char * name() const
Definition: ExprNode.h:475
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:485
virtual ExprType type() const
returns (current) type
Definition: Expression.h:59
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:324
Vec3d value() const
Definition: ExprNode.cpp:342
main expression class
Definition: Expression.h:76
virtual ExprVarRef * resolveVar(const std::string &name) const
Definition: Expression.h:199
const VarBlockCreator * varBlockCreator() const
Definition: Expression.h:231
virtual ExprFunc * resolveFunc(const std::string &name) const
Definition: Expression.h:202
void addVar(const char *n) const
add local variable (this is for internal use)
Definition: Expression.h:318
A class that lets you register for the variables used by one or more expressions.
Definition: VarBlock.h:84
Vec< double, 3, false > Vec3d
Definition: Vec.h:384
</pre >< h3 > Binding our variable reference</h3 > If we now tried to use the variable would still not be found by our expressions To make it bindable we need to override the resolveVar() function as follows</pre >< h3 > Variable setting</h3 > Next we need to make a way of setting the variable As the controlling code will use the expression it will repeatedly alternate between setting the independent variables that are used and calling evaluate(). What it has to do depends very much on the application. In this case we only need to set the independent variable x as</pre >< h2 > Evaluating expressions</h2 > Evaluating an expression is pretty easy But before we can do that we need to make an instance< pre > GrapherExpr expr("x+x^2")
</pre > there might be errors in the expression you must check with isValid() before you can evaluate. Then you can print a parse error as well< pre > if(!expr.isValid())
Definition: tutorial.txt:177
Between a and b
Definition: userdoc.txt:180
Defined as a *alpha b *alpha< br ></div >< br > float< b > float a
Definition: userdoc.txt:174
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