//===--- SyntaxCollection.h -------------------------------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #ifndef SWIFT_SYNTAX_SYNTAXCOLLECTION_H #define SWIFT_SYNTAX_SYNTAXCOLLECTION_H #include "swift/Syntax/Syntax.h" #include "swift/Syntax/SyntaxCollectionData.h" namespace swift { namespace syntax { template struct SyntaxCollectionIterator { const SyntaxCollection &Collection; size_t Index; Element operator*() { return Collection[Index]; } SyntaxCollectionIterator &operator++() { ++Index; return *this; } bool operator==(const SyntaxCollectionIterator &Other) { return Collection.hasSameIdentityAs(Other.Collection) && Index == Other.Index; } bool operator!=(const SyntaxCollectionIterator &Other) { return !operator==(Other); } }; /// A generic unbounded collection of syntax nodes template class SyntaxCollection : public Syntax { friend struct SyntaxFactory; friend class SyntaxData; friend class Syntax; using DataType = SyntaxCollectionData; protected: SyntaxCollection(const RC Root, const DataType *Data) : Syntax(Root, Data) {} public: /// Returns true if the collection is empty. bool empty() const { return size() == 0; } /// Returns the number of elements in the collection. size_t size() const { return getRaw()->Layout.size(); } SyntaxCollectionIterator begin() const { return SyntaxCollectionIterator { *this, 0, }; } SyntaxCollectionIterator end() const { return SyntaxCollectionIterator { *this, getRaw()->Layout.size(), }; } /// Return the element at the given Index. /// /// Precondition: Index < size() /// Precondition: !empty() Element operator[](const size_t Index) const { assert(Index < size()); assert(!empty()); auto RawElement = getRaw()->Layout[Index]; auto *MyData = getUnsafeData>(); if (auto Data = MyData->CachedElements[Index].get()) { return Element { Root, Data }; } auto &ChildPtr = *reinterpret_cast*>( MyData->CachedElements.data() + Index); SyntaxData::realizeSyntaxNode(ChildPtr, RawElement, MyData, Index); return Element { Root, MyData->CachedElements[Index].get() }; } /// Return a new collection with the given element added to the end. SyntaxCollection appending(Element E) const { auto NewLayout = getRaw()->Layout; NewLayout.push_back(E.getRaw()); auto Raw = RawSyntax::make(CollectionKind, NewLayout, getRaw()->Presence); return Data->replaceSelf>(Raw); } /// Return a new collection with an element removed from the end. /// /// Precondition: !empty() SyntaxCollection removingLast() const { assert(!empty()); auto NewLayout = getRaw()->Layout; NewLayout.pop_back(); auto Raw = RawSyntax::make(CollectionKind, NewLayout, getRaw()->Presence); return Data->replaceSelf>(Raw); } /// Return a new collection with the given element appended to the front. SyntaxCollection prepending(Element E) const { RawSyntax::LayoutList NewLayout = { E.getRaw() }; std::copy(getRaw()->Layout.begin(), getRaw()->Layout.end(), std::back_inserter(NewLayout)); auto Raw = RawSyntax::make(CollectionKind, NewLayout, getRaw()->Presence); return Data->replaceSelf>(Raw); } /// Return a new collection with an element removed from the end. /// /// Precondition: !empty() SyntaxCollection removingFirst() const { assert(!empty()); RawSyntax::LayoutList NewLayout; std::copy(getRaw()->Layout.begin() + 1, getRaw()->Layout.end(), std::back_inserter(NewLayout)); auto Raw = RawSyntax::make(CollectionKind, NewLayout, getRaw()->Presence); return Data->replaceSelf>(Raw); } /// Return a new collection with the Element inserted at index i. /// /// Precondition: i <= size() SyntaxCollection inserting(size_t i, Element E) const { assert(i <= size()); RawSyntax::LayoutList NewLayout; std::copy(getRaw()->Layout.begin(), getRaw()->Layout.begin() + i, std::back_inserter(NewLayout)); NewLayout.push_back(E.getRaw()); std::copy(getRaw()->Layout.begin() + i, getRaw()->Layout.end(), std::back_inserter(NewLayout)); auto Raw = RawSyntax::make(CollectionKind, NewLayout, getRaw()->Presence); return Data->replaceSelf>(Raw); } /// Return a new collection with the element removed at index i. SyntaxCollection removing(size_t i) const { auto NewLayout = getRaw()->Layout; NewLayout.erase(NewLayout.begin() + i); auto Raw = RawSyntax::make(CollectionKind, NewLayout, getRaw()->Presence); return Data->replaceSelf>(Raw); } /// Return an empty syntax collection of this type. SyntaxCollection cleared() const { auto Raw = RawSyntax::make(CollectionKind, {}, getRaw()->Presence); return Data->replaceSelf>(Raw); } static bool classof(const Syntax *S) { return S->getKind() == CollectionKind; } }; } // end namespace syntax } // end namespace swift #endif // SWIFT_SYNTAX_SYNTAXCOLLECTION_H