diff --git a/apps/sequence/app.cpp b/apps/sequence/app.cpp index b5ef4253e..3f01d17bc 100644 --- a/apps/sequence/app.cpp +++ b/apps/sequence/app.cpp @@ -67,4 +67,11 @@ Shared::SequenceContext * App::localContext() { return &m_sequenceContext; } +NestedMenuController * App::variableBoxForInputEventHandler(InputEventHandler * textInput) { + MathVariableBoxController * varBox = AppsContainer::sharedAppsContainer()->variableBoxController(); + varBox->setSender(textInput); + varBox->lockDeleteEvent(MathVariableBoxController::Page::Sequence); + return varBox; +} + } diff --git a/apps/sequence/app.h b/apps/sequence/app.h index 834c8d3ce..be61dd8cb 100644 --- a/apps/sequence/app.h +++ b/apps/sequence/app.h @@ -47,6 +47,7 @@ public: // TODO: override variableBoxForInputEventHandler to lock sequence in the variable box once they appear there // NestedMenuController * variableBoxForInputEventHandler(InputEventHandler * textInput) override; CodePoint XNT() override { return 'n'; } + NestedMenuController * variableBoxForInputEventHandler(InputEventHandler * textInput) override; Shared::SequenceContext * localContext() override; Shared::SequenceStore * functionStore() override { return static_cast(AppsContainer::sharedAppsContainer()->globalContext())->sequenceStore(); } Shared::Interval * interval() { return snapshot()->interval(); } diff --git a/apps/shared/cache_context.cpp b/apps/shared/cache_context.cpp index 0758ba9b4..3fcf76f43 100644 --- a/apps/shared/cache_context.cpp +++ b/apps/shared/cache_context.cpp @@ -30,12 +30,14 @@ const Expression CacheContext::expressionForSymbolAbstract(const Poincare::Sy return Float::Builder(m_values[index][1]); } Ion::Storage::Record record = m_sequenceContext->sequenceStore()->recordAtIndex(index); - Sequence * seq = m_sequenceContext->sequenceStore()->modelForRecord(record); - rank.replaceSymbolWithExpression(Symbol::Builder(UCodePointUnknown), Float::Builder(m_nValue)); - T n = PoincareHelpers::ApproximateToScalar(rank, this); - // In case the rank is not int or sequence referenced is not defined, return NAN - if (std::floor(n) == n && seq->fullName() != nullptr) { - return Float::Builder(seq->valueAtRank(n, m_sequenceContext)); + if (!record.isNull()) { + Sequence * seq = m_sequenceContext->sequenceStore()->modelForRecord(record); + rank.replaceSymbolWithExpression(Symbol::Builder(UCodePointUnknown), Float::Builder(m_nValue)); + T n = PoincareHelpers::ApproximateToScalar(rank, this); + // In case the rank is not int or sequence referenced is not defined, return NAN + if (std::floor(n) == n && seq->fullName() != nullptr) { + return Float::Builder(seq->valueAtRank(n, m_sequenceContext)); + } } else { return Float::Builder(NAN); } diff --git a/apps/shared/expression_model.h b/apps/shared/expression_model.h index b57ae5ac2..6fe6501a3 100644 --- a/apps/shared/expression_model.h +++ b/apps/shared/expression_model.h @@ -22,6 +22,7 @@ public: Ion::Storage::Record::ErrorStatus setExpressionContent(Ion::Storage::Record * record, const Poincare::Expression & newExpression); virtual void tidy() const; + bool hasValidExpression() { return !m_expression.isUninitialized(); } protected: // Setters helper static Poincare::Expression BuildExpressionFromText(const char * c, CodePoint symbol = 0, Poincare::Context * context = nullptr); diff --git a/apps/shared/global_context.cpp b/apps/shared/global_context.cpp index b5b6d6fe2..654c7737b 100644 --- a/apps/shared/global_context.cpp +++ b/apps/shared/global_context.cpp @@ -127,7 +127,7 @@ const Expression GlobalContext::ExpressionForSequence(const SymbolAbstract & sym char unknownN[bufferSize]; Poincare::SerializationHelper::CodePoint(unknownN, bufferSize, UCodePointUnknown); float rank = symbol.childAtIndex(0).approximateWithValueForSymbol(unknownN, unknownSymbolValue, ctx, Preferences::sharedPreferences()->complexFormat(),Preferences::sharedPreferences()->angleUnit()); - if (std::floor(rank) == rank) { + if (std::floor(rank) == rank && seq.hasValidExpression()) { SequenceContext sqctx(ctx, sequenceStore()); return Float::Builder(seq.evaluateXYAtParameter(rank, &sqctx).x2()); } else { diff --git a/apps/shared/sequence.h b/apps/shared/sequence.h index 016d12e23..dffbc45b8 100644 --- a/apps/shared/sequence.h +++ b/apps/shared/sequence.h @@ -59,6 +59,7 @@ public: Poincare::Layout nameLayout(); bool isDefined() override; bool isEmpty() override; + bool hasValidExpression() { return m_definition.hasValidExpression(); } // Approximation Poincare::Coordinate2D evaluateXYAtParameter(float x, Poincare::Context * context) const override { return Poincare::Coordinate2D(x, templatedApproximateAtAbscissa(x, static_cast(context))); diff --git a/apps/shared/sequence_context.cpp b/apps/shared/sequence_context.cpp index fc1f48738..528a2c359 100644 --- a/apps/shared/sequence_context.cpp +++ b/apps/shared/sequence_context.cpp @@ -87,9 +87,14 @@ void TemplatedSequenceContext::step(SequenceContext * sqctx, int sequenceInde SequenceStore * sequenceStore = sqctx->sequenceStore(); stop = stepMultipleSequences ? sequenceStore->numberOfModels() : start + 1; for (int i = start; i < stop; i++) { - Sequence * u = sequenceStore->modelForRecord(sequenceStore->recordAtIndex(i)); - int index = stepMultipleSequences ? SequenceStore::sequenceIndexForName(u->fullName()[0]) : 0; - sequences[index] = u->isDefined() ? u : nullptr; + Ion::Storage::Record record = sequenceStore->recordAtIndex(i); + if (!record.isNull()) { + Sequence * u = sequenceStore->modelForRecord(record); + int index = stepMultipleSequences ? SequenceStore::sequenceIndexForName(u->fullName()[0]) : 0; + sequences[index] = u->isDefined() ? u : nullptr; + } else { + sequences[i] = nullptr; + } } // We approximate the value of the next rank for each sequence we want to update