1 // astexpression.h
2 // this file is part of Context Free
3 // ---------------------
4 // Copyright (C) 2011-2014 John Horigan - john@glyphic.com
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 //
20 // John Horigan can be contacted at john@glyphic.com or at
21 // John Horigan, 1209 Villa St., Mountain View, CA 94041-1123, USA
22 //
23 //
24 
25 
26 #ifndef INCLUDE_ASTEXPRESSION_H
27 #define INCLUDE_ASTEXPRESSION_H
28 
29 #include "ast.h"
30 #include "location.hh"
31 #include "cfdg.h"
32 #include "shape.h"
33 #include <string>
34 #include <cmath>
35 #include <limits>
36 #include "Rand64.h"
37 #include <map>
38 #include <initializer_list>
39 #include <cstddef>
40 
41 class RendererAST;
42 class Builder;
43 
44 #include "json_fwd.hpp"
45 using json = nlohmann::json;
46 
47 namespace agg {
48     void to_json(json& j, const trans_affine& m);
49     void to_json(json& j, const trans_affine_1D& m);
50     void to_json(json& j, const trans_affine_time& m);
51 };
52 
53 void to_json(json& j, const HSBColor& m);
54 
55 void to_json(json& j, const Rand64& m);
56 
57 void to_json(json& j, const Modification& m);
58 
59 void to_json(json& j, const StackRule& r);
60 
61 class json_string {
62 public:
63     json_string() = default;
json_string(const char * str)64     json_string(const char* str) : mSep(str) {}
65     json_string& operator=(const char* str) {
66         mString = str;
67         return *this;
68     }
69     json_string& operator+=(const char* str) {
70         if (!mString.empty())
71             mString += mSep;
72         mString += str;
73         return *this;
74     }
75     json_string& operator+=(const std::string& str) {
76         if (!mString.empty())
77             mString += mSep;
78         mString += str;
79         return *this;
80     }
get()81     const std::string& get() const {
82         return mString;
83     }
84 private:
85     std::string mString;
86     std::string mSep = "+";
87 };
88 
89 class json_float {
90 public:
91     json_float() = default;
json_float(double v)92     json_float(double v) : value(v) {}
93     double value = 0.0;
94 };
95 
96 void to_json(json& j, json_float f);
97 void from_json(const json& j, json_float& f);
98 
99 namespace AST {
100 
101     class ASTdefine;
102     class ASTrepContainer;
103     class ASTexpression;
104 
105     struct ASTexp_iter {
106         using size_type = std::size_t;
107         using difference_type = std::ptrdiff_t;
108         using value_type = const ASTexpression;
109         using reference = value_type&;
110         using pointer = value_type*;
111         using iterator_category = std::random_access_iterator_tag;
112 
113         const ASTexpression*    e;
114         std::size_t             i;
115         ~ASTexp_iter() = default;
116         ASTexp_iter& operator=(const ASTexp_iter&) = default;
117         ASTexp_iter& operator++() {++i; return *this;}
118         ASTexp_iter  operator++(int) {auto temp = *this; ++i; return temp;}
119         ASTexp_iter& operator--() {--i; return *this;}
120         ASTexp_iter  operator--(int) {auto temp = *this; --i; return temp;}
121         reference operator*() const;
122         pointer operator->() const;
123         friend bool operator==(const ASTexp_iter& l, const ASTexp_iter& r) noexcept;
124         friend bool operator!=(const ASTexp_iter& l, const ASTexp_iter& r) noexcept;
125         friend bool operator<(const ASTexp_iter& l, const ASTexp_iter& r) noexcept;
126         friend bool operator>(const ASTexp_iter& l, const ASTexp_iter& r) noexcept;
127         friend bool operator<=(const ASTexp_iter& l, const ASTexp_iter& r) noexcept;
128         friend bool operator>=(const ASTexp_iter& l, const ASTexp_iter& r) noexcept;
129 
130         ASTexp_iter& operator+=(size_type j) {i += j; return *this;}
131         friend ASTexp_iter operator+(const ASTexp_iter&, size_type j);
132         friend ASTexp_iter operator+(size_type j, const ASTexp_iter&);
133         ASTexp_iter& operator-=(size_type j) {i -= j; return *this;}
134         friend ASTexp_iter operator-(const ASTexp_iter&, size_type j);
135         friend difference_type operator-(const ASTexp_iter&, const ASTexp_iter&);
136 
137         reference operator[](size_type) const;
138     };
139 
140     inline bool operator==(const ASTexp_iter& l, const ASTexp_iter& r) noexcept {return l.i == r.i;}
141     inline bool operator!=(const ASTexp_iter& l, const ASTexp_iter& r) noexcept {return l.i != r.i;}
142     inline bool operator<(const ASTexp_iter& l, const ASTexp_iter& r) noexcept {return l.i < r.i;}
143     inline bool operator>(const ASTexp_iter& l, const ASTexp_iter& r) noexcept {return l.i > r.i;}
144     inline bool operator<=(const ASTexp_iter& l, const ASTexp_iter& r) noexcept {return l.i <= r.i;}
145     inline bool operator>=(const ASTexp_iter& l, const ASTexp_iter& r) noexcept {return l.i >= r.i;}
146 
147     inline ASTexp_iter operator+(const ASTexp_iter& iter, ASTexp_iter::size_type j)
148     {auto temp = iter; temp.i += j; return temp;}
149     inline ASTexp_iter operator+(ASTexp_iter::size_type j, const ASTexp_iter& iter)
150     {auto temp = iter; temp.i += j; return temp;}
151     inline ASTexp_iter operator-(const ASTexp_iter& iter, ASTexp_iter::size_type j)
152     {auto temp = iter; temp.i -= j; return temp;}
153     inline ASTexp_iter::difference_type operator-(const ASTexp_iter& l, const ASTexp_iter& r)
154     {return l.i - r.i;}
155 
156     class ASTexpression {
157     public:
158         bool isConstant;
159         bool isNatural;
160         Locality_t mLocality;
161         expType mType;
162         yy::location where;
163 
ASTexpression(const yy::location & loc)164         ASTexpression(const yy::location& loc) : isConstant(false), isNatural(false),
165         mLocality(UnknownLocal), mType(NoType), where(loc) {};
166         ASTexpression(const yy::location& loc, bool c, bool n, expType t = NoType)
isConstant(c)167         : isConstant(c), isNatural(n), mLocality(UnknownLocal), mType(t), where(loc) {};
168         virtual ~ASTexpression() = default;
169         virtual int evaluate(double* = nullptr, int = 0, RendererAST* = nullptr) const
170         { return 0; }
evaluate(Modification &,bool,RendererAST *)171         virtual void evaluate(Modification&, bool, RendererAST*) const
172         { CfdgError::Error(where, "Cannot convert this expression into an adjustment"); }
173         virtual param_ptr evalArgs(RendererAST* = nullptr, const StackRule* = nullptr) const
174         { CfdgError::Error(where, "Cannot convert this expression into a shape"); return nullptr; }
entropy(std::string &)175         virtual void entropy(std::string&) const {};
simplify(Builder *)176         virtual ASTexpression* simplify(Builder*) { return nullptr; }
177 
178         virtual const ASTexpression* getChild(std::size_t i) const;
size()179         virtual std::size_t size() const { return 1; }
180         virtual ASTexpression* append(ASTexpression* sib);
compile(CompilePhase,Builder *)181         virtual ASTexpression* compile(CompilePhase, Builder*) { return nullptr; }
182         // Always returns nullptr except during type check in the following cases:
183         // * An ASTvariable bound to a constant returns a copy of the constant
184         // * An ASTvariable bound to a rule spec returns an ASTruleSpec that
185         //   acts as a stack variable
186         // * A shape spec that was parsed as an ASTuserFunc because of grammar
187         //   ambiguity will return the correct ASTruleSpec
188         //
189         // It is safe to ignore the return value if you can guarantee that none
190         // of these conditions is possible. Otherwise you must replace the object
191         // with the returned object. Using the original object after type check
192         // will fail.
193         static ASTexpression* Append(ASTexpression* l, ASTexpression* r);
194         virtual void to_json(json& j) const;
begin()195         ASTexp_iter begin() noexcept { return ASTexp_iter{this, 0};}
begin()196         ASTexp_iter begin() const noexcept {return ASTexp_iter{this, 0};}
end()197         ASTexp_iter end() noexcept {return ASTexp_iter{this, size()};}
end()198         ASTexp_iter end() const noexcept {return ASTexp_iter{this, size()};}
199     };
200 
201     inline ASTexp_iter::reference ASTexp_iter::operator*() const
202     {return *e->getChild(i);}
203     inline ASTexp_iter::pointer ASTexp_iter::operator->() const
204     {return e->getChild(i);}
205     inline ASTexp_iter::reference ASTexp_iter::operator[](ASTexp_iter::size_type j) const
206     {return *e->getChild(i+j);}
207 
208     void to_json(json& j, const ASTexpression& e);
209     void args_to_json(json& j, const ASTexpression& e);
210 
211     class ASTfunction final : public ASTexpression {
212     public:
213         enum FuncType { NotAFunction,
214             Cos, Sin, Tan, Cot, Acos, Asin, Atan, Acot,
215             Cosh, Sinh, Tanh, Acosh, Asinh, Atanh, Log, Log10,
216             Sqrt, Exp, Abs, Floor, Ceiling, Infinity, Factorial, Sg, IsNatural,
217             BitNot, BitOr, BitAnd, BitXOR, BitLeft, BitRight,
218             Atan2, Mod, Divides, Div,
219             Dot, Cross, Hsb2Rgb, Rgb2Hsb, Vec,
220             Min, Max, Ftime, Frame,
221             Rand_Static, Rand, RandOp, Rand2, RandExponential, RandGamma, RandWeibull,
222             RandExtremeValue, RandNormal, RandLogNormal, RandChiSquared,
223             RandCauchy, RandFisherF, RandStudentT,
224             RandInt, RandBernoulli, RandBinomial, RandNegBinomial, RandPoisson,
225             RandDiscrete, RandGeometric
226         };
227         static FuncType GetFuncType(const std::string& func);
228         static const std::string& GetFuncName(ASTfunction::FuncType t);
229         static bool RandStaticIsConst;      // hideous hack for JSON
230         FuncType functype;
231         exp_ptr arguments;
232         double random;
233         ASTfunction() = delete;
234         ASTfunction(const std::string& func, exp_ptr args, Rand64& r,
235                     const yy::location& nameLoc, const yy::location& argsLoc,
236                     Builder* b);
237         ~ASTfunction() final = default;
238         int evaluate(double* dest = nullptr, int size = 0, RendererAST* rti = nullptr) const final;
239         void entropy(std::string& e) const final;
240         ASTexpression* compile(CompilePhase ph, Builder* b) final;
241         ASTexpression* simplify(Builder* b) final;
242         void to_json(json& j) const final;
243     };
244     class ASTselect final : public ASTexpression {
245         enum consts_t: std::size_t { NotCached = static_cast<std::size_t>(-1) };
246     public:
247         int              tupleSize;
248         std::size_t      indexCache;
249         std::string      ent;
250         ASTexpArray      arguments;
251         exp_ptr          selector;
252         bool             ifSelect;
253 
254         ASTselect(exp_ptr args, const yy::location& loc, bool asIf, Builder* b);
255         ~ASTselect() final;
256         int evaluate(double* dest = nullptr, int size = 0, RendererAST* rti = nullptr) const final;
257         void evaluate(Modification& m, bool shapeDest, RendererAST* r) const final;
258         param_ptr evalArgs(RendererAST* rti = nullptr, const StackRule* parent = nullptr) const final;
259         void entropy(std::string& e) const final;
260         ASTexpression* simplify(Builder* b) final;
261         ASTexpression* compile(CompilePhase ph, Builder* b) final;
262         void to_json(json& j) const final;
263     private:
264         //ASTselect(const yy::location& loc)
265         //: ASTexpression(loc), tupleSize(-1), indexCache(0) {}
266         std::size_t getIndex(RendererAST* rti = nullptr) const;
267     };
268     class ASTruleSpecifier : public ASTexpression {
269     public:
270         enum ArgSource {
271             NoArgs,             // shapeType has no arguments
272             DynamicArgs,        // shapeType has non-constant arguments
273             StackArgs,          // not shapeType, StackRule* pointer to shape
274             SimpleArgs,         // shapeType has constant arguments
275             ParentArgs,         // reusing parent args, child shape may be different
276             SimpleParentArgs,   // reusing shape args, child shape same as parent
277             ShapeArgs           // not shapeType, evalArgs arguments (non-constant) to get shape
278         };
279         int shapeType;
280         int argSize;
281         std::string entropyVal;
282         ArgSource argSource;
283         exp_ptr arguments;
284         param_ptr simpleRule;
285         int mStackIndex;
286         const ASTparameters* typeSignature;
287         const ASTparameters* parentSignature;
288         ASTparameter bound;
289 
290         ASTruleSpecifier(int t, const std::string& name, exp_ptr args, const yy::location& loc,
291                          const ASTparameters* parent);
292         ASTruleSpecifier(int t, const std::string& name, const yy::location& loc);
293         ASTruleSpecifier(exp_ptr args, const yy::location& loc);
294         ASTruleSpecifier(ruleSpec_ptr r) noexcept;
295         ASTruleSpecifier(const ASTruleSpecifier&) = delete;
296         ASTruleSpecifier& operator=(const ASTruleSpecifier&) = delete;
ASTruleSpecifier()297         explicit ASTruleSpecifier()
298         :   ASTexpression(CfdgError::Default, false, false, RuleType), shapeType(-1),
299             argSize(0), argSource(NoArgs), arguments(nullptr),
300             simpleRule(nullptr), mStackIndex(0), typeSignature(nullptr),
301             parentSignature(nullptr) {};
302         ~ASTruleSpecifier() override;
303         int evaluate(double* dest = nullptr, int size = 0, RendererAST* rti = nullptr) const override;
304         param_ptr evalArgs(RendererAST* = nullptr, const StackRule* sr = nullptr) const override;
305         void entropy(std::string& e) const override;
306         ASTexpression* simplify(Builder* b) override;
307         ASTexpression* compile(CompilePhase ph, Builder* b) override;
308         void grab(const ASTruleSpecifier* src);
309         void to_json(json& j) const override;
310     };
311     class ASTstartSpecifier final : public ASTruleSpecifier {
312     public:
313         mod_ptr mModification;
ASTstartSpecifier(int t,const std::string & name,exp_ptr args,const yy::location & loc,mod_ptr mod)314         ASTstartSpecifier(int t, const std::string& name, exp_ptr args,
315                           const yy::location& loc, mod_ptr mod)
316         : ASTruleSpecifier(t, name, std::move(args), loc, nullptr),
317           mModification(std::move(mod)) { };
ASTstartSpecifier(int nameIndex,const std::string & name,const yy::location & loc,mod_ptr mod)318         ASTstartSpecifier(int nameIndex, const std::string& name,
319                           const yy::location& loc, mod_ptr mod)
320         : ASTruleSpecifier(nameIndex, name, loc), mModification(std::move(mod)) { };
ASTstartSpecifier(exp_ptr args,const yy::location & loc,mod_ptr mod)321         ASTstartSpecifier(exp_ptr args, const yy::location& loc, mod_ptr mod)
322         : ASTruleSpecifier(std::move(args), loc), mModification(std::move(mod)) { };
ASTstartSpecifier(ruleSpec_ptr r,mod_ptr m)323         ASTstartSpecifier(ruleSpec_ptr r, mod_ptr m) noexcept
324         : ASTruleSpecifier(std::move(r)), mModification(std::move(m)) { };
325         void entropy(std::string& e) const final;
326         ASTexpression* simplify(Builder* b) final;
327         ASTexpression* compile(CompilePhase ph, Builder* b) final;
328         void to_json(json& j) const final;
329     };
330     class ASTcons final : public ASTexpression {
331     public:
332         ASTexpArray children;
333         ASTcons() = delete;
334         ASTcons(exp_list kids);
335         ~ASTcons() final;
336         int evaluate(double* dest = nullptr, int size = 0, RendererAST* rti = nullptr) const final;
337         void evaluate(Modification& m, bool shapeDest, RendererAST* r) const final;
338         void entropy(std::string& e) const final;
339         ASTexpression* simplify(Builder* b) final;
340         ASTexpression* compile(CompilePhase ph, Builder* b) final;
341 
342         const ASTexpression* getChild(std::size_t i) const final;
size()343         std::size_t size() const final { return children.size(); }
344         ASTexpression* append(ASTexpression* sib) final;
345         void to_json(json& j) const final;
346     };
347     class ASTreal final : public ASTexpression {
348     public:
349         double value;
350         std::string text;
351         ASTreal() = delete;
352         ASTreal(const std::string& t, const yy::location& loc, bool negative = false)
ASTexpression(loc,true,false,NumericType)353         : ASTexpression(loc, true, false, NumericType), text(t)
354         {
355             if (negative) text.insert(0, 1, '-');
356             value = CFatof(text.c_str());
357             isNatural = std::floor(value) == value && value >= 0.0 && value < 9007199254740992.;
358             mLocality = PureLocal;
359         };
ASTreal(double v,const yy::location & loc)360         ASTreal(double v, const yy::location& loc)
361         : ASTexpression(loc, true,
362                         std::floor(v) == v && v >= 0.0 && v < 9007199254740992.,
363                         NumericType), value(v) { mLocality = PureLocal; };
364         ~ASTreal() final = default;
365         int evaluate(double* dest = nullptr, int size = 0, RendererAST* rti = nullptr) const final;
366         void entropy(std::string& e) const final;
367         void to_json(json& j) const final;
368     };
369     class ASTvariable final : public ASTexpression {
370     public:
371         enum : int {IllegalStackIndex = std::numeric_limits<int>::max()};
372         int stringIndex;
373         std::string text;
374         int stackIndex;
375         int count;
376         bool isParameter;
377          ASTparameter bound;
378 
379         ASTvariable() = delete;
380         ASTvariable(int stringNum, const std::string& str, const yy::location& loc);
381         int evaluate(double* dest = nullptr, int size = 0, RendererAST* rti = nullptr) const final;
382         void evaluate(Modification& m, bool shapeDest, RendererAST* r) const final;
383         void entropy(std::string& e) const final;
384         ASTexpression* simplify(Builder* b) final;
385         ASTexpression* compile(CompilePhase ph, Builder* b) final;
386         void to_json(json& j) const final;
387     };
388     class ASTuserFunction : public ASTexpression {
389     public:
390         int nameIndex;
391         ASTdefine* definition;      // weak ptr
392         exp_ptr arguments;
393         bool isLet;
394 
395         ASTuserFunction(int name, ASTexpression* args, ASTdefine* func, const yy::location& nameLoc);
396         ~ASTuserFunction() override = default;
397         int evaluate(double* dest = nullptr, int size = 0, RendererAST* rti = nullptr) const override;
398         void evaluate(Modification& m, bool shapeDest, RendererAST* r) const override;
399         param_ptr evalArgs(RendererAST* rti = nullptr, const StackRule* parent = nullptr) const override;
400         void entropy(std::string&) const override;
401         ASTexpression* simplify(Builder* b) override;
402         ASTexpression* compile(CompilePhase ph, Builder* b) override;
403         void to_json(json& j) const override;
404     private:
405         class StackSetup {
406             friend class ASTuserFunction;
407             StackSetup(const ASTuserFunction* func, RendererAST* rti);
408             ~StackSetup();
409 
410             const ASTuserFunction*  mFunc;
411             RendererAST*            mRTI;
412             const StackType*        mOldTop;
413             std::size_t             mOldSize;
414         };
415     };
416     class ASTlet final : public ASTuserFunction {
417         std::unique_ptr<ASTrepContainer> mDefinitions;
418         std::vector<std::string> mNames;
419     public:
420         ASTlet(cont_ptr args, def_ptr func, const yy::location& letLoc,
421                const yy::location& defLoc);
422         ~ASTlet() final;          // inherited definition ptr owns ASTdefine
423         ASTexpression* simplify(Builder* b) final;
424         ASTexpression* compile(CompilePhase ph, Builder* b) final;
425         void to_json(json& j) const final;
426     };
427     class ASToperator final : public ASTexpression {
428     public:
429         char op;
430         int  tupleSize;
431         exp_ptr left;
432         exp_ptr right;
433         ASToperator() = delete;
434         ASToperator(char o, ASTexpression* l, ASTexpression* r);
435         ~ASToperator() final = default;
436         int evaluate(double* dest = nullptr, int size = 0, RendererAST* rti = nullptr) const final;
437         void entropy(std::string& e) const final;
438         ASTexpression* simplify(Builder* b) final;
439         ASTexpression* compile(CompilePhase ph, Builder* b) final;
440         void to_json(json& j) const final;
441     };
442     class ASTparen final : public ASTexpression {
443     public:
444         exp_ptr e;
445         ASTparen() = delete;
ASTparen(ASTexpression * e1)446         ASTparen(ASTexpression* e1) : ASTexpression(e1->where, e1->isConstant,
447                                                     e1->isNatural,
448                                                     e1->mType), e(e1)
449         { };
450         ~ASTparen() final = default;
451         int evaluate(double* dest = nullptr, int size = 0, RendererAST* rti = nullptr) const final;
452         void evaluate(Modification& m, bool shapeDest, RendererAST* r) const final;
453         param_ptr evalArgs(RendererAST* rti = nullptr, const StackRule* parent = nullptr) const final;
454         void entropy(std::string& ent) const final;
455         ASTexpression* simplify(Builder* b) final;
456         ASTexpression* compile(CompilePhase ph, Builder* b) final;
457         void to_json(json& j) const final;
458     };
459 
460     class ASTmodTerm final : public ASTexpression {
461     public:
462         enum modTypeEnum : unsigned {  unknownType, x, y, z, xyz, transform,
463             size, sizexyz, rot, skew, flip,
464             zsize, blend, hue, sat, bright, alpha,
465             hueTarg, satTarg, brightTarg, alphaTarg,
466             targHue, targSat, targBright, targAlpha,
467             time, timescale,
468             stroke, param, x1, y1, x2, y2, xrad, yrad, modification };
469 
470         modTypeEnum modType;
471         exp_ptr args;
472         union {
473             int argCount;
474             int flags;
475         };
476 
ASTmodTerm(modTypeEnum t,ASTexpression * a,const yy::location & loc)477         ASTmodTerm(modTypeEnum t, ASTexpression* a, const yy::location& loc)
478         : ASTexpression(loc, a->isConstant, false, ModType), modType(t), args(a), argCount(0) {};
479         ASTmodTerm(modTypeEnum t, const std::string& ent, const yy::location& loc);
ASTmodTerm(modTypeEnum t,const yy::location & loc)480         ASTmodTerm(modTypeEnum t, const yy::location& loc)
481         : ASTexpression(loc, true, false, ModType), modType(t), args(nullptr), argCount(0) {};
482         ~ASTmodTerm() final = default;
483         int evaluate(double* dest = nullptr, int size = 0, RendererAST* rti = nullptr) const final;
484         void evaluate(Modification& m, bool shapeDest, RendererAST*) const final;
485         void entropy(std::string& e) const final;
486         ASTexpression* simplify(Builder* b) final;
487         ASTexpression* compile(CompilePhase ph, Builder* b) final;
488         void to_json(json& j) const final;
489     };
490 
491     void to_json(json& j, const ASTmodTerm& m);
492 
493     class ASTmodification final : public ASTexpression {
494     public:
495         enum modClassEnum {
496             NotAClass = 0, GeomClass = 1, ZClass = 2, TimeClass = 4,
497             HueClass = 8, SatClass = 16, BrightClass = 32, AlphaClass = 64,
498             HueTargetClass = 128, SatTargetClass = 256, BrightTargetClass = 512, AlphaTargetClass = 1024,
499             StrokeClass = 2048, ParamClass = 4096, PathOpClass = 8192
500         };
501         Modification    modData;
502         ASTtermArray    modExp;
503         int             modClass;
504         int             entropyIndex;
505         bool            canonical;
506 
ASTmodification(const yy::location & loc)507         ASTmodification(const yy::location& loc)
508         : ASTexpression(loc, true, false, ModType), modClass(NotAClass),
509           entropyIndex(0), canonical(true) {}
510         ASTmodification(const ASTmodification& m, const yy::location& loc);
511         ASTmodification(mod_ptr m, const yy::location& loc);
512         ~ASTmodification() final;
513         int evaluate(double* dest = nullptr, int size = 0, RendererAST* rti = nullptr) const final;
514         void evaluate(Modification& m, bool shapeDest, RendererAST*) const final;
515         ASTexpression* simplify(Builder* b) final;
516         ASTexpression* compile(CompilePhase ph, Builder* b) final;
517         void setVal(Modification& m, RendererAST* = nullptr) const;
518         void addEntropy(const std::string& name);
519         void makeCanonical();
520         void grab(ASTmodification* m);
521         void to_json(json& j) const final;
522     };
523 
524     void to_json(json& j, const ASTmodification& m);
525 
526     class ASTarray final : public ASTexpression {
527     public:
528         int     mName;
529         std::unique_ptr<double[]> mData;
530         exp_ptr mArgs;
531         int     mLength;
532         int     mStride;
533         int     mStackIndex;
534         int     mCount;
535         bool    isParameter;
536         std::string entString;
537         ASTparameter bound;
538 
539         ASTarray(int nameIndex, exp_ptr args, const yy::location& loc, const std::string& name);
540         ASTarray(const ASTarray&) = delete;
541         ASTarray& operator=(const ASTarray&) = delete;
542         ~ASTarray() final;
543         int evaluate(double* dest = nullptr, int size = 0, RendererAST* rti = nullptr) const final;
544         void entropy(std::string& e) const final;
545         ASTexpression* simplify(Builder* b) final;
546         ASTexpression* compile(CompilePhase ph, Builder* b) final;
547         void to_json(json& j) const final;
548     };
549 
Compile(exp_ptr & exp,CompilePhase ph,Builder * b)550     inline void Compile(exp_ptr& exp, CompilePhase ph, Builder* b)
551     {
552         if (!exp) return;
553         ASTexpression* r = exp->compile(ph, b);
554         if (r)
555             exp.reset(r);
556     }
557 
Simplify(exp_ptr & exp,Builder * b)558     inline void Simplify(exp_ptr& exp, Builder* b)
559     {
560         if (!exp) return;
561         ASTexpression* r = exp->simplify(b);
562         if (r)
563             exp.reset(r);
564     }
565 
Extract(exp_ptr exp)566     inline ASTexpArray Extract(exp_ptr exp)
567     // Extract children from exp, leaving it empty
568     {
569         ASTexpArray ret;
570         if (ASTcons* c = dynamic_cast<ASTcons*>(exp.get()))
571             ret.swap(c->children);
572         else
573             ret.emplace_back(std::move(exp));
574         return ret;
575     }
576 }
577 
578 #endif //INCLUDE_ASTEXPRESSION_H
579