//===--- ParserResult.h - Parser Result Wrapper -----------------*- 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_PARSER_PARSER_RESULT_H
#define SWIFT_PARSER_PARSER_RESULT_H

#include "llvm/ADT/PointerIntPair.h"
#include "swift/AST/ParameterList.h"
#include <type_traits>

namespace swift {

class ParserStatus;

/// A wrapper for a parser AST node result (Decl, Stmt, Expr, Pattern,
/// etc.)
///
/// Contains the pointer to the AST node itself (or null) and additional bits
/// that indicate:
/// \li if there was a parse error;
/// \li if there was a code completion token.
///
/// If you want to return an AST node pointer in the Parser, consider using
/// ParserResult instead.
template <typename T> class ParserResult {
  llvm::PointerIntPair<T *, 2> PtrAndBits;

  enum {
    IsError = 0x1,
    IsCodeCompletion = 0x2,
  };

  template <typename U> friend class ParserResult;

public:
  /// Construct a null result with error bit set.
  ParserResult(std::nullptr_t = nullptr) { setIsParseError(); }

  /// Construct a null result with specified error bits set.
  ParserResult(ParserStatus Status);

  /// Construct a successful parser result.
  explicit ParserResult(T *Result) : PtrAndBits(Result) {
    assert(Result && "a successful parser result cannot be null");
  }

  /// Convert from a different but compatible parser result.
  template <typename U, typename Enabler = typename std::enable_if<
                            std::is_base_of<T, U>::value>::type>
  ParserResult(ParserResult<U> Other)
      : PtrAndBits(Other.PtrAndBits.getPointer(), Other.PtrAndBits.getInt()) {}

  /// Return true if this result does not have an AST node.
  ///
  /// If returns true, then error bit is set.
  bool isNull() const { return getPtrOrNull() == nullptr; }

  /// Return true if this result has an AST node.
  ///
  /// Note that this does not tell us if there was a parse error or not.
  bool isNonNull() const { return getPtrOrNull() != nullptr; }

  /// Return the AST node if non-null.
  T *get() const {
    assert(getPtrOrNull() && "not checked for nullptr");
    return getPtrOrNull();
  }

  /// Return the AST node or a null pointer.
  T *getPtrOrNull() const { return PtrAndBits.getPointer(); }

  /// Return true if there was a parse error.
  ///
  /// Note that we can still have an AST node which was constructed during
  /// recovery.
  bool isParseError() const { return PtrAndBits.getInt() & IsError; }

  /// Return true if we found a code completion token while parsing this.
  bool hasCodeCompletion() const {
    return PtrAndBits.getInt() & IsCodeCompletion;
  }

  void setIsParseError() { PtrAndBits.setInt(PtrAndBits.getInt() | IsError); }

  void setHasCodeCompletion() {
    PtrAndBits.setInt(PtrAndBits.getInt() | IsError | IsCodeCompletion);
  }
};

/// Create a successful parser result.
template <typename T>
static inline ParserResult<T> makeParserResult(T *Result) {
  return ParserResult<T>(Result);
}

/// Create a result (null or non-null) with error bit set.
template <typename T>
static inline ParserResult<T> makeParserErrorResult(T *Result = nullptr) {
  ParserResult<T> PR;
  if (Result)
    PR = ParserResult<T>(Result);
  PR.setIsParseError();
  return PR;
}

/// Create a result (null or non-null) with error and code completion bits set.
template <typename T>
static inline ParserResult<T> makeParserCodeCompletionResult(T *Result =
                                                                 nullptr) {
  ParserResult<T> PR;
  if (Result)
    PR = ParserResult<T>(Result);
  PR.setHasCodeCompletion();
  return PR;
}

/// Same as \c ParserResult, but just the status bits without the AST
/// node.
///
/// Useful when the AST node is returned by some other means (for example, in
/// a vector out parameter).
///
/// If you want to use 'bool' as a result type in the Parser, consider using
/// ParserStatus instead.
class ParserStatus {
  unsigned IsError : 1;
  unsigned IsCodeCompletion : 1;

public:
  /// Construct a successful parser status.
  ParserStatus() : IsError(0), IsCodeCompletion(0) {}

  /// Construct a parser status with specified bits.
  template<typename T>
  ParserStatus(ParserResult<T> Result) : IsError(0), IsCodeCompletion(0) {
    if (Result.isParseError())
      setIsParseError();
    if (Result.hasCodeCompletion())
      setHasCodeCompletion();
  }

  bool isSuccess() const { return !isError(); }
  bool isError() const { return IsError; }

  /// Return true if we found a code completion token while parsing this.
  bool hasCodeCompletion() const { return IsCodeCompletion; }

  void setIsParseError() {
    IsError = true;
  }

  void setHasCodeCompletion() {
    IsError = true;
    IsCodeCompletion = true;
  }

  /// True if we should stop parsing for any reason.
  bool shouldStopParsing() const {
    return IsError || IsCodeCompletion;
  }

  ParserStatus &operator|=(ParserStatus RHS) {
    IsError |= RHS.IsError;
    IsCodeCompletion |= RHS.IsCodeCompletion;
    return *this;
  }

  friend ParserStatus operator|(ParserStatus LHS, ParserStatus RHS) {
    ParserStatus Result = LHS;
    Result |= RHS;
    return Result;
  }
};

/// Create a successful parser status.
static inline ParserStatus makeParserSuccess() {
  return ParserStatus();
}

/// Create a status with error bit set.
static inline ParserStatus makeParserError() {
  ParserStatus Status;
  Status.setIsParseError();
  return Status;
}

/// Create a status with error and code completion bits set.
static inline ParserStatus makeParserCodeCompletionStatus() {
  ParserStatus Status;
  Status.setHasCodeCompletion();
  return Status;
}

/// Create a parser result with specified bits.
template <typename T>
static inline ParserResult<T> makeParserResult(ParserStatus Status,
                                               T *Result) {
  if (Status.isSuccess())
    return makeParserResult(Result);
  if (Status.hasCodeCompletion())
    return makeParserCodeCompletionResult(Result);
  return makeParserErrorResult(Result);
}

template <typename T> ParserResult<T>::ParserResult(ParserStatus Status) {
  assert(Status.isError());
  setIsParseError();
  if (Status.hasCodeCompletion())
    setHasCodeCompletion();
}

} // namespace swift

#endif // LLVM_SWIFT_PARSER_PARSER_RESULT_H

