// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef SRC_SEM_STATEMENT_H_
#define SRC_SEM_STATEMENT_H_

#include "src/sem/behavior.h"
#include "src/sem/node.h"

// Forward declarations
namespace tint {
namespace ast {
class Function;
class Statement;
}  // namespace ast
namespace sem {
class BlockStatement;
}  // namespace sem
}  // namespace tint

namespace tint {
namespace sem {

/// Forward declaration
class CompoundStatement;
class Function;

namespace detail {
/// FindFirstParentReturn is a traits helper for determining the return type for
/// the template member function Statement::FindFirstParent().
/// For zero or multiple template arguments, FindFirstParentReturn::type
/// resolves to CompoundStatement.
template <typename... TYPES>
struct FindFirstParentReturn {
  /// The pointer type returned by Statement::FindFirstParent()
  using type = CompoundStatement;
};

/// A specialization of FindFirstParentReturn for a single template argument.
/// FindFirstParentReturn::type resolves to the single template argument.
template <typename T>
struct FindFirstParentReturn<T> {
  /// The pointer type returned by Statement::FindFirstParent()
  using type = T;
};

template <typename... TYPES>
using FindFirstParentReturnType =
    typename FindFirstParentReturn<TYPES...>::type;
}  // namespace detail

/// Statement holds the semantic information for a statement.
class Statement : public Castable<Statement, Node> {
 public:
  /// Constructor
  /// @param declaration the AST node for this statement
  /// @param parent the owning statement
  /// @param function the owning function
  Statement(const ast::Statement* declaration,
            const CompoundStatement* parent,
            const sem::Function* function);

  /// Destructor
  ~Statement() override;

  /// @return the AST node for this statement
  const ast::Statement* Declaration() const { return declaration_; }

  /// @return the statement that encloses this statement
  const CompoundStatement* Parent() const { return parent_; }

  /// @returns the closest enclosing parent that satisfies the given predicate,
  /// which may be the statement itself, or nullptr if no match is found.
  /// @param pred a predicate that the resulting block must satisfy
  template <typename Pred>
  const CompoundStatement* FindFirstParent(Pred&& pred) const;

  /// @returns the closest enclosing parent that is of one of the types in
  /// `TYPES`, which may be the statement itself, or nullptr if no match is
  /// found. If `TYPES` is a single template argument, the return type is a
  /// pointer to that template argument type, otherwise a CompoundStatement
  /// pointer is returned.
  template <typename... TYPES>
  const detail::FindFirstParentReturnType<TYPES...>* FindFirstParent() const;

  /// @return the closest enclosing block for this statement
  const BlockStatement* Block() const;

  /// @returns the function that owns this statement
  const sem::Function* Function() const { return function_; }

  /// @return the behaviors of this statement
  const sem::Behaviors& Behaviors() const { return behaviors_; }

  /// @return the behaviors of this statement
  sem::Behaviors& Behaviors() { return behaviors_; }

  /// @returns true if this statement is reachable by control flow according to
  /// the behavior analysis
  bool IsReachable() const { return is_reachable_; }

  /// @param is_reachable whether this statement is reachable by control flow
  /// according to the behavior analysis
  void SetIsReachable(bool is_reachable) { is_reachable_ = is_reachable; }

 private:
  const ast::Statement* const declaration_;
  const CompoundStatement* const parent_;
  const sem::Function* const function_;
  sem::Behaviors behaviors_{sem::Behavior::kNext};
  bool is_reachable_ = true;
};

/// CompoundStatement is the base class of statements that can hold other
/// statements.
class CompoundStatement : public Castable<Statement, Statement> {
 public:
  /// Constructor
  /// @param declaration the AST node for this statement
  /// @param statement the owning statement
  /// @param function the owning function
  CompoundStatement(const ast::Statement* declaration,
                    const CompoundStatement* statement,
                    const sem::Function* function);

  /// Destructor
  ~CompoundStatement() override;
};

template <typename Pred>
const CompoundStatement* Statement::FindFirstParent(Pred&& pred) const {
  if (auto* self = As<CompoundStatement>()) {
    if (pred(self)) {
      return self;
    }
  }
  const auto* curr = parent_;
  while (curr && !pred(curr)) {
    curr = curr->Parent();
  }
  return curr;
}

template <typename... TYPES>
const detail::FindFirstParentReturnType<TYPES...>* Statement::FindFirstParent()
    const {
  using ReturnType = detail::FindFirstParentReturnType<TYPES...>;
  if (sizeof...(TYPES) == 1) {
    if (auto* p = As<ReturnType>()) {
      return p;
    }
    const auto* curr = parent_;
    while (curr) {
      if (auto* p = curr->As<ReturnType>()) {
        return p;
      }
      curr = curr->Parent();
    }
  } else {
    if (IsAnyOf<TYPES...>()) {
      return As<ReturnType>();
    }
    const auto* curr = parent_;
    while (curr) {
      if (curr->IsAnyOf<TYPES...>()) {
        return curr->As<ReturnType>();
      }
      curr = curr->Parent();
    }
  }
  return nullptr;
}

}  // namespace sem
}  // namespace tint

#endif  // SRC_SEM_STATEMENT_H_
