diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 5c316964bf..1b8b6ffaf9 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -1600,35 +1600,12 @@ RelativeTime& RelativeTime::operator= (const RelativeTime& other) throw() return *this; } -bool RelativeTime::operator== (const RelativeTime& other) const throw() -{ - return seconds == other.seconds; -} - -bool RelativeTime::operator!= (const RelativeTime& other) const throw() -{ - return seconds != other.seconds; -} - -bool RelativeTime::operator> (const RelativeTime& other) const throw() -{ - return seconds > other.seconds; -} - -bool RelativeTime::operator< (const RelativeTime& other) const throw() -{ - return seconds < other.seconds; -} - -bool RelativeTime::operator>= (const RelativeTime& other) const throw() -{ - return seconds >= other.seconds; -} - -bool RelativeTime::operator<= (const RelativeTime& other) const throw() -{ - return seconds <= other.seconds; -} +bool RelativeTime::operator== (const RelativeTime& other) const throw() { return seconds == other.seconds; } +bool RelativeTime::operator!= (const RelativeTime& other) const throw() { return seconds != other.seconds; } +bool RelativeTime::operator> (const RelativeTime& other) const throw() { return seconds > other.seconds; } +bool RelativeTime::operator< (const RelativeTime& other) const throw() { return seconds < other.seconds; } +bool RelativeTime::operator>= (const RelativeTime& other) const throw() { return seconds >= other.seconds; } +bool RelativeTime::operator<= (const RelativeTime& other) const throw() { return seconds <= other.seconds; } const RelativeTime RelativeTime::operator+ (const RelativeTime& timeToAdd) const throw() { @@ -4617,6 +4594,7 @@ public: Constant (const double value_, bool isResolutionTarget_) : value (value_), isResolutionTarget (isResolutionTarget_) {} + Type getType() const throw() { return constantType; } Term* clone() const { return new Constant (value, isResolutionTarget); } double evaluate (const EvaluationContext&, int) const { return value; } int getNumInputs() const { return 0; } @@ -4667,9 +4645,11 @@ public: return 0; } + Type getType() const throw() { return symbolType; } Term* clone() const { return new Symbol (mainSymbol, member); } int getNumInputs() const { return 0; } Term* getInput (int) const { return 0; } + const String getFunctionName() const { return toString(); } const String toString() const { @@ -4716,9 +4696,11 @@ public: return c.evaluateFunction (functionName, params, parameters.size()); } - int getInputIndexFor (const Term* possibleInput) const { return parameters.indexOf (possibleInput); } - int getNumInputs() const { return parameters.size(); } - Term* getInput (int i) const { return parameters [i]; } + Type getType() const throw() { return functionType; } + int getInputIndexFor (const Term* possibleInput) const { return parameters.indexOf (possibleInput); } + int getNumInputs() const { return parameters.size(); } + Term* getInput (int i) const { return parameters [i]; } + const String getFunctionName() const { return functionName; } bool referencesSymbol (const String& s, const EvaluationContext& c, int recursionDepth) const { @@ -4760,11 +4742,13 @@ public: jassert (input_ != 0); } + Type getType() const throw() { return operatorType; } int getInputIndexFor (const Term* possibleInput) const { return possibleInput == input ? 0 : -1; } int getNumInputs() const { return 1; } Term* getInput (int index) const { return index == 0 ? static_cast (input) : 0; } Term* clone() const { return new Negate (input->clone()); } double evaluate (const EvaluationContext& c, int recursionDepth) const { return -input->evaluate (c, recursionDepth); } + const String getFunctionName() const { return "-"; } const TermPtr negated() { @@ -4811,6 +4795,8 @@ public: return possibleInput == left ? 0 : (possibleInput == right ? 1 : -1); } + Type getType() const throw() { return operatorType; } + int getNumInputs() const { return 2; } Term* getInput (int index) const { return index == 0 ? static_cast (left) : (index == 1 ? static_cast (right) : 0); } @@ -4820,10 +4806,7 @@ public: || right->referencesSymbol (s, c, recursionDepth); } - protected: - const TermPtr left, right; - - const String createString (const String& op) const + const String toString() const { String s; @@ -4833,7 +4816,7 @@ public: else s = left->toString(); - s << ' ' << op << ' '; + s << ' ' << getFunctionName() << ' '; if (right->getOperatorPrecedence() >= ourPrecendence) s << '(' << right->toString() << ')'; @@ -4843,6 +4826,9 @@ public: return s; } + protected: + const TermPtr left, right; + const TermPtr createDestinationTerm (const EvaluationContext& context, const Term* input, double overallTarget, Term* topLevelTerm) const { jassert (input == left || input == right); @@ -4863,10 +4849,10 @@ public: public: Add (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {} - Term* clone() const { return new Add (left->clone(), right->clone()); } + Term* clone() const { return new Add (left->clone(), right->clone()); } double evaluate (const EvaluationContext& c, int recursionDepth) const { return left->evaluate (c, recursionDepth) + right->evaluate (c, recursionDepth); } - const String toString() const { return createString ("+"); } - int getOperatorPrecedence() const { return 2; } + int getOperatorPrecedence() const { return 2; } + const String getFunctionName() const { return "+"; } const TermPtr createTermToEvaluateInput (const EvaluationContext& c, const Term* input, double overallTarget, Term* topLevelTerm) const { @@ -4883,10 +4869,10 @@ public: public: Subtract (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {} - Term* clone() const { return new Subtract (left->clone(), right->clone()); } + Term* clone() const { return new Subtract (left->clone(), right->clone()); } double evaluate (const EvaluationContext& c, int recursionDepth) const { return left->evaluate (c, recursionDepth) - right->evaluate (c, recursionDepth); } - const String toString() const { return createString ("-"); } - int getOperatorPrecedence() const { return 2; } + int getOperatorPrecedence() const { return 2; } + const String getFunctionName() const { return "-"; } const TermPtr createTermToEvaluateInput (const EvaluationContext& c, const Term* input, double overallTarget, Term* topLevelTerm) const { @@ -4906,10 +4892,10 @@ public: public: Multiply (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {} - Term* clone() const { return new Multiply (left->clone(), right->clone()); } + Term* clone() const { return new Multiply (left->clone(), right->clone()); } double evaluate (const EvaluationContext& c, int recursionDepth) const { return left->evaluate (c, recursionDepth) * right->evaluate (c, recursionDepth); } - const String toString() const { return createString ("*"); } - int getOperatorPrecedence() const { return 1; } + const String getFunctionName() const { return "*"; } + int getOperatorPrecedence() const { return 1; } const TermPtr createTermToEvaluateInput (const EvaluationContext& c, const Term* input, double overallTarget, Term* topLevelTerm) const { @@ -4926,10 +4912,10 @@ public: public: Divide (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {} - Term* clone() const { return new Divide (left->clone(), right->clone()); } + Term* clone() const { return new Divide (left->clone(), right->clone()); } double evaluate (const EvaluationContext& c, int recursionDepth) const { return left->evaluate (c, recursionDepth) / right->evaluate (c, recursionDepth); } - const String toString() const { return createString ("/"); } - int getOperatorPrecedence() const { return 1; } + const String getFunctionName() const { return "/"; } + int getOperatorPrecedence() const { return 1; } const TermPtr createTermToEvaluateInput (const EvaluationContext& c, const Term* input, double overallTarget, Term* topLevelTerm) const { @@ -5444,6 +5430,36 @@ bool Expression::usesAnySymbols() const return Helpers::containsAnySymbols (term); } +Expression::Type Expression::getType() const throw() +{ + return term->getType(); +} + +const String Expression::getSymbol() const +{ + return term->getSymbolName(); +} + +const String Expression::getFunction() const +{ + return term->getFunctionName(); +} + +const String Expression::getOperator() const +{ + return term->getFunctionName(); +} + +int Expression::getNumInputs() const +{ + return term->getNumInputs(); +} + +const Expression Expression::getInput (int index) const +{ + return Expression (term->getInput (index)); +} + int Expression::Term::getOperatorPrecedence() const { return 0; @@ -5470,6 +5486,18 @@ const ReferenceCountedObjectPtr Expression::Term::negated() return new Helpers::Negate (this); } +const String Expression::Term::getSymbolName() const +{ + jassertfalse; // You should only call getSymbol() on an expression that's actually a symbol! + return String::empty; +} + +const String Expression::Term::getFunctionName() const +{ + jassertfalse; // You shouldn't call this for an expression that's not actually a function! + return String::empty; +} + Expression::ParseError::ParseError (const String& message) : description (message) { @@ -276206,6 +276234,16 @@ public: if (JUCEApplication::getInstance() != 0) { JUCEApplication::getInstance()->systemRequestedQuit(); + + if (MessageManager::getInstance()->hasStopMessageBeenSent()) + { + [NSApp performSelectorOnMainThread: @selector (replyToApplicationShouldTerminate:) + withObject: [NSNumber numberWithBool: YES] + waitUntilDone: NO]; + + return NSTerminateLater; + } + return NSTerminateCancel; } diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 5c1f53ef1e..64910b25a8 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -64,7 +64,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 58 +#define JUCE_BUILDNUMBER 59 /** Current Juce version number. @@ -6651,11 +6651,13 @@ public: /** Evaluates this expression, without using an EvaluationContext. Without an EvaluationContext, no symbols can be used, and only basic functions such as sin, cos, tan, min, max are available. + @throws Expression::EvaluationError */ double evaluate() const; /** Evaluates this expression, providing a context that should be able to evaluate any symbols or functions that it uses. + @throws Expression::EvaluationError */ double evaluate (const EvaluationContext& context) const; @@ -6665,6 +6667,8 @@ public: E.g. if the expression is "x + 10" and x is 5, then asking for a target value of 8 will return the expression "x + 3". Obviously some expressions can't be reversed in this way, in which case they might just be adjusted by adding a constant to them. + + @throws Expression::EvaluationError */ const Expression adjustedToGiveNewResult (double targetValue, const EvaluationContext& context) const; @@ -6675,6 +6679,8 @@ public: If a suitable context is supplied, the search will dereference and recursively check all symbols, so that it can be determined whether this expression relies on the given symbol at any level in its evaluation. + + @throws Expression::EvaluationError */ bool referencesSymbol (const String& symbol, const EvaluationContext& context) const; @@ -6699,6 +6705,41 @@ public: String description; }; + /** Expression type. + @see Expression::getType() + */ + enum Type + { + constantType, + functionType, + operatorType, + symbolType + }; + + /** Returns the type of this expression. */ + Type getType() const throw(); + + /** If this expression is a symbol, this returns its name. */ + const String getSymbol() const; + + /** If this expression is a function, this returns its name. */ + const String getFunction() const; + + /** If this expression is an operator, this returns its name. + E.g. "+", "-", "*", "/", etc. + */ + const String getOperator() const; + + /** Returns the number of inputs to this expression. + @see getInput + */ + int getNumInputs() const; + + /** Retrieves one of the inputs to this expression. + @see getNumInputs + */ + const Expression getInput (int index) const; + juce_UseDebuggingNewOperator private: @@ -6722,6 +6763,10 @@ private: virtual const ReferenceCountedObjectPtr createTermToEvaluateInput (const EvaluationContext&, const Term* inputTerm, double overallTarget, Term* topLevelTerm) const; virtual const ReferenceCountedObjectPtr negated(); + virtual Type getType() const throw() = 0; + virtual const String getSymbolName() const; + virtual const String getFunctionName() const; + juce_UseDebuggingNewOperator private: diff --git a/src/containers/juce_Expression.cpp b/src/containers/juce_Expression.cpp index 3910e73e2a..54f7425dfa 100644 --- a/src/containers/juce_Expression.cpp +++ b/src/containers/juce_Expression.cpp @@ -44,6 +44,7 @@ public: Constant (const double value_, bool isResolutionTarget_) : value (value_), isResolutionTarget (isResolutionTarget_) {} + Type getType() const throw() { return constantType; } Term* clone() const { return new Constant (value, isResolutionTarget); } double evaluate (const EvaluationContext&, int) const { return value; } int getNumInputs() const { return 0; } @@ -95,9 +96,11 @@ public: return 0; } + Type getType() const throw() { return symbolType; } Term* clone() const { return new Symbol (mainSymbol, member); } int getNumInputs() const { return 0; } Term* getInput (int) const { return 0; } + const String getFunctionName() const { return toString(); } const String toString() const { @@ -145,9 +148,11 @@ public: return c.evaluateFunction (functionName, params, parameters.size()); } - int getInputIndexFor (const Term* possibleInput) const { return parameters.indexOf (possibleInput); } - int getNumInputs() const { return parameters.size(); } - Term* getInput (int i) const { return parameters [i]; } + Type getType() const throw() { return functionType; } + int getInputIndexFor (const Term* possibleInput) const { return parameters.indexOf (possibleInput); } + int getNumInputs() const { return parameters.size(); } + Term* getInput (int i) const { return parameters [i]; } + const String getFunctionName() const { return functionName; } bool referencesSymbol (const String& s, const EvaluationContext& c, int recursionDepth) const { @@ -190,11 +195,13 @@ public: jassert (input_ != 0); } + Type getType() const throw() { return operatorType; } int getInputIndexFor (const Term* possibleInput) const { return possibleInput == input ? 0 : -1; } int getNumInputs() const { return 1; } Term* getInput (int index) const { return index == 0 ? static_cast (input) : 0; } Term* clone() const { return new Negate (input->clone()); } double evaluate (const EvaluationContext& c, int recursionDepth) const { return -input->evaluate (c, recursionDepth); } + const String getFunctionName() const { return "-"; } const TermPtr negated() { @@ -242,6 +249,8 @@ public: return possibleInput == left ? 0 : (possibleInput == right ? 1 : -1); } + Type getType() const throw() { return operatorType; } + int getNumInputs() const { return 2; } Term* getInput (int index) const { return index == 0 ? static_cast (left) : (index == 1 ? static_cast (right) : 0); } @@ -251,10 +260,7 @@ public: || right->referencesSymbol (s, c, recursionDepth); } - protected: - const TermPtr left, right; - - const String createString (const String& op) const + const String toString() const { String s; @@ -264,7 +270,7 @@ public: else s = left->toString(); - s << ' ' << op << ' '; + s << ' ' << getFunctionName() << ' '; if (right->getOperatorPrecedence() >= ourPrecendence) s << '(' << right->toString() << ')'; @@ -274,6 +280,9 @@ public: return s; } + protected: + const TermPtr left, right; + const TermPtr createDestinationTerm (const EvaluationContext& context, const Term* input, double overallTarget, Term* topLevelTerm) const { jassert (input == left || input == right); @@ -295,10 +304,10 @@ public: public: Add (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {} - Term* clone() const { return new Add (left->clone(), right->clone()); } + Term* clone() const { return new Add (left->clone(), right->clone()); } double evaluate (const EvaluationContext& c, int recursionDepth) const { return left->evaluate (c, recursionDepth) + right->evaluate (c, recursionDepth); } - const String toString() const { return createString ("+"); } - int getOperatorPrecedence() const { return 2; } + int getOperatorPrecedence() const { return 2; } + const String getFunctionName() const { return "+"; } const TermPtr createTermToEvaluateInput (const EvaluationContext& c, const Term* input, double overallTarget, Term* topLevelTerm) const { @@ -316,10 +325,10 @@ public: public: Subtract (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {} - Term* clone() const { return new Subtract (left->clone(), right->clone()); } + Term* clone() const { return new Subtract (left->clone(), right->clone()); } double evaluate (const EvaluationContext& c, int recursionDepth) const { return left->evaluate (c, recursionDepth) - right->evaluate (c, recursionDepth); } - const String toString() const { return createString ("-"); } - int getOperatorPrecedence() const { return 2; } + int getOperatorPrecedence() const { return 2; } + const String getFunctionName() const { return "-"; } const TermPtr createTermToEvaluateInput (const EvaluationContext& c, const Term* input, double overallTarget, Term* topLevelTerm) const { @@ -340,10 +349,10 @@ public: public: Multiply (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {} - Term* clone() const { return new Multiply (left->clone(), right->clone()); } + Term* clone() const { return new Multiply (left->clone(), right->clone()); } double evaluate (const EvaluationContext& c, int recursionDepth) const { return left->evaluate (c, recursionDepth) * right->evaluate (c, recursionDepth); } - const String toString() const { return createString ("*"); } - int getOperatorPrecedence() const { return 1; } + const String getFunctionName() const { return "*"; } + int getOperatorPrecedence() const { return 1; } const TermPtr createTermToEvaluateInput (const EvaluationContext& c, const Term* input, double overallTarget, Term* topLevelTerm) const { @@ -361,10 +370,10 @@ public: public: Divide (Term* const left_, Term* const right_) : BinaryTerm (left_, right_) {} - Term* clone() const { return new Divide (left->clone(), right->clone()); } + Term* clone() const { return new Divide (left->clone(), right->clone()); } double evaluate (const EvaluationContext& c, int recursionDepth) const { return left->evaluate (c, recursionDepth) / right->evaluate (c, recursionDepth); } - const String toString() const { return createString ("/"); } - int getOperatorPrecedence() const { return 1; } + const String getFunctionName() const { return "/"; } + int getOperatorPrecedence() const { return 1; } const TermPtr createTermToEvaluateInput (const EvaluationContext& c, const Term* input, double overallTarget, Term* topLevelTerm) const { @@ -883,6 +892,36 @@ bool Expression::usesAnySymbols() const return Helpers::containsAnySymbols (term); } +Expression::Type Expression::getType() const throw() +{ + return term->getType(); +} + +const String Expression::getSymbol() const +{ + return term->getSymbolName(); +} + +const String Expression::getFunction() const +{ + return term->getFunctionName(); +} + +const String Expression::getOperator() const +{ + return term->getFunctionName(); +} + +int Expression::getNumInputs() const +{ + return term->getNumInputs(); +} + +const Expression Expression::getInput (int index) const +{ + return Expression (term->getInput (index)); +} + //============================================================================== int Expression::Term::getOperatorPrecedence() const { @@ -910,6 +949,18 @@ const ReferenceCountedObjectPtr Expression::Term::negated() return new Helpers::Negate (this); } +const String Expression::Term::getSymbolName() const +{ + jassertfalse; // You should only call getSymbol() on an expression that's actually a symbol! + return String::empty; +} + +const String Expression::Term::getFunctionName() const +{ + jassertfalse; // You shouldn't call this for an expression that's not actually a function! + return String::empty; +} + //============================================================================== Expression::ParseError::ParseError (const String& message) : description (message) diff --git a/src/containers/juce_Expression.h b/src/containers/juce_Expression.h index d10e894244..e573209636 100644 --- a/src/containers/juce_Expression.h +++ b/src/containers/juce_Expression.h @@ -129,11 +129,13 @@ public: /** Evaluates this expression, without using an EvaluationContext. Without an EvaluationContext, no symbols can be used, and only basic functions such as sin, cos, tan, min, max are available. + @throws Expression::EvaluationError */ double evaluate() const; /** Evaluates this expression, providing a context that should be able to evaluate any symbols or functions that it uses. + @throws Expression::EvaluationError */ double evaluate (const EvaluationContext& context) const; @@ -143,6 +145,8 @@ public: E.g. if the expression is "x + 10" and x is 5, then asking for a target value of 8 will return the expression "x + 3". Obviously some expressions can't be reversed in this way, in which case they might just be adjusted by adding a constant to them. + + @throws Expression::EvaluationError */ const Expression adjustedToGiveNewResult (double targetValue, const EvaluationContext& context) const; @@ -153,6 +157,8 @@ public: If a suitable context is supplied, the search will dereference and recursively check all symbols, so that it can be determined whether this expression relies on the given symbol at any level in its evaluation. + + @throws Expression::EvaluationError */ bool referencesSymbol (const String& symbol, const EvaluationContext& context) const; @@ -179,6 +185,42 @@ public: String description; }; + //============================================================================== + /** Expression type. + @see Expression::getType() + */ + enum Type + { + constantType, + functionType, + operatorType, + symbolType + }; + + /** Returns the type of this expression. */ + Type getType() const throw(); + + /** If this expression is a symbol, this returns its name. */ + const String getSymbol() const; + + /** If this expression is a function, this returns its name. */ + const String getFunction() const; + + /** If this expression is an operator, this returns its name. + E.g. "+", "-", "*", "/", etc. + */ + const String getOperator() const; + + /** Returns the number of inputs to this expression. + @see getInput + */ + int getNumInputs() const; + + /** Retrieves one of the inputs to this expression. + @see getNumInputs + */ + const Expression getInput (int index) const; + //============================================================================== juce_UseDebuggingNewOperator @@ -203,6 +245,10 @@ private: virtual const ReferenceCountedObjectPtr createTermToEvaluateInput (const EvaluationContext&, const Term* inputTerm, double overallTarget, Term* topLevelTerm) const; virtual const ReferenceCountedObjectPtr negated(); + virtual Type getType() const throw() = 0; + virtual const String getSymbolName() const; + virtual const String getFunctionName() const; + juce_UseDebuggingNewOperator private: diff --git a/src/core/juce_RelativeTime.cpp b/src/core/juce_RelativeTime.cpp index 45ab1f077e..960f718c58 100644 --- a/src/core/juce_RelativeTime.cpp +++ b/src/core/juce_RelativeTime.cpp @@ -183,35 +183,12 @@ RelativeTime& RelativeTime::operator= (const RelativeTime& other) throw() return *this; } -bool RelativeTime::operator== (const RelativeTime& other) const throw() -{ - return seconds == other.seconds; -} - -bool RelativeTime::operator!= (const RelativeTime& other) const throw() -{ - return seconds != other.seconds; -} - -bool RelativeTime::operator> (const RelativeTime& other) const throw() -{ - return seconds > other.seconds; -} - -bool RelativeTime::operator< (const RelativeTime& other) const throw() -{ - return seconds < other.seconds; -} - -bool RelativeTime::operator>= (const RelativeTime& other) const throw() -{ - return seconds >= other.seconds; -} - -bool RelativeTime::operator<= (const RelativeTime& other) const throw() -{ - return seconds <= other.seconds; -} +bool RelativeTime::operator== (const RelativeTime& other) const throw() { return seconds == other.seconds; } +bool RelativeTime::operator!= (const RelativeTime& other) const throw() { return seconds != other.seconds; } +bool RelativeTime::operator> (const RelativeTime& other) const throw() { return seconds > other.seconds; } +bool RelativeTime::operator< (const RelativeTime& other) const throw() { return seconds < other.seconds; } +bool RelativeTime::operator>= (const RelativeTime& other) const throw() { return seconds >= other.seconds; } +bool RelativeTime::operator<= (const RelativeTime& other) const throw() { return seconds <= other.seconds; } //============================================================================== const RelativeTime RelativeTime::operator+ (const RelativeTime& timeToAdd) const throw() diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index cf55c8651a..47d4d5eba8 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 58 +#define JUCE_BUILDNUMBER 59 /** Current Juce version number. diff --git a/src/native/mac/juce_mac_MessageManager.mm b/src/native/mac/juce_mac_MessageManager.mm index f2d22ba156..e30a27007a 100644 --- a/src/native/mac/juce_mac_MessageManager.mm +++ b/src/native/mac/juce_mac_MessageManager.mm @@ -69,6 +69,16 @@ public: if (JUCEApplication::getInstance() != 0) { JUCEApplication::getInstance()->systemRequestedQuit(); + + if (MessageManager::getInstance()->hasStopMessageBeenSent()) + { + [NSApp performSelectorOnMainThread: @selector (replyToApplicationShouldTerminate:) + withObject: [NSNumber numberWithBool: YES] + waitUntilDone: NO]; + + return NSTerminateLater; + } + return NSTerminateCancel; }