diff --git a/poincare/include/poincare/evaluation.h b/poincare/include/poincare/evaluation.h index 78960b168..1b726abbc 100644 --- a/poincare/include/poincare/evaluation.h +++ b/poincare/include/poincare/evaluation.h @@ -32,6 +32,9 @@ public: virtual Expression complexToExpression(Preferences::ComplexFormat complexFormat) const = 0; virtual std::complex trace() const = 0; virtual std::complex determinant() const = 0; + + // TreeNode + TreeNode * uninitializedStaticNode() const override; }; template diff --git a/poincare/include/poincare/expression_node.h b/poincare/include/poincare/expression_node.h index f95435d9f..4523fac09 100644 --- a/poincare/include/poincare/expression_node.h +++ b/poincare/include/poincare/expression_node.h @@ -153,6 +153,10 @@ public: /* Hierarchy */ ExpressionNode * childAtIndex(int i) const override { return static_cast(TreeNode::childAtIndex(i)); } + + + // TreeNode + TreeNode * uninitializedStaticNode() const override; protected: // Private methods used in simplification process /*!*/ virtual Expression denominator(Context & context, Preferences::AngleUnit angleUnit) const; diff --git a/poincare/include/poincare/ghost_node.h b/poincare/include/poincare/ghost_node.h index 73e3209bb..8495bee49 100644 --- a/poincare/include/poincare/ghost_node.h +++ b/poincare/include/poincare/ghost_node.h @@ -21,14 +21,33 @@ public: // Allocation Failure static GhostNode * FailedAllocationStaticNode(); TreeNode * failedAllocationStaticNode() override { return FailedAllocationStaticNode(); } + // Uninitialized + TreeNode * uninitializedStaticNode() const override; +}; + +class UninitializedGhostNode : public GhostNode { +public: + static UninitializedGhostNode * UninitializedGhostStaticNode(); + + size_t size() const override { return sizeof(UninitializedGhostNode); } + bool isUninitialized() const override { return true; } + GhostNode * failedAllocationStaticNode() override { assert(false); return nullptr; } //TODO ? + int numberOfChildren() const override { return 0; } +#if POINCARE_TREE_LOG + virtual void logNodeName(std::ostream & stream) const override { + stream << "UninitializedGhost"; + } +#endif }; class AllocationFailedGhostNode : public GhostNode { public: // TreeNode size_t size() const override { return sizeof(AllocationFailedGhostNode); } -#if TREE_LOG - const char * description() const override { return "AllocationFailedGhost"; } +#if POINCARE_TREE_LOG + virtual void logNodeName(std::ostream & stream) const override { + stream << "AllocationFailedGhost"; + } #endif bool isAllocationFailure() const override { return true; } }; diff --git a/poincare/include/poincare/layout_node.h b/poincare/include/poincare/layout_node.h index 052437f96..7cf263e4e 100644 --- a/poincare/include/poincare/layout_node.h +++ b/poincare/include/poincare/layout_node.h @@ -129,6 +129,10 @@ public: virtual void didReplaceChildAtIndex(int index, LayoutCursor * cursor, bool force) {} virtual bool willRemoveChild(LayoutNode * l, LayoutCursor * cursor, bool force); virtual void didRemoveChildAtIndex(int index, LayoutCursor * cursor, bool force) {} + + // TreeNode + TreeNode * uninitializedStaticNode() const override; + protected: // Tree navigation virtual void moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited); diff --git a/poincare/include/poincare/tree_node.h b/poincare/include/poincare/tree_node.h index 5ce75c46a..8f59aa2f3 100644 --- a/poincare/include/poincare/tree_node.h +++ b/poincare/include/poincare/tree_node.h @@ -38,6 +38,7 @@ public: // Uninitialized node virtual bool isUninitialized() const { return false; } + virtual TreeNode * uninitializedStaticNode() const = 0; // Ghost virtual bool isGhost() const { return false; } diff --git a/poincare/src/evaluation.cpp b/poincare/src/evaluation.cpp index bc678d704..c415259a6 100644 --- a/poincare/src/evaluation.cpp +++ b/poincare/src/evaluation.cpp @@ -4,6 +4,11 @@ namespace Poincare { +template +TreeNode * EvaluationNode::uninitializedStaticNode() const { + return Evaluation().node(); +} + template Evaluation::Evaluation() : Evaluation(UninitializedEvaluationNode::UninitializedEvaluationStaticNode()) {} @@ -12,6 +17,8 @@ Expression Evaluation::complexToExpression(Preferences::ComplexFormat complex return node()->complexToExpression(complexFormat); } +template TreeNode * EvaluationNode::uninitializedStaticNode() const; +template TreeNode * EvaluationNode::uninitializedStaticNode() const; template Evaluation::Evaluation(); template Evaluation::Evaluation(); template Expression Evaluation::complexToExpression(Preferences::ComplexFormat) const; diff --git a/poincare/src/expression_node.cpp b/poincare/src/expression_node.cpp index ebe5a3de2..8bfc12230 100644 --- a/poincare/src/expression_node.cpp +++ b/poincare/src/expression_node.cpp @@ -93,6 +93,10 @@ bool ExpressionNode::isOfType(Type * types, int length) const { return false; } +TreeNode * ExpressionNode::uninitializedStaticNode() const { + return Expression().node(); +} + Expression ExpressionNode::denominator(Context & context, Preferences::AngleUnit angleUnit) const { return Expression(); } diff --git a/poincare/src/ghost_node.cpp b/poincare/src/ghost_node.cpp index 9853cdcab..ccf3706e9 100644 --- a/poincare/src/ghost_node.cpp +++ b/poincare/src/ghost_node.cpp @@ -3,10 +3,20 @@ namespace Poincare { +TreeNode * GhostNode::uninitializedStaticNode() const { + return UninitializedGhostNode::UninitializedGhostStaticNode(); +} + GhostNode * GhostNode::FailedAllocationStaticNode() { static AllocationFailedGhostNode failure; TreePool::sharedPool()->registerStaticNodeIfRequired(&failure); return &failure; } +UninitializedGhostNode * UninitializedGhostNode::UninitializedGhostStaticNode() { + static UninitializedGhostNode exception; + TreePool::sharedPool()->registerStaticNodeIfRequired(&exception); + return &exception; +} + } diff --git a/poincare/src/layout_node.cpp b/poincare/src/layout_node.cpp index 0b1b0c6d9..1122e2a07 100644 --- a/poincare/src/layout_node.cpp +++ b/poincare/src/layout_node.cpp @@ -144,6 +144,12 @@ bool LayoutNode::canBeOmittedMultiplicationRightFactor() const { return isCollapsable(&numberOfOpenParentheses, false) && !isVerticalOffset(); } +// TreeNode + +TreeNode * LayoutNode::uninitializedStaticNode() const { + return LayoutReference().node(); +} + // Private void LayoutNode::moveCursorVertically(VerticalDirection direction, LayoutCursor * cursor, bool * shouldRecomputeLayout, bool equivalentPositionVisited) { diff --git a/poincare/src/tree_node.cpp b/poincare/src/tree_node.cpp index 38ac52bb1..9172d2d38 100644 --- a/poincare/src/tree_node.cpp +++ b/poincare/src/tree_node.cpp @@ -38,7 +38,7 @@ void TreeNode::rename(int identifier, bool unregisterPreviousIdentifier) { TreeNode * TreeNode::parent() const { if (isStatic()) { - return nullptr; + return uninitializedStaticNode(); } /* Choose between these algorithms: the first has complexity O(numberNodes) * but uses O(3maxNumberNodes) space. The second is much clearer for the diff --git a/poincare/test/tree/blob_node.cpp b/poincare/test/tree/blob_node.cpp index 89b783506..c0ec2a10b 100644 --- a/poincare/test/tree/blob_node.cpp +++ b/poincare/test/tree/blob_node.cpp @@ -2,10 +2,20 @@ namespace Poincare { +TreeNode * BlobNode::uninitializedStaticNode() const { + return UninitializedBlobNode::UninitializedBlobStaticNode(); +} + BlobNode * BlobNode::FailedAllocationStaticNode() { static AllocationFailureBlobNode failureNode; TreePool::sharedPool()->registerStaticNodeIfRequired(&failureNode); return &failureNode; } +UninitializedBlobNode * UninitializedBlobNode::UninitializedBlobStaticNode() { + static UninitializedBlobNode exception; + TreePool::sharedPool()->registerStaticNodeIfRequired(&exception); + return &exception; +} + } diff --git a/poincare/test/tree/blob_node.h b/poincare/test/tree/blob_node.h index bf0badf36..5fa905bf0 100644 --- a/poincare/test/tree/blob_node.h +++ b/poincare/test/tree/blob_node.h @@ -13,6 +13,8 @@ public: virtual BlobNode * failedAllocationStaticNode() override { return BlobNode::FailedAllocationStaticNode(); } + TreeNode * uninitializedStaticNode() const override; + virtual size_t size() const override { return sizeof(BlobNode); } int data() { return m_data; } void setData(int data) { m_data = data; } @@ -26,6 +28,21 @@ private: int m_data; }; +class UninitializedBlobNode : public BlobNode { +public: + static UninitializedBlobNode * UninitializedBlobStaticNode(); + + size_t size() const override { return sizeof(UninitializedBlobNode); } + bool isUninitialized() const override { return true; } + BlobNode * failedAllocationStaticNode() override { assert(false); return nullptr; } //TODO ? + int numberOfChildren() const override { return 0; } +#if POINCARE_TREE_LOG + virtual void logNodeName(std::ostream & stream) const override { + stream << "UninitializedBlob"; + } +#endif +}; + class AllocationFailureBlobNode : public BlobNode { size_t size() const override { return sizeof(AllocationFailureBlobNode); } bool isAllocationFailure() const override { return true; } diff --git a/poincare/test/tree/pair_node.cpp b/poincare/test/tree/pair_node.cpp index c8cbe129d..52497c623 100644 --- a/poincare/test/tree/pair_node.cpp +++ b/poincare/test/tree/pair_node.cpp @@ -2,10 +2,20 @@ namespace Poincare { +TreeNode * PairNode::uninitializedStaticNode() const { + return UninitializedPairNode::UninitializedPairStaticNode(); +} + PairNode * PairNode::FailedAllocationStaticNode() { static AllocationFailurePairNode failureNode; TreePool::sharedPool()->registerStaticNodeIfRequired(&failureNode); return &failureNode; } +UninitializedPairNode * UninitializedPairNode::UninitializedPairStaticNode() { + static UninitializedPairNode exception; + TreePool::sharedPool()->registerStaticNodeIfRequired(&exception); + return &exception; +} + } diff --git a/poincare/test/tree/pair_node.h b/poincare/test/tree/pair_node.h index b4bd11aeb..8d48ce211 100644 --- a/poincare/test/tree/pair_node.h +++ b/poincare/test/tree/pair_node.h @@ -13,6 +13,8 @@ public: virtual PairNode * failedAllocationStaticNode() override { return PairNode::FailedAllocationStaticNode(); } + TreeNode * uninitializedStaticNode() const override; + virtual size_t size() const override { return sizeof(PairNode); } virtual int numberOfChildren() const override { return 2; } #if POINCARE_TREE_LOG @@ -22,6 +24,21 @@ public: #endif }; +class UninitializedPairNode : public PairNode { +public: + static UninitializedPairNode * UninitializedPairStaticNode(); + + size_t size() const override { return sizeof(UninitializedPairNode); } + bool isUninitialized() const override { return true; } + PairNode * failedAllocationStaticNode() override { assert(false); return nullptr; } //TODO ? + int numberOfChildren() const override { return 0; } +#if POINCARE_TREE_LOG + virtual void logNodeName(std::ostream & stream) const override { + stream << "UninitializedPairNode"; + } +#endif +}; + class AllocationFailurePairNode : public PairNode { size_t size() const override { return sizeof(AllocationFailurePairNode); } bool isAllocationFailure() const override { return true; }