mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-30 12:10:03 +02:00
[poincare] Automatically detach a tree before adding it
This commit is contained in:
@@ -44,6 +44,7 @@ public:
|
||||
m_numberOfChildren-= decrement;
|
||||
}
|
||||
void eraseNumberOfChildren() override { m_numberOfChildren = 0; }
|
||||
void childAtIndexWillBeStolen(int index) override;
|
||||
#if POINCARE_TREE_LOG
|
||||
virtual void logNodeName(std::ostream & stream) const override {
|
||||
stream << "HorizontalLayout";
|
||||
|
||||
@@ -17,6 +17,7 @@ public:
|
||||
m_numberOfChildren-= decrement;
|
||||
}
|
||||
void eraseNumberOfChildren() override { m_numberOfChildren = 0; }
|
||||
void childAtIndexWillBeStolen(int index) override;
|
||||
|
||||
// Comparison
|
||||
typedef int (*ExpressionOrder)(const ExpressionNode * e1, const ExpressionNode * e2, bool canBeInterrupted);
|
||||
|
||||
@@ -83,6 +83,9 @@ public:
|
||||
int indexOfChild(TreeByReference t) const {
|
||||
return node()->indexOfChild(t.node());
|
||||
}
|
||||
void childAtIndexWillBeStolen(int index) {
|
||||
node()->childAtIndexWillBeStolen(index);
|
||||
}
|
||||
|
||||
/* Hierarchy operations */
|
||||
// Replace
|
||||
@@ -90,6 +93,10 @@ public:
|
||||
void replaceChildInPlace(TreeByReference oldChild, TreeByReference newChild);
|
||||
void replaceChildAtIndexInPlace(int oldChildIndex, TreeByReference newChild);
|
||||
void replaceWithAllocationFailureInPlace(int currentNumberOfChildren);
|
||||
void replaceChildAtIndexWithGhostInPlace(int index) {
|
||||
assert(index >= 0 && index < numberOfChildren());
|
||||
replaceChildWithGhostInPlace(childAtIndex(index));
|
||||
}
|
||||
void replaceChildWithGhostInPlace(TreeByReference t);
|
||||
// Merge
|
||||
void mergeChildrenAtIndexInPlace(TreeByReference t, int i);
|
||||
@@ -124,6 +131,7 @@ protected:
|
||||
int m_identifier;
|
||||
|
||||
private:
|
||||
void detachFromParent();
|
||||
// Add ghost children on layout construction
|
||||
void buildGhostChildren();
|
||||
};
|
||||
|
||||
@@ -69,6 +69,8 @@ public:
|
||||
bool hasChild(const TreeNode * child) const;
|
||||
bool hasAncestor(const TreeNode * node, bool includeSelf) const;
|
||||
bool hasSibling(const TreeNode * e) const;
|
||||
// Prepare a child that will be stolen by another Expression
|
||||
virtual void childAtIndexWillBeStolen(int index);
|
||||
// AddChild collateral effect
|
||||
virtual void didAddChildAtIndex(int newNumberOfChildren) {}
|
||||
|
||||
|
||||
@@ -193,6 +193,10 @@ bool HorizontalLayoutNode::hasText() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void HorizontalLayoutNode::childAtIndexWillBeStolen(int index) {
|
||||
HorizontalLayoutRef(this).removeChildAtIndex(index, nullptr);
|
||||
}
|
||||
|
||||
// Protected
|
||||
|
||||
KDSize HorizontalLayoutNode::computeSize() {
|
||||
|
||||
@@ -36,6 +36,10 @@ Expression NAryExpressionNode::squashUnaryHierarchy() {
|
||||
return copy;
|
||||
}
|
||||
|
||||
void NAryExpressionNode::childAtIndexWillBeStolen(int index) {
|
||||
NAryExpression(this).removeChildAtIndexInPlace(index);
|
||||
}
|
||||
|
||||
// Private
|
||||
|
||||
int NAryExpressionNode::simplificationOrderSameType(const ExpressionNode * e, bool canBeInterrupted) const {
|
||||
|
||||
@@ -68,6 +68,9 @@ void TreeByReference::replaceChildInPlace(TreeByReference oldChild, TreeByRefere
|
||||
return;
|
||||
}
|
||||
|
||||
// If the new child has a parent, detach from it
|
||||
newChild.detachFromParent();
|
||||
|
||||
// Move the new child
|
||||
assert(newChild.isGhost() || newChild.parent().isUninitialized());
|
||||
TreePool::sharedPool()->move(oldChild.node(), newChild.node(), newChild.numberOfChildren());
|
||||
@@ -144,6 +147,10 @@ void TreeByReference::replaceChildWithGhostInPlace(TreeByReference t) {
|
||||
}
|
||||
|
||||
void TreeByReference::mergeChildrenAtIndexInPlace(TreeByReference t, int i) {
|
||||
/* mergeChildrenAtIndexInPlace should only be called with a tree thant can
|
||||
* have any number of children, so there is no need to replace the stolen
|
||||
* children with ghosts. */
|
||||
// TODO assert this and t are "dynamic" trees
|
||||
assert(i >= 0 && i <= numberOfChildren());
|
||||
// Steal operands
|
||||
int numberOfNewChildren = t.numberOfChildren();
|
||||
@@ -196,8 +203,8 @@ void TreeByReference::addChildAtIndexInPlace(TreeByReference t, int index, int c
|
||||
replaceWithAllocationFailureInPlace(currentNumberOfChildren);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(index >= 0 && index <= currentNumberOfChildren);
|
||||
assert(t.parent().isUninitialized());
|
||||
|
||||
// If the new node is static, copy it in the pool and add the copy
|
||||
if (t.isStatic()) {
|
||||
@@ -210,6 +217,10 @@ void TreeByReference::addChildAtIndexInPlace(TreeByReference t, int index, int c
|
||||
return;
|
||||
}
|
||||
|
||||
// If t has a parent, detach t from it.
|
||||
t.detachFromParent();
|
||||
assert(t.parent().isUninitialized());
|
||||
|
||||
// Move t
|
||||
TreeNode * newChildPosition = node()->next();
|
||||
for (int i = 0; i < index; i++) {
|
||||
@@ -251,6 +262,15 @@ void TreeByReference::removeChildrenInPlace(int currentNumberOfChildren) {
|
||||
|
||||
/* Private */
|
||||
|
||||
void TreeByReference::detachFromParent() {
|
||||
TreeByReference myParent = parent();
|
||||
if (!myParent.isUninitialized()) {
|
||||
int idxInParent = myParent.indexOfChild(*this);
|
||||
myParent.childAtIndexWillBeStolen(idxInParent);
|
||||
}
|
||||
assert(parent().isUninitialized());
|
||||
}
|
||||
|
||||
void TreeByReference::setTo(const TreeByReference & tr) {
|
||||
/* We cannot use (*this)==tr because tr would need to be casted to
|
||||
* TreeByReference, which calls setTo and triggers an infinite loop */
|
||||
|
||||
@@ -192,6 +192,10 @@ TreeNode * TreeNode::nextSibling() const {
|
||||
return node;
|
||||
}
|
||||
|
||||
void TreeNode::childAtIndexWillBeStolen(int index) {
|
||||
TreeByReference(this).replaceChildAtIndexWithGhostInPlace(index);
|
||||
}
|
||||
|
||||
TreeNode * TreeNode::lastDescendant() const {
|
||||
TreeNode * node = const_cast<TreeNode *>(this);
|
||||
int remainingNodesToVisit = node->numberOfChildren();
|
||||
|
||||
Reference in New Issue
Block a user