[poincare][apps] Replace Ans symbol when preprocessing the calculation

This commit is contained in:
Émilie Feral
2018-01-04 10:02:37 +01:00
committed by EmilieNumworks
parent 17fc7998a2
commit 775432efdc
12 changed files with 43 additions and 78 deletions

View File

@@ -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\

View File

@@ -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;

View File

@@ -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 <escher.h>
@@ -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;
};

View File

@@ -1,4 +1,5 @@
#include "calculation.h"
#include "calculation_store.h"
#include <string.h>
#include <cmath>
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);
}
}

View File

@@ -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...) */

View File

@@ -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;

View File

@@ -1,43 +0,0 @@
#include "local_context.h"
#include <string.h>
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);
}
}
}

View File

@@ -1,23 +0,0 @@
#ifndef CALCULATION_LOCAL_CONTEXT_H
#define CALCULATION_LOCAL_CONTEXT_H
#include <poincare.h>
#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

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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) {