diff --git a/apps/calculation/Makefile b/apps/calculation/Makefile index c25380236..77906d671 100644 --- a/apps/calculation/Makefile +++ b/apps/calculation/Makefile @@ -8,7 +8,6 @@ app_objs += $(addprefix apps/calculation/,\ edit_expression_controller.o\ history_view_cell.o\ history_controller.o\ - local_context.o\ output_expressions_view.o\ scrollable_expression_view.o\ scrollable_output_expressions_view.o\ diff --git a/apps/calculation/app.cpp b/apps/calculation/app.cpp index 701ce5926..3807c7b01 100644 --- a/apps/calculation/app.cpp +++ b/apps/calculation/app.cpp @@ -44,16 +44,11 @@ void App::Snapshot::tidy() { App::App(Container * container, Snapshot * snapshot) : TextFieldDelegateApp(container, snapshot, &m_editExpressionController), - m_localContext((GlobalContext *)((AppsContainer *)container)->globalContext(), snapshot->calculationStore()), m_historyController(&m_editExpressionController, snapshot->calculationStore()), m_editExpressionController(&m_modalViewController, &m_historyController, snapshot->calculationStore()) { } -Context * App::localContext() { - return &m_localContext; -} - bool App::textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) { if ((event == Ion::Events::Var || event == Ion::Events::XNT) && TextFieldDelegateApp::textFieldDidReceiveEvent(textField, event)) { return true; diff --git a/apps/calculation/app.h b/apps/calculation/app.h index a9b616599..fdda07e99 100644 --- a/apps/calculation/app.h +++ b/apps/calculation/app.h @@ -4,7 +4,6 @@ #include "calculation_store.h" #include "edit_expression_controller.h" #include "history_controller.h" -#include "local_context.h" #include "../shared/text_field_delegate_app.h" #include @@ -28,12 +27,10 @@ public: void tidy() override; CalculationStore m_calculationStore; }; - Poincare::Context * localContext() override; bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override; const char * XNT() override; private: App(Container * container, Snapshot * snapshot); - LocalContext m_localContext; HistoryController m_historyController; EditExpressionController m_editExpressionController; }; diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 9abfd2b23..3768abd89 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -1,4 +1,5 @@ #include "calculation.h" +#include "calculation_store.h" #include #include using namespace Poincare; @@ -63,9 +64,10 @@ void Calculation::reset() { tidy(); } -void Calculation::setContent(const char * c, Context * context) { +void Calculation::setContent(const char * c, Context * context, CalculationStore * calculationStore) { reset(); m_input = Expression::parse(c); + Expression::ReplaceSymbolWithExpression(&m_input, Symbol::SpecialSymbols::Ans, ansExpression(calculationStore, context)); /* 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)); @@ -196,4 +198,16 @@ bool Calculation::shouldDisplayApproximateOutput(Context * context) { return input()->isApproximate(*context); } +Expression * Calculation::ansExpression(CalculationStore * calculationStore, Context * context) { + if (calculationStore->numberOfCalculations() == 0) { + static Rational defaultExpression(0); + return &defaultExpression; + } + Calculation * lastCalculation = calculationStore->calculationAtIndex(calculationStore->numberOfCalculations()-1); + if (lastCalculation->input()->isApproximate(*context)) { + return lastCalculation->approximateOutput(context); + } + return lastCalculation->exactOutput(context); +} + } diff --git a/apps/calculation/calculation.h b/apps/calculation/calculation.h index d6893d288..69b2ccf48 100644 --- a/apps/calculation/calculation.h +++ b/apps/calculation/calculation.h @@ -6,6 +6,8 @@ namespace Calculation { +class CalculationStore; + class Calculation { public: Calculation(); @@ -16,7 +18,7 @@ public: Calculation& operator=(Calculation&& other) = delete; /* c.reset() is the equivalent of c = Calculation() without copy assingment. */ void reset(); - void setContent(const char * c, Poincare::Context * context); + void setContent(const char * c, Poincare::Context * context, CalculationStore * calculationStore); const char * inputText(); const char * exactOutputText(); const char * approximateOutputText(); @@ -31,6 +33,7 @@ public: bool shouldDisplayApproximateOutput(Poincare::Context * context); constexpr static int k_printedExpressionSize = 2*::TextField::maxBufferSize(); private: + Poincare::Expression * ansExpression(CalculationStore * calculationStore, Poincare::Context * context); /* Buffers holding text expressions have to be longer than the text written * by user (of maximum length TextField::maxBufferSize()) because when we * print an expression we add omitted signs (multiplications, parenthesis...) */ diff --git a/apps/calculation/calculation_store.cpp b/apps/calculation/calculation_store.cpp index 6c8e3fa9d..b48ddbe4d 100644 --- a/apps/calculation/calculation_store.cpp +++ b/apps/calculation/calculation_store.cpp @@ -11,7 +11,7 @@ CalculationStore::CalculationStore() : Calculation * CalculationStore::push(const char * text, Context * context) { Calculation * result = &m_calculations[m_startIndex]; - result->setContent(text, context); + result->setContent(text, context, this); m_startIndex++; if (m_startIndex >= k_maxNumberOfCalculations) { m_startIndex = 0; diff --git a/apps/calculation/local_context.cpp b/apps/calculation/local_context.cpp deleted file mode 100644 index 9d3673e2c..000000000 --- a/apps/calculation/local_context.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "local_context.h" -#include -using namespace Poincare; - -namespace Calculation { - -LocalContext::LocalContext(GlobalContext * parentContext, CalculationStore * calculationStore) : - m_calculationStore(calculationStore), - m_parentContext(parentContext) -{ -} - -Expression * LocalContext::ansValue() { - if (m_calculationStore->numberOfCalculations() == 0) { - return defaultExpression(); - } - Calculation * lastCalculation = m_calculationStore->calculationAtIndex(m_calculationStore->numberOfCalculations()-1); - if (lastCalculation->input()->isApproximate(*m_parentContext)) { - return lastCalculation->approximateOutput(m_parentContext); - } - return lastCalculation->exactOutput(m_parentContext); -} - -Expression * LocalContext::defaultExpression() { - static Rational defaultExpression(0); - return &defaultExpression; -} - -void LocalContext::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) { - if (symbol->name() != Symbol::SpecialSymbols::Ans) { - m_parentContext->setExpressionForSymbolName(expression, symbol, context); - } -} - -const Expression * LocalContext::expressionForSymbol(const Symbol * symbol) { - if (symbol->name() == Symbol::SpecialSymbols::Ans) { - return ansValue(); - } else { - return m_parentContext->expressionForSymbol(symbol); - } -} - -} diff --git a/apps/calculation/local_context.h b/apps/calculation/local_context.h deleted file mode 100644 index 2a516e0fa..000000000 --- a/apps/calculation/local_context.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef CALCULATION_LOCAL_CONTEXT_H -#define CALCULATION_LOCAL_CONTEXT_H - -#include -#include "calculation_store.h" - -namespace Calculation { - -class LocalContext : public Poincare::Context { -public: - LocalContext(Poincare::GlobalContext * parentContext, CalculationStore * calculationStore); - void setExpressionForSymbolName(const Poincare::Expression * expression, const Poincare::Symbol * symbol, Context & context) override; - const Poincare::Expression * expressionForSymbol(const Poincare::Symbol * symbol) override; -private: - Poincare::Expression * ansValue(); - static Poincare::Expression * defaultExpression(); - CalculationStore * m_calculationStore; - Poincare::GlobalContext * m_parentContext; -}; - -} - -#endif diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 5d6831c96..a00a0df53 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -155,6 +155,7 @@ public: /* Constructor & Destructor */ static Expression * parse(char const * string); + static void ReplaceSymbolWithExpression(Expression ** expressionAddress, char symbol, Expression * expression); virtual ~Expression() = default; virtual Expression * clone() const = 0; @@ -242,6 +243,7 @@ protected: * interruption to avoid freezing in the simplification process. */ static int SimplificationOrder(const Expression * e1, const Expression * e2, bool canBeInterrupted = false); private: + virtual Expression * replaceSymbolWithExpression(char symbol, Expression * expression); /* Properties */ virtual Expression * setSign(Sign s, Context & context, AngleUnit angleUnit) { assert(false); return nullptr; } /* Comparison */ diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 422dd1990..3a270420f 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -41,6 +41,7 @@ public: bool hasAnExactRepresentation(Context & context) const; private: const char * textForSpecialSymbols(char name) const; + Expression * replaceSymbolWithExpression(char symbol, Expression * expression) override; /* Simplification */ Expression * shallowReduce(Context& context, AngleUnit angleUnit) override; /* Comparison */ diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 32631bcf6..b818bf12c 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -40,6 +40,19 @@ Expression * Expression::parse(char const * string) { return expression; } +void Expression::ReplaceSymbolWithExpression(Expression ** expressionAddress, char symbol, Expression * expression) { + SimplificationRoot root(*expressionAddress); + root.editableOperand(0)->replaceSymbolWithExpression(symbol, expression); + *expressionAddress = root.editableOperand(0); +} + +Expression * Expression::replaceSymbolWithExpression(char symbol, Expression * expression) { + for (int i = 0; i < numberOfOperands(); i++) { + editableOperand(i)->replaceSymbolWithExpression(symbol, expression); + } + return this; +} + /* Circuit breaker */ static Expression::CircuitBreaker sCircuitBreaker = nullptr; diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 04b3c8fd4..7677fb298 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -97,6 +97,13 @@ Expression * Symbol::clone() const { return new Symbol(m_name); } +Expression * Symbol::replaceSymbolWithExpression(char symbol, Expression * expression) { + if (m_name == symbol) { + return replaceWith(expression->clone(), true); + } + return this; +} + Expression::Sign Symbol::sign() const { /* TODO: Maybe, we will want to know that from a context given in parameter: if (context.expressionForSymbol(this) != nullptr) {