mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[poincare][apps] Replace Ans symbol when preprocessing the calculation
This commit is contained in:
committed by
EmilieNumworks
parent
17fc7998a2
commit
775432efdc
@@ -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\
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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...) */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user