[poincare] TreeNode::parent() should never return nullptr

This commit is contained in:
Léa Saviot
2018-08-14 17:53:32 +02:00
parent cd43d84b1e
commit 942e1a8f25
14 changed files with 115 additions and 3 deletions

View File

@@ -32,6 +32,9 @@ public:
virtual Expression complexToExpression(Preferences::ComplexFormat complexFormat) const = 0;
virtual std::complex<T> trace() const = 0;
virtual std::complex<T> determinant() const = 0;
// TreeNode
TreeNode * uninitializedStaticNode() const override;
};
template<typename T>

View File

@@ -153,6 +153,10 @@ public:
/* Hierarchy */
ExpressionNode * childAtIndex(int i) const override { return static_cast<ExpressionNode *>(TreeNode::childAtIndex(i)); }
// TreeNode
TreeNode * uninitializedStaticNode() const override;
protected:
// Private methods used in simplification process
/*!*/ virtual Expression denominator(Context & context, Preferences::AngleUnit angleUnit) const;

View File

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

View File

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

View File

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

View File

@@ -4,6 +4,11 @@
namespace Poincare {
template<typename T>
TreeNode * EvaluationNode<T>::uninitializedStaticNode() const {
return Evaluation<T>().node();
}
template<typename T>
Evaluation<T>::Evaluation() : Evaluation<T>(UninitializedEvaluationNode<T>::UninitializedEvaluationStaticNode()) {}
@@ -12,6 +17,8 @@ Expression Evaluation<T>::complexToExpression(Preferences::ComplexFormat complex
return node()->complexToExpression(complexFormat);
}
template TreeNode * EvaluationNode<float>::uninitializedStaticNode() const;
template TreeNode * EvaluationNode<double>::uninitializedStaticNode() const;
template Evaluation<float>::Evaluation();
template Evaluation<double>::Evaluation();
template Expression Evaluation<float>::complexToExpression(Preferences::ComplexFormat) const;

View File

@@ -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();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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