diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 3768abd89..d64202749 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -71,8 +71,7 @@ void Calculation::setContent(const char * c, Context * context, CalculationStore /* We do not store directly the text enter by the user but its serialization * to be able to compare it to the exact ouput text. */ m_input->writeTextInBuffer(m_inputText, sizeof(m_inputText)); - m_exactOutput = input()->clone(); - Expression::Simplify(&m_exactOutput, *context); + m_exactOutput = Expression::ParseAndSimplify(m_inputText, *context); m_exactOutput->writeTextInBuffer(m_exactOutputText, sizeof(m_exactOutputText)); m_approximateOutput = m_exactOutput->approximate(*context); m_approximateOutput->writeTextInBuffer(m_approximateOutputText, sizeof(m_approximateOutputText)); @@ -148,13 +147,8 @@ void Calculation::tidy() { Expression * Calculation::exactOutput(Context * context) { if (m_exactOutput == nullptr) { /* To ensure that the expression 'm_exactOutput' is a simplified, we - * call 'simplifyAndBeautify'. */ - m_exactOutput = Expression::parse(m_exactOutputText); - if (m_exactOutput != nullptr) { - Expression::Simplify(&m_exactOutput, *context); - } else { - m_exactOutput = new Undefined(); - } + * call 'ParseAndSimplify'. */ + m_exactOutput = Expression::ParseAndSimplify(m_exactOutputText, *context); } return m_exactOutput; } diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index 6658dbc0a..b0bfe3ae2 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -149,20 +149,14 @@ void Sequence::setInitialRank(int rank) { Poincare::Expression * Sequence::firstInitialConditionExpression(Context * context) const { if (m_firstInitialConditionExpression == nullptr) { - m_firstInitialConditionExpression = Poincare::Expression::parse(m_firstInitialConditionText); - if (m_firstInitialConditionExpression) { - Expression::Simplify(&m_firstInitialConditionExpression, *context); - } + m_firstInitialConditionExpression = Poincare::Expression::ParseAndSimplify(m_firstInitialConditionText, *context); } return m_firstInitialConditionExpression; } Poincare::Expression * Sequence::secondInitialConditionExpression(Context * context) const { if (m_secondInitialConditionExpression == nullptr) { - m_secondInitialConditionExpression = Poincare::Expression::parse(m_secondInitialConditionText); - if (m_secondInitialConditionExpression) { - Expression::Simplify(&m_secondInitialConditionExpression, *context); - } + m_secondInitialConditionExpression = Poincare::Expression::ParseAndSimplify(m_secondInitialConditionText, *context); } return m_secondInitialConditionExpression; } diff --git a/apps/shared/function.cpp b/apps/shared/function.cpp index dd4e46444..2c36c64cc 100644 --- a/apps/shared/function.cpp +++ b/apps/shared/function.cpp @@ -71,10 +71,7 @@ const char * Function::name() const { Poincare::Expression * Function::expression(Poincare::Context * context) const { if (m_expression == nullptr) { - m_expression = Expression::parse(m_text); - if (m_expression) { - Expression::Simplify(&m_expression, *context); - } + m_expression = Expression::ParseAndSimplify(m_text, *context); } return m_expression; } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 87b5b4987..44dd1cb89 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -217,6 +217,7 @@ public: virtual int writeTextInBuffer(char * buffer, int bufferSize) const = 0; /* Simplification */ + static Expression * ParseAndSimplify(const char * text, Context & context, AngleUnit angleUnit = AngleUnit::Default); static void Simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit = AngleUnit::Default); /* Evaluation Engine diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 120d674c6..5116d63df 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -56,6 +56,7 @@ Expression * Expression::replaceSymbolWithExpression(char symbol, Expression * e /* Circuit breaker */ static Expression::CircuitBreaker sCircuitBreaker = nullptr; +static bool sSimplificationHasBeenInterrupted = false; void Expression::setCircuitBreaker(CircuitBreaker cb) { sCircuitBreaker = cb; @@ -65,7 +66,11 @@ bool Expression::shouldStopProcessing() { if (sCircuitBreaker == nullptr) { return false; } - return sCircuitBreaker(); + if (sCircuitBreaker()) { + sSimplificationHasBeenInterrupted = true; + return true; + } + return false; } /* Hierarchy */ @@ -229,7 +234,20 @@ ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, C /* Simplification */ +Expression * Expression::ParseAndSimplify(const char * text, Context & context, AngleUnit angleUnit) { + Expression * exp = parse(text); + if (exp == nullptr) { + return new Undefined(); + } + Simplify(&exp, context, angleUnit); + if (exp == nullptr) { + return parse(text); + } + return exp; +} + void Expression::Simplify(Expression ** expressionAddress, Context & context, AngleUnit angleUnit) { + sSimplificationHasBeenInterrupted = false; if (angleUnit == AngleUnit::Default) { angleUnit = Preferences::sharedPreferences()->angleUnit(); } @@ -243,6 +261,11 @@ void Expression::Simplify(Expression ** expressionAddress, Context & context, An root.editableOperand(0)->deepReduce(context, angleUnit); root.editableOperand(0)->deepBeautify(context, angleUnit); *expressionAddress = root.editableOperand(0); + if (sSimplificationHasBeenInterrupted) { + root.detachOperands(); + delete *expressionAddress; + *expressionAddress = nullptr; + } } @@ -310,8 +333,7 @@ template T Expression::approximateToScalar(Context& context, AngleUn } template T Expression::approximateToScalar(const char * text, Context& context, AngleUnit angleUnit) { - Expression * exp = parse(text); - Simplify(&exp, context, angleUnit); + Expression * exp = ParseAndSimplify(text, context, angleUnit); T result = exp->approximateToScalar(context, angleUnit); delete exp; return result;