text: //===--- Syntax.h - Swift Syntax Interface ----------------------*- 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
  //
  //===----------------------------------------------------------------------===//
  //
  // This file defines the Syntax type, the main public-facing classes and
  // subclasses for dealing with Swift Syntax.
  //
  // Syntax types contain a strong reference to the root of the tree to keep
  // the subtree above alive, and a weak reference to the data representing
  // the syntax node (weak to prevent retain cycles). All significant public API
  // are contained in Syntax and its subclasses.
  //
  //===----------------------------------------------------------------------===//
  
  #ifndef SWIFT_SYNTAX_SYNTAX_H
  #define SWIFT_SYNTAX_SYNTAX_H
  
  #include "swift/Syntax/References.h"
  #include "swift/Syntax/RawSyntax.h"
  #include "swift/Syntax/Trivia.h"
  #include "llvm/ADT/IntrusiveRefCntPtr.h"
  #include "llvm/ADT/Optional.h"
  #include "llvm/Support/raw_ostream.h"
  
  namespace swift {
  namespace sema {
    class Semantics;
  }
  namespace syntax {
  
  const auto NoParent = llvm::None;
  
  class SyntaxData;
  
  /// The main handle for syntax nodes - subclasses contain all public
  /// structured editing APIs.
  ///
  /// This opaque structure holds two pieces of data: a strong reference to a
  /// root node and a weak reference to the node itself. The node of interest can
  /// be weakly held because the data nodes contain strong references to
  /// their children.
  class Syntax {
    friend struct SyntaxFactory;
    friend class SyntaxData;
    friend class LegacyASTTransformer;
    friend class sema::Semantics;
  
  #define SYNTAX(Id, Parent) friend class Id##Syntax;
  #include "swift/Syntax/SyntaxKinds.def"
  
  protected:
    /// A strong reference to the root node of the tree in which this piece of
    /// syntax resides.
    const RC<SyntaxData> Root;
  
    /// A raw pointer to the data representing this syntax node.
    ///
    /// This is mutable for being able to set cached child members, which are
    /// lazily created.
    mutable const SyntaxData *Data;
  
    template <typename SyntaxNode>
    typename SyntaxNode::DataType *getUnsafeData() const {
      auto Casted = cast<typename SyntaxNode::DataType>(Data);
      return const_cast<typename SyntaxNode::DataType *>(Casted);
    }
  
  public:
    using DataType = SyntaxData;
  
    Syntax(const RC<SyntaxData> Root, const SyntaxData *Data);
  
    /// Get the kind of syntax.
    SyntaxKind getKind() const;
  
    /// Get the shared raw syntax.
    RC<RawSyntax> getRaw() const;
  
    /// Returns true if the syntax node is of the given type.
    template <typename T>
    bool is() const {
      return T::classof(this);
    }
  
    /// Get the Data for this Syntax node.
    template <typename T>
    typename T::DataType &getData() const {
      assert(is<T>() && "getData<T>() node of incompatible type!");
      return *reinterpret_cast<typename T::DataType *>(Data);
    }
  
    const SyntaxData *getDataPointer() const {
      return Data;
    }
  
    /// Cast this Syntax node to a more specific type, asserting it's of the
    /// right kind.
    template <typename T>
    T castTo() const {
      assert(is<T>() && "castTo<T>() node of incompatible type!");
      return T { Root, reinterpret_cast<const typename T::DataType *>(Data) };
    }
  
    /// If this Syntax node is of the right kind, cast and return it,
    /// otherwise return None.
    template <typename T>
    llvm::Optional<T> getAs() const {
      if (is<T>()) {
        return castTo<T>();
      }
      return llvm::None;
    }
  
    /// Return the parent of this node, if it has one.
    llvm::Optional<Syntax> getParent() const;
  
    /// Returns the child index of this node in its parent,
    /// if it has one, otherwise 0.
    CursorIndex getIndexInParent() const;
  
    /// Returns true if this syntax node represents a statement.
    bool isStmt() const;
  
    /// Returns true if this syntax node represents a declaration.
    bool isDecl() const;
  
    /// Returns true if this syntax node represents an expression.
    bool isExpr() const;
  
    /// Returns true if this syntax node represents a type.
    bool isType() const;
  
    /// Returns true if this syntax is of some "unknown" kind.
    bool isUnknown() const;
  
    /// Print the syntax node with full fidelity to the given output stream.
    void print(llvm::raw_ostream &OS) const;
  
    /// Print a debug representation of the syntax node to the given output stream
    /// and indentation level.
    void dump(llvm::raw_ostream &OS, unsigned Indent = 0) const;
  
    /// Print a debug representation of the syntax node to standard error.
    void dump() const;
  
    bool hasSameIdentityAs(const Syntax &Other) const {
      return Root == Other.Root && Data == Other.Data;
    }
  
    // TODO: hasSameStructureAs ?
  };
  
  } // end namespace syntax
  } // end namespace swift
  
  #endif // SWIFT_SYNTAX_SYNTAX_H
  