@@ -28,6 +28,8 @@ class SyntaxIndexInTree {
28
28
explicit SyntaxIndexInTree (size_t IndexInTree) : IndexInTree(IndexInTree) {}
29
29
30
30
public:
31
+ // / Create an *uninitialized* \c SyntaxIndexInTree.
32
+ SyntaxIndexInTree () {}
31
33
static SyntaxIndexInTree zero () { return SyntaxIndexInTree (0 ); }
32
34
33
35
// / Assuming that this index points to the start of \p Raw, advance it so that
@@ -83,6 +85,9 @@ class SyntaxIdentifier {
83
85
SyntaxIndexInTree IndexInTree;
84
86
85
87
public:
88
+ // / Create an *uninitialized* \c SyntaxIdentifier.
89
+ SyntaxIdentifier () {}
90
+
86
91
SyntaxIdentifier (RootIdType RootId, SyntaxIndexInTree IndexInTree)
87
92
: RootId(RootId), IndexInTree(IndexInTree) {
88
93
assert (RootId < NextUnusedRootId && " New RootIds should only be created "
@@ -139,6 +144,9 @@ class AbsoluteSyntaxPosition {
139
144
IndexInParentType IndexInParent;
140
145
141
146
public:
147
+ // / Create an *uninitialized* \c AbsoluteSyntaxPosition.
148
+ AbsoluteSyntaxPosition () {}
149
+
142
150
AbsoluteSyntaxPosition (OffsetType Offset, IndexInParentType IndexInParent)
143
151
: Offset(Offset), IndexInParent(IndexInParent) {}
144
152
@@ -185,6 +193,8 @@ class AbsoluteOffsetPosition {
185
193
AbsoluteSyntaxPosition::OffsetType Offset;
186
194
187
195
public:
196
+ // / Create an *uninitialized* \c AbsoluteOffsetPosition.
197
+ AbsoluteOffsetPosition () {}
188
198
explicit AbsoluteOffsetPosition (AbsoluteSyntaxPosition::OffsetType Offset)
189
199
: Offset(Offset) {}
190
200
AbsoluteOffsetPosition (AbsoluteSyntaxPosition Position)
@@ -205,6 +215,8 @@ class AbsoluteSyntaxInfo {
205
215
SyntaxIdentifier NodeId;
206
216
207
217
public:
218
+ // / Create an *uninitialized* \c AbsoluteSyntaxInfo.
219
+ AbsoluteSyntaxInfo () {}
208
220
AbsoluteSyntaxInfo (AbsoluteSyntaxPosition Position, SyntaxIdentifier NodeId)
209
221
: Position(Position), NodeId(NodeId) {}
210
222
@@ -242,42 +254,111 @@ class AbsoluteSyntaxInfo {
242
254
243
255
// / A \c RawSyntax node that is enrichted with information of its position
244
256
// / within the syntax tree it lives in.
245
- struct AbsoluteRawSyntax {
257
+ class AbsoluteRawSyntax {
258
+ // / OptionalStorage is a friend so it can access the \c nullptr initializer
259
+ // / and \c isNull.
260
+ template <typename , bool >
261
+ friend class llvm ::optional_detail::OptionalStorage;
262
+
246
263
const RawSyntax *Raw;
247
- const AbsoluteSyntaxInfo Info;
264
+ AbsoluteSyntaxInfo Info;
265
+
266
+ // / Whether this is a null \c AbsoluteRawSyntax.
267
+ bool isNull () const { return Raw == nullptr ; }
268
+
269
+ // / Create a null \c AbsoluteRawSyntax. This should only be used in \c
270
+ // / AbsoluteRawSyntax's \c OptionalStorage.
271
+ explicit AbsoluteRawSyntax (std::nullptr_t ) : Raw(nullptr ) {}
248
272
249
273
public:
274
+ // / Create an *uninitialized* \c AbsoluteRawSyntax.
275
+ explicit AbsoluteRawSyntax () {}
276
+
277
+ // / Create a new \c AbsoluteRawData backed by \p Raw and with additional \p
278
+ // / Info. The caller of this constructor is responsible to ensure that the
279
+ // / Arena of \p Raw (and thus \p Raw itself) outlives this \c
280
+ // / AbsoluteRawSyntax.
250
281
AbsoluteRawSyntax (const RawSyntax *Raw, AbsoluteSyntaxInfo Info)
251
- : Raw(Raw), Info(Info) {}
282
+ : Raw(Raw), Info(Info) {
283
+ assert (Raw != nullptr &&
284
+ " A AbsoluteRawSyntax created through the memberwise constructor "
285
+ " should always have a RawSyntax" );
286
+ }
252
287
253
288
// / Construct a \c AbsoluteRawSyntax for a \c RawSyntax node that represents
254
289
// / the syntax tree's root.
255
290
static AbsoluteRawSyntax forRoot (const RawSyntax *Raw) {
256
291
return AbsoluteRawSyntax (Raw, AbsoluteSyntaxInfo::forRoot ());
257
292
}
258
293
259
- const RawSyntax *getRaw () const { return Raw; }
294
+ const RawSyntax *getRaw () const {
295
+ assert (!isNull () && " Cannot get Raw of a null AbsoluteRawSyntax" );
296
+ return Raw;
297
+ }
260
298
261
- AbsoluteSyntaxInfo getInfo () const { return Info; }
299
+ AbsoluteSyntaxInfo getInfo () const {
300
+ assert (!isNull () && " Cannot get Raw of a null AbsoluteRawSyntax" );
301
+ return Info;
302
+ }
262
303
263
304
// / Get the position at which the leading triva of this node starts.
264
- AbsoluteSyntaxPosition getPosition () const { return Info.getPosition (); };
305
+ AbsoluteSyntaxPosition getPosition () const {
306
+ return getInfo ().getPosition ();
307
+ };
265
308
266
- SyntaxIdentifier getNodeId () const { return Info .getNodeId (); };
309
+ SyntaxIdentifier getNodeId () const { return getInfo () .getNodeId (); };
267
310
268
311
AbsoluteSyntaxPosition::IndexInParentType getIndexInParent () const {
269
312
return getPosition ().getIndexInParent ();
270
313
}
271
314
315
+ size_t getNumChildren () const { return getRaw ()->getLayout ().size (); }
316
+
317
+ // / Get the child at \p Index if it exists. If the node does not have a child
318
+ // / at \p Index, return \c None. Asserts that \p Index < \c NumChildren
319
+ inline Optional<AbsoluteRawSyntax>
320
+ getChild (AbsoluteSyntaxPosition::IndexInParentType Index) const ;
321
+
322
+ // / Get the child at \p Index, asserting that it exists. This is slightly
323
+ // / more performant than \c getChild in these cases since the \c
324
+ // / AbsoluteRawSyntax node does not have to be wrapped in an \c Optional.
325
+ AbsoluteRawSyntax
326
+ getPresentChild (AbsoluteSyntaxPosition::IndexInParentType Index) const {
327
+ assert (Index < getNumChildren () && " Index out of bounds" );
328
+ auto RawChild = getRaw ()->getChild (Index);
329
+ assert (RawChild &&
330
+ " Child retrieved using getPresentChild must always exist" );
331
+
332
+ AbsoluteSyntaxPosition Position = getPosition ().advancedToFirstChild ();
333
+ SyntaxIdentifier NodeId = getNodeId ().advancedToFirstChild ();
334
+
335
+ for (size_t I = 0 ; I < Index; ++I) {
336
+ Position = Position.advancedBy (getRaw ()->getChild (I));
337
+ NodeId = NodeId.advancedBy (getRaw ()->getChild (I));
338
+ }
339
+
340
+ AbsoluteSyntaxInfo Info (Position, NodeId);
341
+ return AbsoluteRawSyntax (RawChild, Info);
342
+ }
343
+
344
+ // / Get the first non-missing token node in this tree. Return \c None if
345
+ // / this node does not contain non-missing tokens.
346
+ inline Optional<AbsoluteRawSyntax> getFirstToken () const ;
347
+
348
+ // / Get the last non-missing token node in this tree. Return \c None if
349
+ // / this node does not contain non-missing tokens.
350
+ inline Optional<AbsoluteRawSyntax> getLastToken () const ;
351
+
272
352
// / Construct a new \c AbsoluteRawSyntax node that has the same info as the
273
353
// / current one, but
274
354
// / - the \p NewRaw as the backing storage
275
355
// / - the \p NewRootId as the RootId
276
356
AbsoluteRawSyntax
277
357
replacingSelf (const RawSyntax *NewRaw,
278
358
SyntaxIdentifier::RootIdType NewRootId) const {
279
- SyntaxIdentifier NewNodeId (NewRootId, Info.getNodeId ().getIndexInTree ());
280
- AbsoluteSyntaxInfo NewInfo (Info.getPosition (), NewNodeId);
359
+ SyntaxIdentifier NewNodeId (NewRootId,
360
+ getInfo ().getNodeId ().getIndexInTree ());
361
+ AbsoluteSyntaxInfo NewInfo (getInfo ().getPosition (), NewNodeId);
281
362
return AbsoluteRawSyntax (NewRaw, NewInfo);
282
363
}
283
364
};
@@ -288,6 +369,122 @@ struct AbsoluteRawSyntax {
288
369
namespace llvm {
289
370
raw_ostream &operator <<(raw_ostream &OS,
290
371
swift::syntax::AbsoluteOffsetPosition Pos);
372
+
373
+ namespace optional_detail {
374
+
375
+ using swift::syntax::AbsoluteRawSyntax;
376
+
377
+ // / A custom \c OptionalStorage implementation for \c AbsoluteRawSyntax that
378
+ // / makes \c Optional<AbsoluteRawSyntax> a zero-cost wrapper around \c
379
+ // / AbsoluteRawSyntax by using a special (externally not accessible) null \c
380
+ // / AbsoluteRawSyntax to represent a missing value.
381
+ template <>
382
+ class OptionalStorage <AbsoluteRawSyntax> {
383
+ AbsoluteRawSyntax Storage;
384
+
385
+ public:
386
+ OptionalStorage () : Storage(nullptr ) {}
387
+ OptionalStorage (OptionalStorage const &other) = default ;
388
+ OptionalStorage (OptionalStorage &&other) = default ;
389
+
390
+ template <class ... ArgTypes>
391
+ explicit OptionalStorage (llvm::optional_detail::in_place_t ,
392
+ ArgTypes &&...Args)
393
+ : Storage(std::forward<ArgTypes>(Args)...) {}
394
+
395
+ void reset () { Storage = AbsoluteRawSyntax (nullptr ); }
396
+
397
+ bool hasValue () const { return !Storage.isNull (); }
398
+
399
+ AbsoluteRawSyntax &getValue () LLVM_LVALUE_FUNCTION {
400
+ assert (hasValue ());
401
+ return Storage;
402
+ }
403
+ AbsoluteRawSyntax const &getValue () const LLVM_LVALUE_FUNCTION {
404
+ assert (hasValue ());
405
+ return Storage;
406
+ }
407
+ #if LLVM_HAS_RVALUE_REFERENCE_THIS
408
+ AbsoluteRawSyntax &&getValue() &&noexcept {
409
+ assert (hasValue ());
410
+ return std::move (Storage);
411
+ }
412
+ #endif
413
+
414
+ template <class ... Args>
415
+ void emplace (Args &&...args) {
416
+ Storage = AbsoluteRawSyntax (std::forward<Args>(args)...);
417
+ }
418
+
419
+ OptionalStorage &operator =(const AbsoluteRawSyntax &AbsoluteRaw) {
420
+ Storage = AbsoluteRaw;
421
+ return *this ;
422
+ }
423
+
424
+ OptionalStorage &operator =(AbsoluteRawSyntax &&AbsoluteRaw) {
425
+ Storage = std::move (AbsoluteRaw);
426
+ return *this ;
427
+ }
428
+
429
+ OptionalStorage &operator =(OptionalStorage const &other) = default ;
430
+ OptionalStorage &operator =(OptionalStorage &&other) = default ;
431
+ };
432
+ } // namespace optional_detail
291
433
} // end namespace llvm
292
434
435
+ namespace swift {
436
+ namespace syntax {
437
+
438
+ Optional<AbsoluteRawSyntax> AbsoluteRawSyntax::getChild (
439
+ AbsoluteSyntaxPosition::IndexInParentType Index) const {
440
+ assert (Index < getNumChildren () && " Index out of bounds" );
441
+ if (getRaw ()->getChild (Index)) {
442
+ return getPresentChild (Index);
443
+ } else {
444
+ return None;
445
+ }
446
+ }
447
+
448
+ Optional<AbsoluteRawSyntax> AbsoluteRawSyntax::getFirstToken () const {
449
+ if (getRaw ()->isToken () && !getRaw ()->isMissing ()) {
450
+ return *this ;
451
+ }
452
+
453
+ size_t NumChildren = getNumChildren ();
454
+ for (size_t I = 0 ; I < NumChildren; ++I) {
455
+ if (auto Child = getChild (I)) {
456
+ if (Child->getRaw ()->isMissing ()) {
457
+ continue ;
458
+ }
459
+
460
+ if (auto Token = Child->getFirstToken ()) {
461
+ return Token;
462
+ }
463
+ }
464
+ }
465
+ return None;
466
+ }
467
+
468
+ Optional<AbsoluteRawSyntax> AbsoluteRawSyntax::getLastToken () const {
469
+ if (getRaw ()->isToken () && !getRaw ()->isMissing ()) {
470
+ return *this ;
471
+ }
472
+
473
+ for (int I = getNumChildren () - 1 ; I >= 0 ; --I) {
474
+ if (auto Child = getChild (I)) {
475
+ if (Child->getRaw ()->isMissing ()) {
476
+ continue ;
477
+ }
478
+
479
+ if (auto Token = Child->getLastToken ()) {
480
+ return Token;
481
+ }
482
+ }
483
+ }
484
+ return None;
485
+ }
486
+
487
+ } // end namespace syntax
488
+ } // end namespace swift
489
+
293
490
#endif // SWIFT_SYNTAX_ABSOLUTERAWSYNTAX_H
0 commit comments