//===--- Scope.cpp - Scope Implementation ---------------------------------===//
//
// 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 implements semantic analysis for Swift declarations.
//
//===----------------------------------------------------------------------===//

#include "swift/Parse/Scope.h"
#include "swift/Parse/Parser.h"
#include "llvm/ADT/Twine.h"

using namespace swift;

//===----------------------------------------------------------------------===//
// Scope Implementation
//===----------------------------------------------------------------------===//

static bool isResolvableScope(ScopeKind SK) {
  switch (SK) {
  case ScopeKind::Extension:
  case ScopeKind::EnumBody:
  case ScopeKind::StructBody:
  case ScopeKind::ClassBody:
  case ScopeKind::ProtocolBody:
  case ScopeKind::TopLevel:
  case ScopeKind::InheritanceClause:
    return false;
  case ScopeKind::FunctionBody:
  case ScopeKind::Generics:
  case ScopeKind::Brace:
  case ScopeKind::ForeachVars:
  case ScopeKind::ClosureParams:
  case ScopeKind::CaseVars:
  case ScopeKind::CatchVars:
  case ScopeKind::IfVars:
  case ScopeKind::WhileVars:
    return true;
  }

  llvm_unreachable("Unhandled ScopeKind in switch.");
}

Scope::Scope(Parser *P, ScopeKind SC, bool isInactiveConfigBlock)
  : SI(P->getScopeInfo()),
    HTScope(SI.HT, SI.CurScope ? &SI.CurScope->HTScope : nullptr),
    PrevScope(SI.CurScope),
    PrevResolvableDepth(SI.ResolvableDepth),
    Kind(SC),
    IsInactiveConfigBlock(isInactiveConfigBlock) {
  assert(PrevScope || Kind == ScopeKind::TopLevel);
  
  if (SI.CurScope) {
    Depth = SI.CurScope->Depth + 1;
    IsInactiveConfigBlock |= SI.CurScope->IsInactiveConfigBlock;
  } else {
    Depth = 0;
  }
  SI.CurScope = this;
  if (!isResolvableScope(Kind))
    SI.ResolvableDepth = Depth + 1;
}

Scope::Scope(Parser *P, SavedScope &&SS):
    SI(P->getScopeInfo()),
    HTScope(std::move(SS.HTDetachedScope)),
    PrevScope(SI.CurScope),
    PrevResolvableDepth(SI.ResolvableDepth),
    Depth(SS.Depth),
    Kind(SS.Kind),
    IsInactiveConfigBlock(SS.IsInactiveConfigBlock) {

    SI.CurScope = this;
    if (!isResolvableScope(Kind))
      SI.ResolvableDepth = Depth + 1;
}

bool Scope::isResolvable() const {
  return isResolvableScope(Kind);
}

//===----------------------------------------------------------------------===//
// ScopeInfo Implementation
//===----------------------------------------------------------------------===//

/// checkValidOverload - Check whether it is ok for D1 and D2 to be declared at
/// the same scope.  This check is a transitive relationship, so if "D1 is a
/// valid overload of D2" and "D2 is a valid overload of D3" then we know that
/// D1/D3 are valid overloads and we don't have to check all permutations.
static bool checkValidOverload(const ValueDecl *D1, const ValueDecl *D2,
                               Parser &P) {
  // Currently, there is no restriction on overloading.
  return false;
}


/// addToScope - Register the specified decl as being in the current lexical
/// scope.
void ScopeInfo::addToScope(ValueDecl *D, Parser &TheParser,
                           bool diagnoseRedefinitions) {
  if (!CurScope->isResolvable())
    return;

  assert(CurScope->getDepth() >= ResolvableDepth &&
         "inserting names into a non-resolvable scope");

  // If we have a shadowed variable definition, check to see if we have a
  // redefinition: two definitions in the same scope with the same name.
  ScopedHTTy::iterator EntryI = HT.begin(CurScope->HTScope, D->getFullName());

  // A redefinition is a hit in the scoped table at the same depth.
  if (EntryI != HT.end() && EntryI->first == CurScope->getDepth()) {
    ValueDecl *PrevDecl = EntryI->second;
    
    // If this is in a resolvable scope, diagnose redefinitions.  Later
    // phases will handle scopes like module-scope, etc.
    if (CurScope->getDepth() >= ResolvableDepth) {
      if (diagnoseRedefinitions) {
        return TheParser.diagnoseRedefinition(PrevDecl, D);
      }
      return;
    }

    // If this is at top-level scope, validate that the members of the overload
    // set all agree.
    
    // Check to see if D and PrevDecl are valid in the same overload set.
    if (checkValidOverload(D, PrevDecl, TheParser))
      return;
    
    // Note: we don't check whether all of the elements of the overload set have
    // different argument types.  This is checked later.
  }

  HT.insertIntoScope(CurScope->HTScope,
                     D->getFullName(),
                     std::make_pair(CurScope->getDepth(), D));
}

void ScopeInfo::dump() const {
#ifndef NDEBUG
  // Dump out the current list of scopes.
  if (!CurScope->isResolvable())
    return;

  assert(CurScope->getDepth() >= ResolvableDepth &&
         "Attempting to dump a non-resolvable scope?!");

  llvm::dbgs() << "--- Dumping ScopeInfo ---\n";
  std::function<void(decltype(HT)::DebugVisitValueTy)> func =
      [&](const decltype(HT)::DebugVisitValueTy &iter) -> void {
    llvm::dbgs() << "DeclName: " << iter->getKey() << "\n"
                 << "KeyScopeID: " << iter->getValue().first << "\n"
                 << "Decl: ";
    iter->getValue().second->dumpRef(llvm::dbgs());
    llvm::dbgs() << "\n";
  };
  HT.debugVisit(std::move(func));
  llvm::dbgs() << "\n";
#endif
}
