// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_WASM_RESULT_H_
#define V8_WASM_RESULT_H_

#include "src/base/compiler-specific.h"
#include "src/base/smart-pointers.h"

#include "src/globals.h"

namespace v8 {
namespace internal {

class Isolate;

namespace wasm {

// Error codes for programmatic checking of the decoder's verification.
enum ErrorCode {
  kSuccess,
  kError,                 // TODO(titzer): remove me
  kOutOfMemory,           // decoder ran out of memory
  kEndOfCode,             // end of code reached prematurely
  kInvalidOpcode,         // found invalid opcode
  kUnreachableCode,       // found unreachable code
  kImproperContinue,      // improperly nested continue
  kImproperBreak,         // improperly nested break
  kReturnCount,           // return count mismatch
  kTypeError,             // type mismatch
  kInvalidLocalIndex,     // invalid local
  kInvalidGlobalIndex,    // invalid global
  kInvalidFunctionIndex,  // invalid function
  kInvalidMemType         // invalid memory type
};

// The overall result of decoding a function or a module.
template <typename T>
struct Result {
  Result()
      : val(nullptr), error_code(kSuccess), start(nullptr), error_pc(nullptr) {
    error_msg.Reset(nullptr);
  }

  T val;
  ErrorCode error_code;
  const byte* start;
  const byte* error_pc;
  const byte* error_pt;
  base::SmartArrayPointer<char> error_msg;

  bool ok() const { return error_code == kSuccess; }
  bool failed() const { return error_code != kSuccess; }

  template <typename V>
  void CopyFrom(Result<V>& that) {
    error_code = that.error_code;
    start = that.start;
    error_pc = that.error_pc;
    error_pt = that.error_pt;
    error_msg = that.error_msg;
  }
};

template <typename T>
std::ostream& operator<<(std::ostream& os, const Result<T>& result) {
  os << "Result = ";
  if (result.ok()) {
    if (result.val != nullptr) {
      os << *result.val;
    } else {
      os << "success (no value)";
    }
  } else if (result.error_msg.get() != nullptr) {
    ptrdiff_t offset = result.error_pc - result.start;
    if (offset < 0) {
      os << result.error_msg.get() << " @" << offset;
    } else {
      os << result.error_msg.get() << " @+" << offset;
    }
  } else {
    os << result.error_code;
  }
  os << std::endl;
  return os;
}

std::ostream& operator<<(std::ostream& os, const ErrorCode& error_code);

// A helper for generating error messages that bubble up to JS exceptions.
class ErrorThrower {
 public:
  ErrorThrower(Isolate* isolate, const char* context)
      : isolate_(isolate), context_(context), error_(false) {}

  PRINTF_FORMAT(2, 3) void Error(const char* fmt, ...);

  template <typename T>
  void Failed(const char* error, Result<T>& result) {
    std::ostringstream str;
    str << error << result;
    return Error("%s", str.str().c_str());
  }

  bool error() const { return error_; }

 private:
  Isolate* isolate_;
  const char* context_;
  bool error_;
};
}  // namespace wasm
}  // namespace internal
}  // namespace v8

#endif
