@@ -57,8 +57,9 @@ bool syntax::Leaf::classof(const Node *N) {
57
57
}
58
58
59
59
syntax::Node::Node (NodeKind Kind)
60
- : Parent(nullptr ), NextSibling(nullptr ), Kind(static_cast <unsigned >(Kind)),
61
- Role(0 ), Original(false ), CanModify(false ) {
60
+ : Parent(nullptr ), NextSibling(nullptr ), PreviousSibling(nullptr ),
61
+ Kind(static_cast <unsigned >(Kind)), Role(0 ), Original(false ),
62
+ CanModify(false ) {
62
63
this ->setRole (NodeRole::Detached);
63
64
}
64
65
@@ -74,6 +75,30 @@ bool syntax::Tree::classof(const Node *N) {
74
75
return N->getKind () > NodeKind::Leaf;
75
76
}
76
77
78
+ void syntax::Tree::appendChildLowLevel (Node *Child, NodeRole Role) {
79
+ assert (Child->getRole () == NodeRole::Detached);
80
+ assert (Role != NodeRole::Detached);
81
+
82
+ Child->setRole (Role);
83
+ appendChildLowLevel (Child);
84
+ }
85
+
86
+ void syntax::Tree::appendChildLowLevel (Node *Child) {
87
+ assert (Child->Parent == nullptr );
88
+ assert (Child->NextSibling == nullptr );
89
+ assert (Child->PreviousSibling == nullptr );
90
+ assert (Child->getRole () != NodeRole::Detached);
91
+
92
+ Child->Parent = this ;
93
+ if (this ->LastChild ) {
94
+ Child->PreviousSibling = this ->LastChild ;
95
+ this ->LastChild ->NextSibling = Child;
96
+ } else
97
+ this ->FirstChild = Child;
98
+
99
+ this ->LastChild = Child;
100
+ }
101
+
77
102
void syntax::Tree::prependChildLowLevel (Node *Child, NodeRole Role) {
78
103
assert (Child->getRole () == NodeRole::Detached);
79
104
assert (Role != NodeRole::Detached);
@@ -85,22 +110,26 @@ void syntax::Tree::prependChildLowLevel(Node *Child, NodeRole Role) {
85
110
void syntax::Tree::prependChildLowLevel (Node *Child) {
86
111
assert (Child->Parent == nullptr );
87
112
assert (Child->NextSibling == nullptr );
113
+ assert (Child->PreviousSibling == nullptr );
88
114
assert (Child->getRole () != NodeRole::Detached);
89
115
90
116
Child->Parent = this ;
91
- Child->NextSibling = this ->FirstChild ;
117
+ if (this ->FirstChild ) {
118
+ Child->NextSibling = this ->FirstChild ;
119
+ this ->FirstChild ->PreviousSibling = Child;
120
+ } else
121
+ this ->LastChild = Child;
122
+
92
123
this ->FirstChild = Child;
93
124
}
94
125
95
- void syntax::Tree::replaceChildRangeLowLevel (Node *BeforeBegin , Node *End,
126
+ void syntax::Tree::replaceChildRangeLowLevel (Node *Begin , Node *End,
96
127
Node *New) {
97
- assert ((!BeforeBegin || BeforeBegin ->Parent == this ) &&
98
- " `BeforeBegin ` is not a child of `this`." );
128
+ assert ((!Begin || Begin ->Parent == this ) &&
129
+ " `Begin ` is not a child of `this`." );
99
130
assert ((!End || End->Parent == this ) && " `End` is not a child of `this`." );
100
131
assert (canModify () && " Cannot modify `this`." );
101
132
102
- Node *&Begin = BeforeBegin ? BeforeBegin->NextSibling : FirstChild;
103
-
104
133
#ifndef NDEBUG
105
134
for (auto *N = New; N; N = N->NextSibling ) {
106
135
assert (N->Parent == nullptr );
@@ -116,9 +145,8 @@ void syntax::Tree::replaceChildRangeLowLevel(Node *BeforeBegin, Node *End,
116
145
return true ;
117
146
return false ;
118
147
};
119
- assert (Reachable (FirstChild, BeforeBegin) &&
120
- " `BeforeBegin` is not reachable." );
121
- assert (Reachable (Begin, End) && " `End` is not after `BeforeBegin`." );
148
+ assert (Reachable (FirstChild, Begin) && " `Begin` is not reachable." );
149
+ assert (Reachable (Begin, End) && " `End` is not after `Begin`." );
122
150
#endif
123
151
124
152
if (!New && Begin == End)
@@ -128,31 +156,44 @@ void syntax::Tree::replaceChildRangeLowLevel(Node *BeforeBegin, Node *End,
128
156
for (auto *T = this ; T && T->Original ; T = T->Parent )
129
157
T->Original = false ;
130
158
159
+ // Save the node before the range to be removed. Later we insert the `New`
160
+ // range after this node.
161
+ auto *BeforeBegin = Begin ? Begin->PreviousSibling : LastChild;
162
+
131
163
// Detach old nodes.
132
164
for (auto *N = Begin; N != End;) {
133
165
auto *Next = N->NextSibling ;
134
166
135
167
N->setRole (NodeRole::Detached);
136
168
N->Parent = nullptr ;
137
169
N->NextSibling = nullptr ;
170
+ N->PreviousSibling = nullptr ;
138
171
if (N->Original )
139
172
traverse (N, [](Node *C) { C->Original = false ; });
140
173
141
174
N = Next;
142
175
}
143
176
177
+ // Attach new range.
178
+ auto *&NewFirst = BeforeBegin ? BeforeBegin->NextSibling : FirstChild;
179
+ auto *&NewLast = End ? End->PreviousSibling : LastChild;
180
+
144
181
if (!New) {
145
- Begin = End;
182
+ NewFirst = End;
183
+ NewLast = BeforeBegin;
146
184
return ;
147
185
}
148
- // Attach new nodes.
149
- Begin = New;
150
- auto *Last = New;
186
+
187
+ New->PreviousSibling = BeforeBegin;
188
+ NewFirst = New;
189
+
190
+ Node *LastInNew;
151
191
for (auto *N = New; N != nullptr ; N = N->NextSibling ) {
152
- Last = N;
192
+ LastInNew = N;
153
193
N->Parent = this ;
154
194
}
155
- Last->NextSibling = End;
195
+ LastInNew->NextSibling = End;
196
+ NewLast = LastInNew;
156
197
}
157
198
158
199
namespace {
@@ -248,6 +289,11 @@ void syntax::Node::assertInvariants() const {
248
289
assert (C.isOriginal ());
249
290
assert (!C.isDetached ());
250
291
assert (C.getParent () == T);
292
+ const auto *Next = C.getNextSibling ();
293
+ assert (!Next || &C == Next->getPreviousSibling ());
294
+ if (!C.getNextSibling ())
295
+ assert (&C == T->getLastChild () &&
296
+ " Last child is reachable by advancing from the first child." );
251
297
}
252
298
253
299
const auto *L = dyn_cast<List>(T);
@@ -282,14 +328,13 @@ const syntax::Leaf *syntax::Tree::findFirstLeaf() const {
282
328
}
283
329
284
330
const syntax::Leaf *syntax::Tree::findLastLeaf () const {
285
- const syntax::Leaf *Last = nullptr ;
286
- for (const Node &C : getChildren ()) {
287
- if (const auto *L = dyn_cast<syntax::Leaf>(&C))
288
- Last = L;
289
- else if (const auto *L = cast<syntax::Tree>(C).findLastLeaf ())
290
- Last = L;
331
+ for (const auto *C = getLastChild (); C; C = C->getPreviousSibling ()) {
332
+ if (const auto *L = dyn_cast<syntax::Leaf>(C))
333
+ return L;
334
+ if (const auto *L = cast<syntax::Tree>(C)->findLastLeaf ())
335
+ return L;
291
336
}
292
- return Last ;
337
+ return nullptr ;
293
338
}
294
339
295
340
const syntax::Node *syntax::Tree::findChild (NodeRole R) const {
0 commit comments