@@ -28,6 +28,8 @@ class SyntaxIndexInTree {
2828 explicit SyntaxIndexInTree (size_t IndexInTree) : IndexInTree(IndexInTree) {}
2929
3030public:
31+ // / Create an *uninitialized* \c SyntaxIndexInTree.
32+ SyntaxIndexInTree () {}
3133 static SyntaxIndexInTree zero () { return SyntaxIndexInTree (0 ); }
3234
3335 // / Assuming that this index points to the start of \p Raw, advance it so that
@@ -83,6 +85,9 @@ class SyntaxIdentifier {
8385 SyntaxIndexInTree IndexInTree;
8486
8587public:
88+ // / Create an *uninitialized* \c SyntaxIdentifier.
89+ SyntaxIdentifier () {}
90+
8691 SyntaxIdentifier (RootIdType RootId, SyntaxIndexInTree IndexInTree)
8792 : RootId(RootId), IndexInTree(IndexInTree) {
8893 assert (RootId < NextUnusedRootId && " New RootIds should only be created "
@@ -139,6 +144,9 @@ class AbsoluteSyntaxPosition {
139144 IndexInParentType IndexInParent;
140145
141146public:
147+ // / Create an *uninitialized* \c AbsoluteSyntaxPosition.
148+ AbsoluteSyntaxPosition () {}
149+
142150 AbsoluteSyntaxPosition (OffsetType Offset, IndexInParentType IndexInParent)
143151 : Offset(Offset), IndexInParent(IndexInParent) {}
144152
@@ -185,6 +193,8 @@ class AbsoluteOffsetPosition {
185193 AbsoluteSyntaxPosition::OffsetType Offset;
186194
187195public:
196+ // / Create an *uninitialized* \c AbsoluteOffsetPosition.
197+ AbsoluteOffsetPosition () {}
188198 explicit AbsoluteOffsetPosition (AbsoluteSyntaxPosition::OffsetType Offset)
189199 : Offset(Offset) {}
190200 AbsoluteOffsetPosition (AbsoluteSyntaxPosition Position)
@@ -205,6 +215,8 @@ class AbsoluteSyntaxInfo {
205215 SyntaxIdentifier NodeId;
206216
207217public:
218+ // / Create an *uninitialized* \c AbsoluteSyntaxInfo.
219+ AbsoluteSyntaxInfo () {}
208220 AbsoluteSyntaxInfo (AbsoluteSyntaxPosition Position, SyntaxIdentifier NodeId)
209221 : Position(Position), NodeId(NodeId) {}
210222
@@ -242,42 +254,111 @@ class AbsoluteSyntaxInfo {
242254
243255// / A \c RawSyntax node that is enrichted with information of its position
244256// / 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+
246263 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 ) {}
248272
249273public:
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.
250281 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+ }
252287
253288 // / Construct a \c AbsoluteRawSyntax for a \c RawSyntax node that represents
254289 // / the syntax tree's root.
255290 static AbsoluteRawSyntax forRoot (const RawSyntax *Raw) {
256291 return AbsoluteRawSyntax (Raw, AbsoluteSyntaxInfo::forRoot ());
257292 }
258293
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+ }
260298
261- AbsoluteSyntaxInfo getInfo () const { return Info; }
299+ AbsoluteSyntaxInfo getInfo () const {
300+ assert (!isNull () && " Cannot get Raw of a null AbsoluteRawSyntax" );
301+ return Info;
302+ }
262303
263304 // / 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+ };
265308
266- SyntaxIdentifier getNodeId () const { return Info .getNodeId (); };
309+ SyntaxIdentifier getNodeId () const { return getInfo () .getNodeId (); };
267310
268311 AbsoluteSyntaxPosition::IndexInParentType getIndexInParent () const {
269312 return getPosition ().getIndexInParent ();
270313 }
271314
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+
272352 // / Construct a new \c AbsoluteRawSyntax node that has the same info as the
273353 // / current one, but
274354 // / - the \p NewRaw as the backing storage
275355 // / - the \p NewRootId as the RootId
276356 AbsoluteRawSyntax
277357 replacingSelf (const RawSyntax *NewRaw,
278358 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);
281362 return AbsoluteRawSyntax (NewRaw, NewInfo);
282363 }
283364};
@@ -288,6 +369,122 @@ struct AbsoluteRawSyntax {
288369namespace llvm {
289370raw_ostream &operator <<(raw_ostream &OS,
290371 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
291433} // end namespace llvm
292434
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+
293490#endif // SWIFT_SYNTAX_ABSOLUTERAWSYNTAX_H
0 commit comments