diff --git a/apps/regression/regression_context.cpp b/apps/regression/regression_context.cpp index bd79b9247..b7d480743 100644 --- a/apps/regression/regression_context.cpp +++ b/apps/regression/regression_context.cpp @@ -9,7 +9,7 @@ using namespace Shared; namespace Regression { -const Expression RegressionContext::expressionForSymbol(const SymbolAbstract & symbol) { +const Expression RegressionContext::expressionForSymbol(const SymbolAbstract & symbol, bool clone) { if (symbol.type() == ExpressionNode::Type::Symbol && Symbol::isRegressionSymbol(symbol.name())) { const char * seriesName = symbol.name(); assert(strlen(seriesName) == 2); @@ -24,7 +24,7 @@ const Expression RegressionContext::expressionForSymbol(const SymbolAbstract & s assert(m_seriesPairIndex < m_store->numberOfPairsOfSeries(series)); return Float(m_store->get(series, storeI, m_seriesPairIndex)); } else { - return m_parentContext->expressionForSymbol(symbol); + return m_parentContext->expressionForSymbol(symbol, clone); } } diff --git a/apps/regression/regression_context.h b/apps/regression/regression_context.h index fe9e9bf24..d2c92ef5d 100644 --- a/apps/regression/regression_context.h +++ b/apps/regression/regression_context.h @@ -9,7 +9,7 @@ namespace Regression { class RegressionContext : public Shared::StoreContext { public: using Shared::StoreContext::StoreContext; - const Poincare::Expression expressionForSymbol(const Poincare::SymbolAbstract & symbol) override; + const Poincare::Expression expressionForSymbol(const Poincare::SymbolAbstract & symbol, bool clone) override; }; } diff --git a/apps/sequence/cache_context.cpp b/apps/sequence/cache_context.cpp index 8e37f6b98..b16a3d4f3 100644 --- a/apps/sequence/cache_context.cpp +++ b/apps/sequence/cache_context.cpp @@ -15,7 +15,7 @@ CacheContext::CacheContext(Context * parentContext) : } template -const Expression CacheContext::expressionForSymbol(const SymbolAbstract & symbol) { +const Expression CacheContext::expressionForSymbol(const SymbolAbstract & symbol, bool clone) { // [u|v](n(+1)?) if (symbol.type() == ExpressionNode::Type::Symbol && (symbol.name()[0] == SequenceStore::k_sequenceNames[0][0] || symbol.name()[0] == SequenceStore::k_sequenceNames[1][0]) @@ -24,7 +24,7 @@ const Expression CacheContext::expressionForSymbol(const SymbolAbstract & sym Symbol s = const_cast(static_cast(symbol)); return Float(m_values[nameIndexForSymbol(s)][rankIndexForSymbol(s)]); } - return VariableContext::expressionForSymbol(symbol); + return VariableContext::expressionForSymbol(symbol, clone); } template diff --git a/apps/sequence/cache_context.h b/apps/sequence/cache_context.h index 4ae6b556a..e9dc40560 100644 --- a/apps/sequence/cache_context.h +++ b/apps/sequence/cache_context.h @@ -13,7 +13,7 @@ template class CacheContext : public Poincare::VariableContext { public: CacheContext(Poincare::Context * parentContext); - const Poincare::Expression expressionForSymbol(const Poincare::SymbolAbstract & symbol) override; + const Poincare::Expression expressionForSymbol(const Poincare::SymbolAbstract & symbol, bool clone) override; void setValueForSymbol(T value, const Poincare::Symbol & symbol); private: int nameIndexForSymbol(const Poincare::Symbol & symbol); diff --git a/apps/sequence/sequence_context.h b/apps/sequence/sequence_context.h index 121bc3390..6b3216aa7 100644 --- a/apps/sequence/sequence_context.h +++ b/apps/sequence/sequence_context.h @@ -45,8 +45,8 @@ public: * context respective methods. Indeed, special chars like n, u(n), u(n+1), * v(n), v(n+1) are taken into accound only when evaluating sequences which * is done in another context. */ - const Poincare::Expression expressionForSymbol(const Poincare::SymbolAbstract & symbol) override { - return m_parentContext->expressionForSymbol(symbol); + const Poincare::Expression expressionForSymbol(const Poincare::SymbolAbstract & symbol, bool clone) override { + return m_parentContext->expressionForSymbol(symbol, clone); } void setExpressionForSymbol(const Poincare::Expression & expression, const Poincare::SymbolAbstract & symbol, Poincare::Context & context) override { m_parentContext->setExpressionForSymbol(expression, symbol, context); diff --git a/apps/shared/global_context.cpp b/apps/shared/global_context.cpp index 2da769330..83e4da400 100644 --- a/apps/shared/global_context.cpp +++ b/apps/shared/global_context.cpp @@ -60,7 +60,7 @@ void GlobalContext::DestroyRecordsBaseNamedWithoutExtension(const char * baseNam } } -const Expression GlobalContext::expressionForSymbol(const SymbolAbstract & symbol) { +const Expression GlobalContext::expressionForSymbol(const SymbolAbstract & symbol, bool clone) { Ion::Storage::Record r = SymbolAbstractRecordWithBaseName(symbol.name()); return ExpressionForSymbolAndRecord(symbol, r); } diff --git a/apps/shared/global_context.h b/apps/shared/global_context.h index 436cf9f12..d94ac7d0a 100644 --- a/apps/shared/global_context.h +++ b/apps/shared/global_context.h @@ -38,7 +38,7 @@ public: /* Expression for symbol * The expression recorded in global context is already an expression. * Otherwise, we would need the context and the angle unit to evaluate it */ - const Poincare::Expression expressionForSymbol(const Poincare::SymbolAbstract & symbol) override; + const Poincare::Expression expressionForSymbol(const Poincare::SymbolAbstract & symbol, bool clone) override; void setExpressionForSymbol( const Poincare::Expression & expression, const Poincare::SymbolAbstract & symbol, diff --git a/apps/statistics/statistics_context.cpp b/apps/statistics/statistics_context.cpp index 46f744c00..1f5260ee9 100644 --- a/apps/statistics/statistics_context.cpp +++ b/apps/statistics/statistics_context.cpp @@ -9,7 +9,7 @@ using namespace Shared; namespace Statistics { -const Expression StatisticsContext::expressionForSymbol(const SymbolAbstract & symbol) { +const Expression StatisticsContext::expressionForSymbol(const SymbolAbstract & symbol, bool clone) { if (symbol.type() == ExpressionNode::Type::Symbol && Symbol::isSeriesSymbol(symbol.name())) { const char * seriesName = symbol.name(); assert(strlen(seriesName) == 2); @@ -24,7 +24,7 @@ const Expression StatisticsContext::expressionForSymbol(const SymbolAbstract & s assert(m_seriesPairIndex < m_store->numberOfPairsOfSeries(series)); return Float(m_store->get(series, storeI, m_seriesPairIndex)); } else { - return m_parentContext->expressionForSymbol(symbol); + return m_parentContext->expressionForSymbol(symbol, clone); } } diff --git a/apps/statistics/statistics_context.h b/apps/statistics/statistics_context.h index 8cdd2f082..833dff458 100644 --- a/apps/statistics/statistics_context.h +++ b/apps/statistics/statistics_context.h @@ -8,7 +8,7 @@ namespace Statistics { class StatisticsContext : public Shared::StoreContext { public: using Shared::StoreContext::StoreContext; - const Poincare::Expression expressionForSymbol(const Poincare::SymbolAbstract & symbol) override; + const Poincare::Expression expressionForSymbol(const Poincare::SymbolAbstract & symbol, bool clone) override; }; } diff --git a/poincare/include/poincare/context.h b/poincare/include/poincare/context.h index 327dd4ab2..c42b209a4 100644 --- a/poincare/include/poincare/context.h +++ b/poincare/include/poincare/context.h @@ -8,7 +8,7 @@ class SymbolAbstract; class Context { public: - virtual const Expression expressionForSymbol(const SymbolAbstract & symbol) = 0; + virtual const Expression expressionForSymbol(const SymbolAbstract & symbol, bool clone) = 0; virtual void setExpressionForSymbol(const Expression & expression, const SymbolAbstract & symbol, Context & context) = 0; }; diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index f61023106..4a30ea42e 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -82,7 +82,7 @@ public: Expression replaceReplaceableSymbols(Context & context); private: SymbolNode * node() const { return static_cast(Expression::node()); } - Expression expand(Context & context) const; + Expression expand(Context & context, bool cloneContextValue) const; }; } diff --git a/poincare/include/poincare/symbol_abstract.h b/poincare/include/poincare/symbol_abstract.h index a8ead1f62..e5310240a 100644 --- a/poincare/include/poincare/symbol_abstract.h +++ b/poincare/include/poincare/symbol_abstract.h @@ -58,7 +58,7 @@ public: static size_t TruncateExtension(char * dst, const char * src, size_t len); static bool ValidInContext(SymbolAbstract & s, Context * context) { // Retrive from context the expression corresponding to s - Expression f = context ? context->expressionForSymbol(s) : Expression(); + Expression f = context ? context->expressionForSymbol(s, false) : Expression(); return f.isUninitialized() || f.type() == s.type(); } constexpr static size_t k_maxNameSize = 8; diff --git a/poincare/include/poincare/variable_context.h b/poincare/include/poincare/variable_context.h index 26c1d58a1..27af51ff9 100644 --- a/poincare/include/poincare/variable_context.h +++ b/poincare/include/poincare/variable_context.h @@ -14,7 +14,7 @@ public: // Context void setExpressionForSymbol(const Expression & expression, const SymbolAbstract & symbol, Context & context) override; - const Expression expressionForSymbol(const SymbolAbstract & symbol) override; + const Expression expressionForSymbol(const SymbolAbstract & symbol, bool clone) override; private: const char * m_name; diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 7c1c5b883..f1b76a907 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -227,9 +227,9 @@ bool Expression::hasReplaceableSymbols(Context & context) const { return recursivelyMatches([](const Expression e, Context & context, bool replaceSymbols) { return (e.type() == ExpressionNode::Type::Symbol && !static_cast(e).isSystemSymbol() - && !context.expressionForSymbol(static_cast(e)).isUninitialized()) + && !context.expressionForSymbol(static_cast(e), false).isUninitialized()) || (e.type() == ExpressionNode::Type::Function - && !context.expressionForSymbol(static_cast(e)).isUninitialized()); + && !context.expressionForSymbol(static_cast(e), false).isUninitialized()); }, context, false); } diff --git a/poincare/src/function.cpp b/poincare/src/function.cpp index 6d6d20067..14f47930b 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -121,7 +121,7 @@ Expression Function::shallowReduce(Context & context, Preferences::AngleUnit ang } Expression Function::replaceReplaceableSymbols(Context & context) { - Expression e = context.expressionForSymbol(*this); + Expression e = context.expressionForSymbol(*this, true); if (e.isUninitialized()) { return *this; } @@ -131,7 +131,7 @@ Expression Function::replaceReplaceableSymbols(Context & context) { } Expression Function::expand(Context & context) const { - Expression e = context.expressionForSymbol(*this); + Expression e = context.expressionForSymbol(*this, true); e = ExpressionWithoutSymbols(e, context); if (!e.isUninitialized()) { e = e.replaceSymbolWithExpression(Symbol(Symbol::SpecialSymbols::UnknownX), childAtIndex(0)); @@ -155,7 +155,7 @@ VariableContext Function::unknownXContext(Context & parentContext) const { /* If the parentContext already has an expression for UnknownX, we have to * replace in childAtIndex(0) any occurence of UnknownX by its value in * parentContext. That way, we handle: evaluatin f(x-1) with x = 2 & f:x->x^2 */ - Expression unknownXValue = parentContext.expressionForSymbol(unknownXSymbol); + Expression unknownXValue = parentContext.expressionForSymbol(unknownXSymbol, true); if (!unknownXValue.isUninitialized()) { xContext = static_cast(parentContext); // copy the parentContext child.replaceSymbolWithExpression(unknownXSymbol, unknownXValue); diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 161ff1ed0..c8a2108ff 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -47,7 +47,7 @@ Evaluation StoreNode::templatedApproximate(Context& context, Preferences::Ang Store s(this); assert(!s.value().isUninitialized()); context.setExpressionForSymbol(s.value(), s.symbol(), context); - Expression e = context.expressionForSymbol(s.symbol()); + Expression e = context.expressionForSymbol(s.symbol(), false); if (e.isUninitialized()) { return Complex::Undefined(); } @@ -68,7 +68,7 @@ Expression Store::shallowReduce(Context & context, Preferences::AngleUnit angleU } assert(!finalValue.isUninitialized()); context.setExpressionForSymbol(finalValue, symbol(), context); - Expression e = context.expressionForSymbol(symbol()); + Expression e = context.expressionForSymbol(symbol(), true); if (e.isUninitialized()) { return Undefined(); } diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index f15f1145b..77ddae679 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -17,8 +17,8 @@ constexpr char Symbol::k_ans[]; /*ExpressionNode::Sign SymbolNode::sign() const { TODO: Maybe, we will want to know that from a context given in parameter: - if (context.expressionForSymbol(this) != nullptr) { - return context.expressionForSymbol(this)->sign(context); + if (context.expressionForSymbol(this, false) != nullptr) { + return context.expressionForSymbol(this, false)->sign(context); } } */ @@ -126,7 +126,7 @@ Expression SymbolNode::replaceReplaceableSymbols(Context & context) { template Evaluation SymbolNode::templatedApproximate(Context& context, Preferences::AngleUnit angleUnit) const { - Expression e = Symbol(this).expand(context); + Expression e = Symbol(this).expand(context, false); if (e.isUninitialized()) { return Complex::Undefined(); } @@ -156,7 +156,7 @@ bool Symbol::isRegressionSymbol(const char * c) { } bool Symbol::matches(ExpressionTest test, Context & context) const { - Expression e = expand(context); + Expression e = expand(context, false); return !e.isUninitialized() && test(e, context, true); } @@ -164,7 +164,7 @@ Expression Symbol::shallowReduce(Context & context, Preferences::AngleUnit angle if (!replaceSymbols) { return *this; } - Expression result = expand(context); + Expression result = expand(context, true); if (result.isUninitialized()) { return *this; } @@ -200,7 +200,7 @@ Expression Symbol::replaceReplaceableSymbols(Context & context) { if (isSystemSymbol()) { return *this; } - Expression e = context.expressionForSymbol(*this); + Expression e = context.expressionForSymbol(*this, true); if (e.isUninitialized()) { return *this; } @@ -208,10 +208,10 @@ Expression Symbol::replaceReplaceableSymbols(Context & context) { return e; } -Expression Symbol::expand(Context & context) const { +Expression Symbol::expand(Context & context, bool clone) const { /* Replace all the symbols iteratively. This prevents a memory failure when * symbols are defined circularly. */ - Expression e = context.expressionForSymbol(*this); + Expression e = context.expressionForSymbol(*this, clone); return ExpressionWithoutSymbols(e, context); } diff --git a/poincare/src/variable_context.cpp b/poincare/src/variable_context.cpp index 858f18c58..b0ebbbcde 100644 --- a/poincare/src/variable_context.cpp +++ b/poincare/src/variable_context.cpp @@ -29,11 +29,11 @@ void VariableContext::setExpressionForSymbol(const Expression & expression, cons } } -const Expression VariableContext::expressionForSymbol(const SymbolAbstract & symbol) { +const Expression VariableContext::expressionForSymbol(const SymbolAbstract & symbol, bool clone) { if (strcmp(symbol.name(), m_name) == 0) { - return m_value.clone(); + return clone ? m_value.clone() : m_value; } else { - return m_parentContext->expressionForSymbol(symbol); + return m_parentContext->expressionForSymbol(symbol, clone); } }