LMMS
Loading...
Searching...
No Matches
juce_Expression.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
27{
28public:
29 Term() {}
30 virtual ~Term() {}
31
32 virtual Type getType() const noexcept = 0;
33 virtual Term* clone() const = 0;
34 virtual ReferenceCountedObjectPtr<Term> resolve (const Scope&, int recursionDepth) = 0;
35 virtual String toString() const = 0;
36 virtual double toDouble() const { return 0; }
37 virtual int getInputIndexFor (const Term*) const { return -1; }
38 virtual int getOperatorPrecedence() const { return 0; }
39 virtual int getNumInputs() const { return 0; }
40 virtual Term* getInput (int) const { return nullptr; }
41 virtual ReferenceCountedObjectPtr<Term> negated();
42
44 double /*overallTarget*/, Term* /*topLevelTerm*/) const
45 {
48 }
49
50 virtual String getName() const
51 {
52 jassertfalse; // You shouldn't call this for an expression that's not actually a function!
53 return {};
54 }
55
56 virtual void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int recursionDepth)
57 {
58 for (int i = getNumInputs(); --i >= 0;)
59 getInput (i)->renameSymbol (oldSymbol, newName, scope, recursionDepth);
60 }
61
63 {
64 public:
65 virtual ~SymbolVisitor() {}
66 virtual void useSymbol (const Symbol&) = 0;
67 };
68
69 virtual void visitAllSymbols (SymbolVisitor& visitor, const Scope& scope, int recursionDepth)
70 {
71 for (int i = getNumInputs(); --i >= 0;)
72 getInput(i)->visitAllSymbols (visitor, scope, recursionDepth);
73 }
74
75private:
77};
78
79
80//==============================================================================
82{
84
85 static void checkRecursionDepth (int depth)
86 {
87 if (depth > 256)
88 throw EvaluationError ("Recursive symbol references");
89 }
90
91 friend class Expression::Term;
92
93 //==============================================================================
95 class EvaluationError : public std::exception
96 {
97 public:
98 EvaluationError (const String& desc) : description (desc)
99 {
100 DBG ("Expression::EvaluationError: " + description);
101 }
102
104 };
105
106 //==============================================================================
107 class Constant : public Term
108 {
109 public:
110 Constant (double val, bool resolutionTarget)
111 : value (val), isResolutionTarget (resolutionTarget) {}
112
114 Term* clone() const { return new Constant (value, isResolutionTarget); }
115 TermPtr resolve (const Scope&, int) { return *this; }
116 double toDouble() const { return value; }
118
120 {
121 String s (value);
123 s = "@" + s;
124
125 return s;
126 }
127
128 double value;
130 };
131
132 //==============================================================================
133 class BinaryTerm : public Term
134 {
135 public:
136 BinaryTerm (TermPtr l, TermPtr r) : left (std::move (l)), right (std::move (r))
137 {
138 jassert (left != nullptr && right != nullptr);
139 }
140
141 int getInputIndexFor (const Term* possibleInput) const
142 {
143 return possibleInput == left ? 0 : (possibleInput == right ? 1 : -1);
144 }
145
147 int getNumInputs() const { return 2; }
148 Term* getInput (int index) const { return index == 0 ? left.get() : (index == 1 ? right.get() : nullptr); }
149
150 virtual double performFunction (double left, double right) const = 0;
151 virtual void writeOperator (String& dest) const = 0;
152
153 TermPtr resolve (const Scope& scope, int recursionDepth)
154 {
155 return *new Constant (performFunction (left ->resolve (scope, recursionDepth)->toDouble(),
156 right->resolve (scope, recursionDepth)->toDouble()), false);
157 }
158
160 {
161 String s;
162 auto ourPrecendence = getOperatorPrecedence();
163
164 if (left->getOperatorPrecedence() > ourPrecendence)
165 s << '(' << left->toString() << ')';
166 else
167 s = left->toString();
168
170
171 if (right->getOperatorPrecedence() >= ourPrecendence)
172 s << '(' << right->toString() << ')';
173 else
174 s << right->toString();
175
176 return s;
177 }
178
179 protected:
181
182 TermPtr createDestinationTerm (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
183 {
184 jassert (input == left || input == right);
185 if (input != left && input != right)
186 return {};
187
188 if (auto dest = findDestinationFor (topLevelTerm, this))
189 return dest->createTermToEvaluateInput (scope, this, overallTarget, topLevelTerm);
190
191 return *new Constant (overallTarget, false);
192 }
193 };
194
195 //==============================================================================
196 class SymbolTerm : public Term
197 {
198 public:
199 explicit SymbolTerm (const String& sym) : symbol (sym) {}
200
201 TermPtr resolve (const Scope& scope, int recursionDepth)
202 {
203 checkRecursionDepth (recursionDepth);
204 return scope.getSymbolValue (symbol).term->resolve (scope, recursionDepth + 1);
205 }
206
208 Term* clone() const { return new SymbolTerm (symbol); }
209 String toString() const { return symbol; }
210 String getName() const { return symbol; }
211
212 void visitAllSymbols (SymbolVisitor& visitor, const Scope& scope, int recursionDepth)
213 {
214 checkRecursionDepth (recursionDepth);
215 visitor.useSymbol (Symbol (scope.getScopeUID(), symbol));
216 scope.getSymbolValue (symbol).term->visitAllSymbols (visitor, scope, recursionDepth + 1);
217 }
218
219 void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int /*recursionDepth*/)
220 {
221 if (oldSymbol.symbolName == symbol && scope.getScopeUID() == oldSymbol.scopeUID)
222 symbol = newName;
223 }
224
226 };
227
228 //==============================================================================
229 class Function : public Term
230 {
231 public:
232 explicit Function (const String& name) : functionName (name) {}
233
234 Function (const String& name, const Array<Expression>& params)
235 : functionName (name), parameters (params)
236 {}
237
239 Term* clone() const { return new Function (functionName, parameters); }
240 int getNumInputs() const { return parameters.size(); }
241 Term* getInput (int i) const { return parameters.getReference(i).term.get(); }
242 String getName() const { return functionName; }
243
244 TermPtr resolve (const Scope& scope, int recursionDepth)
245 {
246 checkRecursionDepth (recursionDepth);
247 double result = 0;
248 auto numParams = parameters.size();
249
250 if (numParams > 0)
251 {
252 HeapBlock<double> params (numParams);
253
254 for (int i = 0; i < numParams; ++i)
255 params[i] = parameters.getReference(i).term->resolve (scope, recursionDepth + 1)->toDouble();
256
257 result = scope.evaluateFunction (functionName, params, numParams);
258 }
259 else
260 {
261 result = scope.evaluateFunction (functionName, nullptr, 0);
262 }
263
264 return *new Constant (result, false);
265 }
266
267 int getInputIndexFor (const Term* possibleInput) const
268 {
269 for (int i = 0; i < parameters.size(); ++i)
270 if (parameters.getReference(i).term == possibleInput)
271 return i;
272
273 return -1;
274 }
275
277 {
278 if (parameters.size() == 0)
279 return functionName + "()";
280
281 String s (functionName + " (");
282
283 for (int i = 0; i < parameters.size(); ++i)
284 {
285 s << parameters.getReference(i).term->toString();
286
287 if (i < parameters.size() - 1)
288 s << ", ";
289 }
290
291 s << ')';
292 return s;
293 }
294
297 };
298
299 //==============================================================================
300 class DotOperator : public BinaryTerm
301 {
302 public:
304
305 TermPtr resolve (const Scope& scope, int recursionDepth)
306 {
307 checkRecursionDepth (recursionDepth);
308
309 EvaluationVisitor visitor (right, recursionDepth + 1);
310 scope.visitRelativeScope (getSymbol()->symbol, visitor);
311 return visitor.output;
312 }
313
314 Term* clone() const { return new DotOperator (getSymbol(), *right); }
315 String getName() const { return "."; }
316 int getOperatorPrecedence() const { return 1; }
317 void writeOperator (String& dest) const { dest << '.'; }
318 double performFunction (double, double) const { return 0.0; }
319
320 void visitAllSymbols (SymbolVisitor& visitor, const Scope& scope, int recursionDepth)
321 {
322 checkRecursionDepth (recursionDepth);
323 visitor.useSymbol (Symbol (scope.getScopeUID(), getSymbol()->symbol));
324
325 SymbolVisitingVisitor v (right, visitor, recursionDepth + 1);
326
327 try
328 {
329 scope.visitRelativeScope (getSymbol()->symbol, v);
330 }
331 catch (...) {}
332 }
333
334 void renameSymbol (const Symbol& oldSymbol, const String& newName, const Scope& scope, int recursionDepth)
335 {
336 checkRecursionDepth (recursionDepth);
337 getSymbol()->renameSymbol (oldSymbol, newName, scope, recursionDepth);
338
339 SymbolRenamingVisitor visitor (right, oldSymbol, newName, recursionDepth + 1);
340
341 try
342 {
343 scope.visitRelativeScope (getSymbol()->symbol, visitor);
344 }
345 catch (...) {}
346 }
347
348 private:
349 //==============================================================================
351 {
352 public:
353 EvaluationVisitor (const TermPtr& t, const int recursion)
354 : input (t), output (t), recursionCount (recursion) {}
355
356 void visit (const Scope& scope) { output = input->resolve (scope, recursionCount); }
357
360 const int recursionCount;
361
362 private:
364 };
365
367 {
368 public:
369 SymbolVisitingVisitor (const TermPtr& t, SymbolVisitor& v, const int recursion)
370 : input (t), visitor (v), recursionCount (recursion) {}
371
372 void visit (const Scope& scope) { input->visitAllSymbols (visitor, scope, recursionCount); }
373
374 private:
377 const int recursionCount;
378
380 };
381
383 {
384 public:
385 SymbolRenamingVisitor (const TermPtr& t, const Expression::Symbol& symbol_, const String& newName_, const int recursionCount_)
386 : input (t), symbol (symbol_), newName (newName_), recursionCount (recursionCount_) {}
387
388 void visit (const Scope& scope) { input->renameSymbol (symbol, newName, scope, recursionCount); }
389
390 private:
394 const int recursionCount;
395
397 };
398
399 SymbolTerm* getSymbol() const { return static_cast<SymbolTerm*> (left.get()); }
400
402 };
403
404 //==============================================================================
405 class Negate : public Term
406 {
407 public:
408 explicit Negate (const TermPtr& t) : input (t)
409 {
410 jassert (t != nullptr);
411 }
412
414 int getInputIndexFor (const Term* possibleInput) const { return possibleInput == input ? 0 : -1; }
415 int getNumInputs() const { return 1; }
416 Term* getInput (int index) const { return index == 0 ? input.get() : nullptr; }
417 Term* clone() const { return new Negate (*input->clone()); }
418
419 TermPtr resolve (const Scope& scope, int recursionDepth)
420 {
421 return *new Constant (-input->resolve (scope, recursionDepth)->toDouble(), false);
422 }
423
424 String getName() const { return "-"; }
425 TermPtr negated() { return input; }
426
427 TermPtr createTermToEvaluateInput (const Scope& scope, const Term* t, double overallTarget, Term* topLevelTerm) const
428 {
429 ignoreUnused (t);
430 jassert (t == input);
431
432 const Term* const dest = findDestinationFor (topLevelTerm, this);
433
434 return *new Negate (dest == nullptr ? TermPtr (*new Constant (overallTarget, false))
435 : dest->createTermToEvaluateInput (scope, this, overallTarget, topLevelTerm));
436 }
437
439 {
440 if (input->getOperatorPrecedence() > 0)
441 return "-(" + input->toString() + ")";
442
443 return "-" + input->toString();
444 }
445
446 private:
448 };
449
450 //==============================================================================
451 class Add : public BinaryTerm
452 {
453 public:
455
456 Term* clone() const { return new Add (*left->clone(), *right->clone()); }
457 double performFunction (double lhs, double rhs) const { return lhs + rhs; }
458 int getOperatorPrecedence() const { return 3; }
459 String getName() const { return "+"; }
460 void writeOperator (String& dest) const { dest << " + "; }
461
462 TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
463 {
464 if (auto newDest = createDestinationTerm (scope, input, overallTarget, topLevelTerm))
465 return *new Subtract (newDest, *(input == left ? right : left)->clone());
466
467 return {};
468 }
469
470 private:
472 };
473
474 //==============================================================================
475 class Subtract : public BinaryTerm
476 {
477 public:
479
480 Term* clone() const { return new Subtract (*left->clone(), *right->clone()); }
481 double performFunction (double lhs, double rhs) const { return lhs - rhs; }
482 int getOperatorPrecedence() const { return 3; }
483 String getName() const { return "-"; }
484 void writeOperator (String& dest) const { dest << " - "; }
485
486 TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
487 {
488 if (auto newDest = createDestinationTerm (scope, input, overallTarget, topLevelTerm))
489 {
490 if (input == left)
491 return *new Add (*newDest, *right->clone());
492
493 return *new Subtract (*left->clone(), *newDest);
494 }
495
496 return {};
497 }
498
499 private:
501 };
502
503 //==============================================================================
504 class Multiply : public BinaryTerm
505 {
506 public:
508
509 Term* clone() const { return new Multiply (*left->clone(), *right->clone()); }
510 double performFunction (double lhs, double rhs) const { return lhs * rhs; }
511 String getName() const { return "*"; }
512 void writeOperator (String& dest) const { dest << " * "; }
513 int getOperatorPrecedence() const { return 2; }
514
515 TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
516 {
517 if (auto newDest = createDestinationTerm (scope, input, overallTarget, topLevelTerm))
518 return *new Divide (newDest, *(input == left ? right : left)->clone());
519
520 return {};
521 }
522
524 };
525
526 //==============================================================================
527 class Divide : public BinaryTerm
528 {
529 public:
531
532 Term* clone() const { return new Divide (*left->clone(), *right->clone()); }
533 double performFunction (double lhs, double rhs) const { return lhs / rhs; }
534 String getName() const { return "/"; }
535 void writeOperator (String& dest) const { dest << " / "; }
536 int getOperatorPrecedence() const { return 2; }
537
538 TermPtr createTermToEvaluateInput (const Scope& scope, const Term* input, double overallTarget, Term* topLevelTerm) const
539 {
540 auto newDest = createDestinationTerm (scope, input, overallTarget, topLevelTerm);
541
542 if (newDest == nullptr)
543 return {};
544
545 if (input == left)
546 return *new Multiply (*newDest, *right->clone());
547
548 return *new Divide (*left->clone(), *newDest);
549 }
550
552 };
553
554 //==============================================================================
555 static Term* findDestinationFor (Term* const topLevel, const Term* const inputTerm)
556 {
557 const int inputIndex = topLevel->getInputIndexFor (inputTerm);
558 if (inputIndex >= 0)
559 return topLevel;
560
561 for (int i = topLevel->getNumInputs(); --i >= 0;)
562 {
563 Term* const t = findDestinationFor (topLevel->getInput (i), inputTerm);
564
565 if (t != nullptr)
566 return t;
567 }
568
569 return nullptr;
570 }
571
572 static Constant* findTermToAdjust (Term* const term, const bool mustBeFlagged)
573 {
574 if (term == nullptr)
575 {
577 return nullptr;
578 }
579
580 if (term->getType() == constantType)
581 {
582 Constant* const c = static_cast<Constant*> (term);
583 if (c->isResolutionTarget || ! mustBeFlagged)
584 return c;
585 }
586
587 if (term->getType() == functionType)
588 return nullptr;
589
590 const int numIns = term->getNumInputs();
591
592 for (int i = 0; i < numIns; ++i)
593 {
594 Term* const input = term->getInput (i);
595
596 if (input->getType() == constantType)
597 {
598 Constant* const c = static_cast<Constant*> (input);
599
600 if (c->isResolutionTarget || ! mustBeFlagged)
601 return c;
602 }
603 }
604
605 for (int i = 0; i < numIns; ++i)
606 if (auto c = findTermToAdjust (term->getInput (i), mustBeFlagged))
607 return c;
608
609 return nullptr;
610 }
611
612 static bool containsAnySymbols (const Term& t)
613 {
614 if (t.getType() == Expression::symbolType)
615 return true;
616
617 for (int i = t.getNumInputs(); --i >= 0;)
618 if (containsAnySymbols (*t.getInput (i)))
619 return true;
620
621 return false;
622 }
623
624 //==============================================================================
626 {
627 public:
629 void useSymbol (const Symbol& s) { wasFound = wasFound || s == symbol; }
630
631 bool wasFound = false;
632
633 private:
635
637 };
638
639 //==============================================================================
641 {
642 public:
644 void useSymbol (const Symbol& s) { list.addIfNotAlreadyThere (s); }
645
646 private:
648
650 };
651
652 //==============================================================================
653 class Parser
654 {
655 public:
656 //==============================================================================
657 Parser (String::CharPointerType& stringToParse) : text (stringToParse)
658 {
659 }
660
662 {
663 if (text.isEmpty())
664 return *new Constant (0.0, false);
665
666 auto e = readExpression();
667
668 if (e == nullptr || ((! readOperator (",")) && ! text.isEmpty()))
669 return parseError ("Syntax error: \"" + String (text) + "\"");
670
671 return e;
672 }
673
675
676 private:
677 String::CharPointerType& text;
678
680 {
681 if (error.isEmpty())
682 error = message;
683
684 return {};
685 }
686
687 //==============================================================================
688 static bool isDecimalDigit (const juce_wchar c) noexcept
689 {
690 return c >= '0' && c <= '9';
691 }
692
693 bool readChar (const juce_wchar required) noexcept
694 {
695 if (*text == required)
696 {
697 ++text;
698 return true;
699 }
700
701 return false;
702 }
703
704 bool readOperator (const char* ops, char* const opType = nullptr) noexcept
705 {
706 text.incrementToEndOfWhitespace();
707
708 while (*ops != 0)
709 {
710 if (readChar ((juce_wchar) (uint8) *ops))
711 {
712 if (opType != nullptr)
713 *opType = *ops;
714
715 return true;
716 }
717
718 ++ops;
719 }
720
721 return false;
722 }
723
724 bool readIdentifier (String& identifier) noexcept
725 {
726 text.incrementToEndOfWhitespace();
727 auto t = text;
728 int numChars = 0;
729
730 if (t.isLetter() || *t == '_')
731 {
732 ++t;
733 ++numChars;
734
735 while (t.isLetterOrDigit() || *t == '_')
736 {
737 ++t;
738 ++numChars;
739 }
740 }
741
742 if (numChars > 0)
743 {
744 identifier = String (text, (size_t) numChars);
745 text = t;
746 return true;
747 }
748
749 return false;
750 }
751
753 {
754 text.incrementToEndOfWhitespace();
755 auto t = text;
756 bool isResolutionTarget = (*t == '@');
757
758 if (isResolutionTarget)
759 {
760 ++t;
761 t.incrementToEndOfWhitespace();
762 text = t;
763 }
764
765 if (*t == '-')
766 {
767 ++t;
768 t.incrementToEndOfWhitespace();
769 }
770
771 if (isDecimalDigit (*t) || (*t == '.' && isDecimalDigit (t[1])))
772 return new Constant (CharacterFunctions::readDoubleValue (text), isResolutionTarget);
773
774 return nullptr;
775 }
776
778 {
780 char opType;
781
782 while (lhs != nullptr && readOperator ("+-", &opType))
783 {
785
786 if (rhs == nullptr)
787 return parseError ("Expected expression after \"" + String::charToString ((juce_wchar) (uint8) opType) + "\"");
788
789 if (opType == '+')
790 lhs = *new Add (lhs, rhs);
791 else
792 lhs = *new Subtract (lhs, rhs);
793 }
794
795 return lhs;
796 }
797
799 {
800 auto lhs = readUnaryExpression();
801 char opType;
802
803 while (lhs != nullptr && readOperator ("*/", &opType))
804 {
806
807 if (rhs == nullptr)
808 return parseError ("Expected expression after \"" + String::charToString ((juce_wchar) (uint8) opType) + "\"");
809
810 if (opType == '*')
811 lhs = *new Multiply (lhs, rhs);
812 else
813 lhs = *new Divide (lhs, rhs);
814 }
815
816 return lhs;
817 }
818
820 {
821 char opType;
822 if (readOperator ("+-", &opType))
823 {
825
826 if (e == nullptr)
827 return parseError ("Expected expression after \"" + String::charToString ((juce_wchar) (uint8) opType) + "\"");
828
829 if (opType == '-')
830 e = e->negated();
831
832 return e;
833 }
834
835 return readPrimaryExpression();
836 }
837
839 {
840 if (auto e = readParenthesisedExpression())
841 return e;
842
843 if (auto e = readNumber())
844 return e;
845
846 return readSymbolOrFunction();
847 }
848
850 {
851 String identifier;
852
853 if (readIdentifier (identifier))
854 {
855 if (readOperator ("(")) // method call...
856 {
857 auto f = new Function (identifier);
858 std::unique_ptr<Term> func (f); // (can't use std::unique_ptr<Function> in MSVC)
859
860 auto param = readExpression();
861
862 if (param == nullptr)
863 {
864 if (readOperator (")"))
865 return TermPtr (func.release());
866
867 return parseError ("Expected parameters after \"" + identifier + " (\"");
868 }
869
870 f->parameters.add (Expression (param.get()));
871
872 while (readOperator (","))
873 {
874 param = readExpression();
875
876 if (param == nullptr)
877 return parseError ("Expected expression after \",\"");
878
879 f->parameters.add (Expression (param.get()));
880 }
881
882 if (readOperator (")"))
883 return TermPtr (func.release());
884
885 return parseError ("Expected \")\"");
886 }
887
888 if (readOperator ("."))
889 {
891
892 if (rhs == nullptr)
893 return parseError ("Expected symbol or function after \".\"");
894
895 if (identifier == "this")
896 return rhs;
897
898 return *new DotOperator (new SymbolTerm (identifier), rhs);
899 }
900
901 // just a symbol..
902 jassert (identifier.trim() == identifier);
903 return *new SymbolTerm (identifier);
904 }
905
906 return {};
907 }
908
910 {
911 if (! readOperator ("("))
912 return {};
913
914 auto e = readExpression();
915
916 if (e == nullptr || ! readOperator (")"))
917 return {};
918
919 return e;
920 }
921
923 };
924};
925
926//==============================================================================
928 : term (new Expression::Helpers::Constant (0, false))
929{
930}
931
935
937{
938 jassert (term != nullptr);
939}
940
941Expression::Expression (const double constant)
942 : term (new Expression::Helpers::Constant (constant, false))
943{
944}
945
947 : term (other.term)
948{
949}
950
951Expression& Expression::operator= (const Expression& other)
952{
953 term = other.term;
954 return *this;
955}
956
958 : term (std::move (other.term))
959{
960}
961
962Expression& Expression::operator= (Expression&& other) noexcept
963{
964 term = std::move (other.term);
965 return *this;
966}
967
968Expression::Expression (const String& stringToParse, String& parseError)
969{
970 auto text = stringToParse.getCharPointer();
971 Helpers::Parser parser (text);
972 term = parser.readUpToComma();
973 parseError = parser.error;
974}
975
976Expression Expression::parse (String::CharPointerType& stringToParse, String& parseError)
977{
978 Helpers::Parser parser (stringToParse);
979 Expression e (parser.readUpToComma().get());
980 parseError = parser.error;
981 return e;
982}
983
985{
986 return evaluate (Expression::Scope());
987}
988
990{
991 String err;
992 return evaluate (scope, err);
993}
994
995double Expression::evaluate (const Scope& scope, String& evaluationError) const
996{
997 try
998 {
999 return term->resolve (scope, 0)->toDouble();
1000 }
1002 {
1003 evaluationError = e.description;
1004 }
1005
1006 return 0;
1007}
1008
1009Expression Expression::operator+ (const Expression& other) const { return Expression (new Helpers::Add (term, other.term)); }
1010Expression Expression::operator- (const Expression& other) const { return Expression (new Helpers::Subtract (term, other.term)); }
1011Expression Expression::operator* (const Expression& other) const { return Expression (new Helpers::Multiply (term, other.term)); }
1012Expression Expression::operator/ (const Expression& other) const { return Expression (new Helpers::Divide (term, other.term)); }
1013Expression Expression::operator-() const { return Expression (term->negated().get()); }
1015
1016Expression Expression::function (const String& functionName, const Array<Expression>& parameters)
1017{
1018 return Expression (new Helpers::Function (functionName, parameters));
1019}
1020
1022{
1023 std::unique_ptr<Term> newTerm (term->clone());
1024
1025 auto termToAdjust = Helpers::findTermToAdjust (newTerm.get(), true);
1026
1027 if (termToAdjust == nullptr)
1028 termToAdjust = Helpers::findTermToAdjust (newTerm.get(), false);
1029
1030 if (termToAdjust == nullptr)
1031 {
1032 newTerm.reset (new Helpers::Add (*newTerm.release(), *new Helpers::Constant (0, false)));
1033 termToAdjust = Helpers::findTermToAdjust (newTerm.get(), false);
1034 }
1035
1036 jassert (termToAdjust != nullptr);
1037
1038 if (const Term* parent = Helpers::findDestinationFor (newTerm.get(), termToAdjust))
1039 {
1040 if (Helpers::TermPtr reverseTerm = parent->createTermToEvaluateInput (scope, termToAdjust, targetValue, newTerm.get()))
1041 termToAdjust->value = Expression (reverseTerm.get()).evaluate (scope);
1042 else
1043 return Expression (targetValue);
1044 }
1045 else
1046 {
1047 termToAdjust->value = targetValue;
1048 }
1049
1050 return Expression (newTerm.release());
1051}
1052
1053Expression Expression::withRenamedSymbol (const Expression::Symbol& oldSymbol, const String& newName, const Scope& scope) const
1054{
1055 jassert (newName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_"));
1056
1057 if (oldSymbol.symbolName == newName)
1058 return *this;
1059
1060 Expression e (term->clone());
1061 e.term->renameSymbol (oldSymbol, newName, scope, 0);
1062 return e;
1063}
1064
1065bool Expression::referencesSymbol (const Expression::Symbol& symbolToCheck, const Scope& scope) const
1066{
1067 Helpers::SymbolCheckVisitor visitor (symbolToCheck);
1068
1069 try
1070 {
1071 term->visitAllSymbols (visitor, scope, 0);
1072 }
1074 {}
1075
1076 return visitor.wasFound;
1077}
1078
1080{
1081 try
1082 {
1083 Helpers::SymbolListVisitor visitor (results);
1084 term->visitAllSymbols (visitor, scope, 0);
1085 }
1087 {}
1088}
1089
1090String Expression::toString() const { return term->toString(); }
1093String Expression::getSymbolOrFunction() const { return term->getName(); }
1094int Expression::getNumInputs() const { return term->getNumInputs(); }
1095Expression Expression::getInput (int index) const { return Expression (term->getInput (index)); }
1096
1097//==============================================================================
1102
1103//==============================================================================
1108
1109bool Expression::Symbol::operator== (const Symbol& other) const noexcept
1110{
1111 return symbolName == other.symbolName && scopeUID == other.scopeUID;
1112}
1113
1114bool Expression::Symbol::operator!= (const Symbol& other) const noexcept
1115{
1116 return ! operator== (other);
1117}
1118
1119//==============================================================================
1122
1124{
1125 if (symbol.isNotEmpty())
1126 throw Helpers::EvaluationError ("Unknown symbol: " + symbol);
1127
1128 return Expression();
1129}
1130
1131double Expression::Scope::evaluateFunction (const String& functionName, const double* parameters, int numParams) const
1132{
1133 if (numParams > 0)
1134 {
1135 if (functionName == "min")
1136 {
1137 double v = parameters[0];
1138 for (int i = 1; i < numParams; ++i)
1139 v = jmin (v, parameters[i]);
1140
1141 return v;
1142 }
1143
1144 if (functionName == "max")
1145 {
1146 double v = parameters[0];
1147 for (int i = 1; i < numParams; ++i)
1148 v = jmax (v, parameters[i]);
1149
1150 return v;
1151 }
1152
1153 if (numParams == 1)
1154 {
1155 if (functionName == "sin") return std::sin (parameters[0]);
1156 if (functionName == "cos") return std::cos (parameters[0]);
1157 if (functionName == "tan") return std::tan (parameters[0]);
1158 if (functionName == "abs") return std::abs (parameters[0]);
1159 }
1160 }
1161
1162 throw Helpers::EvaluationError ("Unknown function: \"" + functionName + "\"");
1163}
1164
1166{
1167 throw Helpers::EvaluationError ("Unknown symbol: " + scopeName);
1168}
1169
1171{
1172 return {};
1173}
1174
1175} // namespace juce
#define noexcept
Definition DistrhoDefines.h:72
static Audio_Scope * scope
Definition player.cpp:26
static void message(int level, const char *fmt,...)
Definition adplugdb.cpp:120
static volatile bool term
Definition carla-uhe-test.c:12
Definition juce_Array.h:56
static double readDoubleValue(CharPointerType &text) noexcept
Definition juce_CharacterFunctions.h:147
Definition juce_Expression.cpp:452
void writeOperator(String &dest) const
Definition juce_Expression.cpp:460
Add(TermPtr l, TermPtr r)
Definition juce_Expression.cpp:454
int getOperatorPrecedence() const
Definition juce_Expression.cpp:458
Term * clone() const
Definition juce_Expression.cpp:456
TermPtr createTermToEvaluateInput(const Scope &scope, const Term *input, double overallTarget, Term *topLevelTerm) const
Definition juce_Expression.cpp:462
double performFunction(double lhs, double rhs) const
Definition juce_Expression.cpp:457
String getName() const
Definition juce_Expression.cpp:459
Term * getInput(int index) const
Definition juce_Expression.cpp:148
String toString() const
Definition juce_Expression.cpp:159
Type getType() const noexcept
Definition juce_Expression.cpp:146
TermPtr createDestinationTerm(const Scope &scope, const Term *input, double overallTarget, Term *topLevelTerm) const
Definition juce_Expression.cpp:182
BinaryTerm(TermPtr l, TermPtr r)
Definition juce_Expression.cpp:136
const TermPtr left
Definition juce_Expression.cpp:180
TermPtr resolve(const Scope &scope, int recursionDepth)
Definition juce_Expression.cpp:153
int getInputIndexFor(const Term *possibleInput) const
Definition juce_Expression.cpp:141
const TermPtr right
Definition juce_Expression.cpp:180
virtual double performFunction(double left, double right) const =0
int getNumInputs() const
Definition juce_Expression.cpp:147
virtual void writeOperator(String &dest) const =0
Definition juce_Expression.cpp:108
double toDouble() const
Definition juce_Expression.cpp:116
Type getType() const noexcept
Definition juce_Expression.cpp:113
TermPtr negated()
Definition juce_Expression.cpp:117
double value
Definition juce_Expression.cpp:128
bool isResolutionTarget
Definition juce_Expression.cpp:129
String toString() const
Definition juce_Expression.cpp:119
Constant(double val, bool resolutionTarget)
Definition juce_Expression.cpp:110
TermPtr resolve(const Scope &, int)
Definition juce_Expression.cpp:115
Term * clone() const
Definition juce_Expression.cpp:114
Definition juce_Expression.cpp:528
TermPtr createTermToEvaluateInput(const Scope &scope, const Term *input, double overallTarget, Term *topLevelTerm) const
Definition juce_Expression.cpp:538
void writeOperator(String &dest) const
Definition juce_Expression.cpp:535
Term * clone() const
Definition juce_Expression.cpp:532
String getName() const
Definition juce_Expression.cpp:534
int getOperatorPrecedence() const
Definition juce_Expression.cpp:536
double performFunction(double lhs, double rhs) const
Definition juce_Expression.cpp:533
Divide(TermPtr l, TermPtr r)
Definition juce_Expression.cpp:530
EvaluationVisitor(const TermPtr &t, const int recursion)
Definition juce_Expression.cpp:353
void visit(const Scope &scope)
Definition juce_Expression.cpp:356
const TermPtr input
Definition juce_Expression.cpp:358
const int recursionCount
Definition juce_Expression.cpp:360
TermPtr output
Definition juce_Expression.cpp:359
const String newName
Definition juce_Expression.cpp:393
SymbolRenamingVisitor(const TermPtr &t, const Expression::Symbol &symbol_, const String &newName_, const int recursionCount_)
Definition juce_Expression.cpp:385
void visit(const Scope &scope)
Definition juce_Expression.cpp:388
const TermPtr input
Definition juce_Expression.cpp:391
const int recursionCount
Definition juce_Expression.cpp:394
const Symbol & symbol
Definition juce_Expression.cpp:392
void visit(const Scope &scope)
Definition juce_Expression.cpp:372
const TermPtr input
Definition juce_Expression.cpp:375
const int recursionCount
Definition juce_Expression.cpp:377
SymbolVisitor & visitor
Definition juce_Expression.cpp:376
SymbolVisitingVisitor(const TermPtr &t, SymbolVisitor &v, const int recursion)
Definition juce_Expression.cpp:369
Definition juce_Expression.cpp:301
void visitAllSymbols(SymbolVisitor &visitor, const Scope &scope, int recursionDepth)
Definition juce_Expression.cpp:320
Term * clone() const
Definition juce_Expression.cpp:314
double performFunction(double, double) const
Definition juce_Expression.cpp:318
SymbolTerm * getSymbol() const
Definition juce_Expression.cpp:399
DotOperator(SymbolTerm *l, TermPtr r)
Definition juce_Expression.cpp:303
void writeOperator(String &dest) const
Definition juce_Expression.cpp:317
int getOperatorPrecedence() const
Definition juce_Expression.cpp:316
void renameSymbol(const Symbol &oldSymbol, const String &newName, const Scope &scope, int recursionDepth)
Definition juce_Expression.cpp:334
TermPtr resolve(const Scope &scope, int recursionDepth)
Definition juce_Expression.cpp:305
String getName() const
Definition juce_Expression.cpp:315
Definition juce_Expression.cpp:96
EvaluationError(const String &desc)
Definition juce_Expression.cpp:98
String description
Definition juce_Expression.cpp:103
Definition juce_Expression.cpp:230
Term * getInput(int i) const
Definition juce_Expression.cpp:241
Type getType() const noexcept
Definition juce_Expression.cpp:238
int getInputIndexFor(const Term *possibleInput) const
Definition juce_Expression.cpp:267
Function(const String &name, const Array< Expression > &params)
Definition juce_Expression.cpp:234
String getName() const
Definition juce_Expression.cpp:242
int getNumInputs() const
Definition juce_Expression.cpp:240
Term * clone() const
Definition juce_Expression.cpp:239
TermPtr resolve(const Scope &scope, int recursionDepth)
Definition juce_Expression.cpp:244
Array< Expression > parameters
Definition juce_Expression.cpp:296
Function(const String &name)
Definition juce_Expression.cpp:232
const String functionName
Definition juce_Expression.cpp:295
String toString() const
Definition juce_Expression.cpp:276
Definition juce_Expression.cpp:505
TermPtr createTermToEvaluateInput(const Scope &scope, const Term *input, double overallTarget, Term *topLevelTerm) const
Definition juce_Expression.cpp:515
Multiply(TermPtr l, TermPtr r)
Definition juce_Expression.cpp:507
String getName() const
Definition juce_Expression.cpp:511
Term * clone() const
Definition juce_Expression.cpp:509
double performFunction(double lhs, double rhs) const
Definition juce_Expression.cpp:510
void writeOperator(String &dest) const
Definition juce_Expression.cpp:512
int getOperatorPrecedence() const
Definition juce_Expression.cpp:513
Definition juce_Expression.cpp:406
int getInputIndexFor(const Term *possibleInput) const
Definition juce_Expression.cpp:414
Type getType() const noexcept
Definition juce_Expression.cpp:413
Term * clone() const
Definition juce_Expression.cpp:417
TermPtr negated()
Definition juce_Expression.cpp:425
Negate(const TermPtr &t)
Definition juce_Expression.cpp:408
String toString() const
Definition juce_Expression.cpp:438
Term * getInput(int index) const
Definition juce_Expression.cpp:416
const TermPtr input
Definition juce_Expression.cpp:447
TermPtr createTermToEvaluateInput(const Scope &scope, const Term *t, double overallTarget, Term *topLevelTerm) const
Definition juce_Expression.cpp:427
String getName() const
Definition juce_Expression.cpp:424
TermPtr resolve(const Scope &scope, int recursionDepth)
Definition juce_Expression.cpp:419
int getNumInputs() const
Definition juce_Expression.cpp:415
Definition juce_Expression.cpp:654
Term * readNumber() noexcept
Definition juce_Expression.cpp:752
Parser(String::CharPointerType &stringToParse)
Definition juce_Expression.cpp:657
TermPtr readUnaryExpression()
Definition juce_Expression.cpp:819
bool readIdentifier(String &identifier) noexcept
Definition juce_Expression.cpp:724
bool readChar(const juce_wchar required) noexcept
Definition juce_Expression.cpp:693
static bool isDecimalDigit(const juce_wchar c) noexcept
Definition juce_Expression.cpp:688
TermPtr readParenthesisedExpression()
Definition juce_Expression.cpp:909
TermPtr readUpToComma()
Definition juce_Expression.cpp:661
String::CharPointerType & text
Definition juce_Expression.cpp:677
String error
Definition juce_Expression.cpp:674
TermPtr parseError(const String &message)
Definition juce_Expression.cpp:679
TermPtr readSymbolOrFunction()
Definition juce_Expression.cpp:849
bool readOperator(const char *ops, char *const opType=nullptr) noexcept
Definition juce_Expression.cpp:704
TermPtr readExpression()
Definition juce_Expression.cpp:777
TermPtr readMultiplyOrDivideExpression()
Definition juce_Expression.cpp:798
TermPtr readPrimaryExpression()
Definition juce_Expression.cpp:838
Definition juce_Expression.cpp:476
String getName() const
Definition juce_Expression.cpp:483
Subtract(TermPtr l, TermPtr r)
Definition juce_Expression.cpp:478
int getOperatorPrecedence() const
Definition juce_Expression.cpp:482
Term * clone() const
Definition juce_Expression.cpp:480
double performFunction(double lhs, double rhs) const
Definition juce_Expression.cpp:481
TermPtr createTermToEvaluateInput(const Scope &scope, const Term *input, double overallTarget, Term *topLevelTerm) const
Definition juce_Expression.cpp:486
void writeOperator(String &dest) const
Definition juce_Expression.cpp:484
Definition juce_Expression.cpp:626
SymbolCheckVisitor(const Symbol &s)
Definition juce_Expression.cpp:628
void useSymbol(const Symbol &s)
Definition juce_Expression.cpp:629
const Symbol & symbol
Definition juce_Expression.cpp:634
bool wasFound
Definition juce_Expression.cpp:631
Definition juce_Expression.cpp:641
Array< Symbol > & list
Definition juce_Expression.cpp:647
void useSymbol(const Symbol &s)
Definition juce_Expression.cpp:644
SymbolListVisitor(Array< Symbol > &list_)
Definition juce_Expression.cpp:643
Definition juce_Expression.cpp:197
void visitAllSymbols(SymbolVisitor &visitor, const Scope &scope, int recursionDepth)
Definition juce_Expression.cpp:212
String symbol
Definition juce_Expression.cpp:225
Term * clone() const
Definition juce_Expression.cpp:208
Type getType() const noexcept
Definition juce_Expression.cpp:207
void renameSymbol(const Symbol &oldSymbol, const String &newName, const Scope &scope, int)
Definition juce_Expression.cpp:219
String toString() const
Definition juce_Expression.cpp:209
TermPtr resolve(const Scope &scope, int recursionDepth)
Definition juce_Expression.cpp:201
SymbolTerm(const String &sym)
Definition juce_Expression.cpp:199
String getName() const
Definition juce_Expression.cpp:210
Definition juce_Expression.h:137
Definition juce_Expression.h:109
virtual Expression getSymbolValue(const String &symbol) const
Definition juce_Expression.cpp:1123
virtual void visitRelativeScope(const String &scopeName, Visitor &visitor) const
Definition juce_Expression.cpp:1165
virtual String getScopeUID() const
Definition juce_Expression.cpp:1170
virtual double evaluateFunction(const String &functionName, const double *parameters, int numParameters) const
Definition juce_Expression.cpp:1131
virtual ~Scope()
Definition juce_Expression.cpp:1121
Scope()
Definition juce_Expression.cpp:1120
Definition juce_Expression.cpp:63
virtual void useSymbol(const Symbol &)=0
virtual ~SymbolVisitor()
Definition juce_Expression.cpp:65
Definition juce_Expression.cpp:27
Term()
Definition juce_Expression.cpp:29
virtual int getOperatorPrecedence() const
Definition juce_Expression.cpp:38
virtual void visitAllSymbols(SymbolVisitor &visitor, const Scope &scope, int recursionDepth)
Definition juce_Expression.cpp:69
virtual void renameSymbol(const Symbol &oldSymbol, const String &newName, const Scope &scope, int recursionDepth)
Definition juce_Expression.cpp:56
virtual String getName() const
Definition juce_Expression.cpp:50
virtual ~Term()
Definition juce_Expression.cpp:30
virtual ReferenceCountedObjectPtr< Term > createTermToEvaluateInput(const Scope &, const Term *, double, Term *) const
Definition juce_Expression.cpp:43
virtual ReferenceCountedObjectPtr< Term > resolve(const Scope &, int recursionDepth)=0
virtual double toDouble() const
Definition juce_Expression.cpp:36
virtual int getNumInputs() const
Definition juce_Expression.cpp:39
virtual Type getType() const noexcept=0
virtual String toString() const =0
virtual ReferenceCountedObjectPtr< Term > negated()
Definition juce_Expression.cpp:1098
virtual Term * clone() const =0
virtual int getInputIndexFor(const Term *) const
Definition juce_Expression.cpp:37
virtual Term * getInput(int) const
Definition juce_Expression.cpp:40
Expression adjustedToGiveNewResult(double targetValue, const Scope &scope) const
Definition juce_Expression.cpp:1021
void findReferencedSymbols(Array< Symbol > &results, const Scope &scope) const
Definition juce_Expression.cpp:1079
static Expression function(const String &functionName, const Array< Expression > &parameters)
Definition juce_Expression.cpp:1016
String getSymbolOrFunction() const
Definition juce_Expression.cpp:1093
Expression()
Definition juce_Expression.cpp:927
bool usesAnySymbols() const
Definition juce_Expression.cpp:1091
Expression withRenamedSymbol(const Symbol &oldSymbol, const String &newName, const Scope &scope) const
Definition juce_Expression.cpp:1053
Expression operator-(const Expression &) const
Definition juce_Expression.cpp:1010
~Expression()
Definition juce_Expression.cpp:932
Type getType() const noexcept
Definition juce_Expression.cpp:1092
double evaluate() const
Definition juce_Expression.cpp:984
static Expression parse(String::CharPointerType &stringToParse, String &parseError)
Definition juce_Expression.cpp:976
int getNumInputs() const
Definition juce_Expression.cpp:1094
Expression getInput(int index) const
Definition juce_Expression.cpp:1095
bool referencesSymbol(const Symbol &symbol, const Scope &scope) const
Definition juce_Expression.cpp:1065
ReferenceCountedObjectPtr< Term > term
Definition juce_Expression.h:246
static Expression symbol(const String &symbol)
Definition juce_Expression.cpp:1014
Type
Definition juce_Expression.h:219
@ symbolType
Definition juce_Expression.h:223
@ functionType
Definition juce_Expression.h:221
@ constantType
Definition juce_Expression.h:220
@ operatorType
Definition juce_Expression.h:222
String toString() const
Definition juce_Expression.cpp:1090
Definition juce_HeapBlock.h:87
Definition juce_ReferenceCountedObject.h:247
ReferencedType * get() const noexcept
Definition juce_ReferenceCountedObject.h:381
Definition juce_String.h:53
CharPointerType getCharPointer() const noexcept
Definition juce_String.h:1153
String trim() const
Definition juce_String.cpp:1656
String toLowerCase() const
Definition juce_String.cpp:1474
static String charToString(juce_wchar character)
Definition juce_String.cpp:359
bool containsOnly(StringRef charactersItMightContain) const noexcept
Definition juce_String.cpp:1796
* e
Definition inflate.c:1404
int * l
Definition inflate.c:1579
struct huft * t
Definition inflate.c:943
unsigned v[N_MAX]
Definition inflate.c:1584
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
unsigned f
Definition inflate.c:1572
static const char * name
Definition pugl.h:1582
static uintptr_t parent
Definition pugl.h:1644
CARLA_PLUGIN_EXPORT int clone(int(*)(void *), void *, int, void *,...)
Definition interposer-safe.cpp:46
int val
Definition jpeglib.h:956
#define jassert(expression)
#define DBG(textToWrite)
#define JUCE_DECLARE_NON_COPYABLE(className)
#define jassertfalse
Definition carla_juce.cpp:31
constexpr Type jmin(Type a, Type b)
Definition juce_MathsFunctions.h:106
jack_client_t client jack_client_t client jack_client_t client jack_client_t JackInfoShutdownCallback void arg jack_client_t jack_port_t port void(* func)(const char *))
Definition juce_linux_JackAudio.cpp:67
constexpr Type jmax(Type a, Type b)
Definition juce_MathsFunctions.h:94
wchar_t juce_wchar
Definition juce_CharacterFunctions.h:42
void ignoreUnused(Types &&...) noexcept
Definition juce_MathsFunctions.h:333
unsigned char uint8
Definition juce_MathsFunctions.h:37
Definition juce_Uuid.h:141
#define false
Definition ordinals.h:83
Definition juce_Expression.cpp:82
friend class Expression::Term
Definition juce_Expression.cpp:91
static Term * findDestinationFor(Term *const topLevel, const Term *const inputTerm)
Definition juce_Expression.cpp:555
static void checkRecursionDepth(int depth)
Definition juce_Expression.cpp:85
static Constant * findTermToAdjust(Term *const term, const bool mustBeFlagged)
Definition juce_Expression.cpp:572
static bool containsAnySymbols(const Term &t)
Definition juce_Expression.cpp:612
ReferenceCountedObjectPtr< Term > TermPtr
Definition juce_Expression.cpp:83
Definition juce_Expression.h:186
String symbolName
Definition juce_Expression.h:192
String scopeUID
Definition juce_Expression.h:191
Symbol(const String &scopeUID, const String &symbolName)
Definition juce_Expression.cpp:1104
const char * text
Definition swell-functions.h:167
return c
Definition crypt.c:175
int r
Definition crypt.c:458
int result
Definition process.c:1455
#define const
Definition zconf.h:137