text: //===--- Initializer.h - Initializer DeclContext ----------------*- 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 Initializer class, which is a kind of
  // DeclContext used for expressions that are not part of a normal
  // code-evaluation context, such as a global initializer or a default
  // argument.
  //
  //===----------------------------------------------------------------------===//
  
  #ifndef SWIFT_INITIALIZER_H
  #define SWIFT_INITIALIZER_H
  
  #include "swift/AST/DeclContext.h"
  #include "swift/AST/Decl.h"
  
  namespace swift {
  class PatternBindingDecl;
  
  enum class InitializerKind : uint8_t {
    /// The initializer expression of a PatternBindingDecl that declares
    /// a global variable or type member.
    PatternBinding,
  
    /// A function's default argument expression.
    DefaultArgument,
  };
  
  /// An Initializer is a kind of DeclContext used for expressions that
  /// aren't potentially evaluated as part of some function.
  ///
  /// Generally, Initializers are created lazily, as most initializers
  /// don't really require DeclContexts.
  class Initializer : public DeclContext {
    unsigned Kind : 1;
  protected:
    unsigned SpareBits : 31;
    
    Initializer(InitializerKind kind, DeclContext *parent)
      : DeclContext(DeclContextKind::Initializer, parent),
        Kind(unsigned(kind)) {
    }
  
    // Expose this to subclasses.
    using DeclContext::setParent;
  
  public:
    /// Returns the kind of initializer this is.
    InitializerKind getInitializerKind() const {
      return InitializerKind(Kind);
    }
  
    static bool classof(const DeclContext *DC) {
      return DC->getContextKind() == DeclContextKind::Initializer;
    }
    static bool classof(const Initializer *I) { return true; }
  };
  
  /// The initializer expression of a non-local pattern binding
  /// declaration, such as a field or global variable.
  class PatternBindingInitializer : public Initializer {
    PatternBindingDecl *Binding;
  
    // created lazily for 'self' lookup from lazy property initializer
    ParamDecl *SelfParam;
  
    friend class ASTContext; // calls reset on unused contexts
  
    void reset(DeclContext *parent) {
      setParent(parent);
      Binding = nullptr;
      SelfParam = nullptr;
    }
  
  public:
    explicit PatternBindingInitializer(DeclContext *parent)
      : Initializer(InitializerKind::PatternBinding, parent),
        Binding(nullptr), SelfParam(nullptr) {
      SpareBits = 0;
    }
   
  
    void setBinding(PatternBindingDecl *binding, unsigned bindingIndex) {
      setParent(binding->getDeclContext());
      Binding = binding;
      SpareBits = bindingIndex;
    }
    
    PatternBindingDecl *getBinding() const { return Binding; }
  
    unsigned getBindingIndex() const { return SpareBits; }
  
    /// If this initializes a single @lazy variable, return it.
    VarDecl *getInitializedLazyVar() const;
  
    /// If this initializes a single @lazy variable, lazily create a self
    /// declaration for it to refer to.
    ParamDecl *getImplicitSelfDecl();
  
    static bool classof(const DeclContext *DC) {
      if (auto init = dyn_cast<Initializer>(DC))
        return classof(init);
      return false;
    }
    static bool classof(const Initializer *I) {
      return I->getInitializerKind() == InitializerKind::PatternBinding;
    }
  };
  
  /// SerializedPatternBindingInitializer - This represents what was originally a
  /// PatternBindingInitializer during serialization. It is preserved as a special
  /// class only to maintain the correct AST structure and remangling after
  /// deserialization.
  class SerializedPatternBindingInitializer : public SerializedLocalDeclContext {
    PatternBindingDecl *Binding;
  
  public:
    SerializedPatternBindingInitializer(PatternBindingDecl *Binding,
                                        unsigned bindingIndex)
      : SerializedLocalDeclContext(LocalDeclContextKind::PatternBindingInitializer,
                                   Binding->getDeclContext()),
        Binding(Binding) {
      SpareBits = bindingIndex;
    }
  
    PatternBindingDecl *getBinding() const {
      return Binding;
    }
  
    unsigned getBindingIndex() const { return SpareBits; }
  
  
    static bool classof(const DeclContext *DC) {
      if (auto LDC = dyn_cast<SerializedLocalDeclContext>(DC))
        return LDC->getLocalDeclContextKind() ==
        LocalDeclContextKind::PatternBindingInitializer;
      return false;
    }
  };
  
  /// A default argument expression.  The parent context is the function
  /// (possibly a closure) for which this is a default argument.
  class DefaultArgumentInitializer : public Initializer {
    friend class ASTContext; // calls reset on unused contexts
    void reset(DeclContext *parent, unsigned index) {
      setParent(parent);
      SpareBits = index;
    }
  
  public:
    explicit DefaultArgumentInitializer(DeclContext *parent, unsigned index)
        : Initializer(InitializerKind::DefaultArgument, parent) {
      SpareBits = index;
    }
  
    unsigned getIndex() const { return SpareBits; }
  
    /// Change the parent of this context.  This is necessary because
    /// the function signature is parsed before the function
    /// declaration/expression itself is built.
    void changeFunction(DeclContext *parent, ParameterList *paramLists);
  
    static bool classof(const DeclContext *DC) {
      if (auto init = dyn_cast<Initializer>(DC))
        return classof(init);
      return false;
    }
    static bool classof(const Initializer *I) {
      return I->getInitializerKind() == InitializerKind::DefaultArgument;
    }
  };
  
  /// SerializedDefaultArgumentInitializer - This represents what was originally a
  /// DefaultArgumentInitializer during serialization. It is preserved only to
  /// maintain the correct AST structure and remangling after deserialization.
  class SerializedDefaultArgumentInitializer : public SerializedLocalDeclContext {
    const unsigned Index;
  public:
    SerializedDefaultArgumentInitializer(unsigned Index, DeclContext *Parent)
      : SerializedLocalDeclContext(LocalDeclContextKind::DefaultArgumentInitializer,
                                   Parent),
        Index(Index) {}
  
    unsigned getIndex() const {
      return Index;
    }
  
    static bool classof(const DeclContext *DC) {
      if (auto LDC = dyn_cast<SerializedLocalDeclContext>(DC))
        return LDC->getLocalDeclContextKind() ==
          LocalDeclContextKind::DefaultArgumentInitializer;
      return false;
    }
  };
    
  } // end namespace swift
  
  #endif
  