//===-- CommandObjectExpression.cpp -----------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
// C++ Includes
// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"

// Project includes
#include "CommandObjectExpression.h"
#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Expression/REPL.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"

using namespace lldb;
using namespace lldb_private;

CommandObjectExpression::CommandOptions::CommandOptions() : OptionGroup() {}

CommandObjectExpression::CommandOptions::~CommandOptions() = default;

static OptionEnumValueElement g_description_verbosity_type[] = {
    {eLanguageRuntimeDescriptionDisplayVerbosityCompact, "compact",
     "Only show the description string"},
    {eLanguageRuntimeDescriptionDisplayVerbosityFull, "full",
     "Show the full output, including persistent variable's name and type"},
    {0, nullptr, nullptr}};

static OptionDefinition g_expression_options[] = {
    // clang-format off
  {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads",           'a', OptionParser::eRequiredArgument, nullptr, nullptr,                      0, eArgTypeBoolean,              "Should we run all threads if the execution doesn't complete on one thread."},
  {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints",    'i', OptionParser::eRequiredArgument, nullptr, nullptr,                      0, eArgTypeBoolean,              "Ignore breakpoint hits while running expressions"},
  {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout",               't', OptionParser::eRequiredArgument, nullptr, nullptr,                      0, eArgTypeUnsignedInteger,      "Timeout value (in microseconds) for running the expression."},
  {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error",       'u', OptionParser::eRequiredArgument, nullptr, nullptr,                      0, eArgTypeBoolean,              "Clean up program state if the expression causes a crash, or raises a signal.  "
                                                                                                                                                                                  "Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."},
  {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug",                 'g', OptionParser::eNoArgument,       nullptr, nullptr,                      0, eArgTypeNone,                 "When specified, debug the JIT code by setting a breakpoint on the first instruction "
                                                                                                                                                                                  "and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."},
  {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language",              'l', OptionParser::eRequiredArgument, nullptr, nullptr,                      0, eArgTypeLanguage,             "Specifies the Language to use when parsing the expression.  If not set the target.language "
                                                                                                                                                                                  "setting is used." },
  {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits",          'X', OptionParser::eRequiredArgument, nullptr, nullptr,                      0, eArgTypeLanguage,             "If true, simple fix-it hints will be automatically applied to the expression." },
  {LLDB_OPT_SET_1,                  false, "description-verbosity", 'v', OptionParser::eOptionalArgument, nullptr, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."},
  {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level",             'p', OptionParser::eNoArgument,       nullptr, nullptr,                      0, eArgTypeNone,                 "Interpret the expression as a complete translation unit, without injecting it into the local "
                                                                                                                                                                                  "context.  Allows declaration of persistent, top-level entities without a $ prefix."},
  {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "allow-jit",             'j', OptionParser::eRequiredArgument, nullptr, nullptr,                      0, eArgTypeBoolean,              "Controls whether the expression can fall back to being JITted if it's not supported by "
                                                                                                                                                                                  "the interpreter (defaults to true)."}
    // clang-format on
};

Status CommandObjectExpression::CommandOptions::SetOptionValue(
    uint32_t option_idx, llvm::StringRef option_arg,
    ExecutionContext *execution_context) {
  Status error;

  const int short_option = GetDefinitions()[option_idx].short_option;

  switch (short_option) {
  case 'l':
    language = Language::GetLanguageTypeFromString(option_arg);
    if (language == eLanguageTypeUnknown)
      error.SetErrorStringWithFormat(
          "unknown language type: '%s' for expression",
          option_arg.str().c_str());
    break;

  case 'a': {
    bool success;
    bool result;
    result = OptionArgParser::ToBoolean(option_arg, true, &success);
    if (!success)
      error.SetErrorStringWithFormat(
          "invalid all-threads value setting: \"%s\"",
          option_arg.str().c_str());
    else
      try_all_threads = result;
  } break;

  case 'i': {
    bool success;
    bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
    if (success)
      ignore_breakpoints = tmp_value;
    else
      error.SetErrorStringWithFormat(
          "could not convert \"%s\" to a boolean value.",
          option_arg.str().c_str());
    break;
  }

  case 'j': {
    bool success;
    bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
    if (success)
      allow_jit = tmp_value;
    else
      error.SetErrorStringWithFormat(
          "could not convert \"%s\" to a boolean value.",
          option_arg.str().c_str());
    break;
  }

  case 't':
    if (option_arg.getAsInteger(0, timeout)) {
      timeout = 0;
      error.SetErrorStringWithFormat("invalid timeout setting \"%s\"",
                                     option_arg.str().c_str());
    }
    break;

  case 'u': {
    bool success;
    bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
    if (success)
      unwind_on_error = tmp_value;
    else
      error.SetErrorStringWithFormat(
          "could not convert \"%s\" to a boolean value.",
          option_arg.str().c_str());
    break;
  }

  case 'v':
    if (option_arg.empty()) {
      m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull;
      break;
    }
    m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity)
        OptionArgParser::ToOptionEnum(
            option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
    if (!error.Success())
      error.SetErrorStringWithFormat(
          "unrecognized value for description-verbosity '%s'",
          option_arg.str().c_str());
    break;

  case 'g':
    debug = true;
    unwind_on_error = false;
    ignore_breakpoints = false;
    break;

  case 'p':
    top_level = true;
    break;

  case 'X': {
    bool success;
    bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
    if (success)
      auto_apply_fixits = tmp_value ? eLazyBoolYes : eLazyBoolNo;
    else
      error.SetErrorStringWithFormat(
          "could not convert \"%s\" to a boolean value.",
          option_arg.str().c_str());
    break;
  }

  default:
    error.SetErrorStringWithFormat("invalid short option character '%c'",
                                   short_option);
    break;
  }

  return error;
}

void CommandObjectExpression::CommandOptions::OptionParsingStarting(
    ExecutionContext *execution_context) {
  auto process_sp =
      execution_context ? execution_context->GetProcessSP() : ProcessSP();
  if (process_sp) {
    ignore_breakpoints = process_sp->GetIgnoreBreakpointsInExpressions();
    unwind_on_error = process_sp->GetUnwindOnErrorInExpressions();
  } else {
    ignore_breakpoints = true;
    unwind_on_error = true;
  }

  show_summary = true;
  try_all_threads = true;
  timeout = 0;
  debug = false;
  language = eLanguageTypeUnknown;
  m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact;
  auto_apply_fixits = eLazyBoolCalculate;
  top_level = false;
  allow_jit = true;
}

llvm::ArrayRef<OptionDefinition>
CommandObjectExpression::CommandOptions::GetDefinitions() {
  return llvm::makeArrayRef(g_expression_options);
}

CommandObjectExpression::CommandObjectExpression(
    CommandInterpreter &interpreter)
    : CommandObjectRaw(
          interpreter, "expression", "Evaluate an expression on the current "
                                     "thread.  Displays any returned value "
                                     "with LLDB's default formatting.",
          "", eCommandProcessMustBePaused | eCommandTryTargetAPILock),
      IOHandlerDelegate(IOHandlerDelegate::Completion::Expression),
      m_option_group(), m_format_options(eFormatDefault),
      m_repl_option(LLDB_OPT_SET_1, false, "repl", 'r', "Drop into REPL", false,
                    true),
      m_command_options(), m_expr_line_count(0), m_expr_lines() {
  SetHelpLong(
      R"(
Single and multi-line expressions:

)"
      "    The expression provided on the command line must be a complete expression \
with no newlines.  To evaluate a multi-line expression, \
hit a return after an empty expression, and lldb will enter the multi-line expression editor. \
Hit return on an empty line to end the multi-line expression."
      
      R"(

Timeouts:

)"
      "    If the expression can be evaluated statically (without running code) then it will be.  \
Otherwise, by default the expression will run on the current thread with a short timeout: \
currently .25 seconds.  If it doesn't return in that time, the evaluation will be interrupted \
and resumed with all threads running.  You can use the -a option to disable retrying on all \
threads.  You can use the -t option to set a shorter timeout."
      R"(

User defined variables:

)"
      "    You can define your own variables for convenience or to be used in subsequent expressions.  \
You define them the same way you would define variables in C.  If the first character of \
your user defined variable is a $, then the variable's value will be available in future \
expressions, otherwise it will just be available in the current expression."
      R"(

Continuing evaluation after a breakpoint:

)"
      "    If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once \
you are done with your investigation, you can either remove the expression execution frames \
from the stack with \"thread return -x\" or if you are still interested in the expression result \
you can issue the \"continue\" command and the expression evaluation will complete and the \
expression result will be available using the \"thread.completed-expression\" key in the thread \
format."

      R"(

Examples:

    expr my_struct->a = my_array[3]
    expr -f bin -- (index * 8) + 5
    expr unsigned int $foo = 5
    expr char c[] = \"foo\"; c[0])");

  CommandArgumentEntry arg;
  CommandArgumentData expression_arg;

  // Define the first (and only) variant of this arg.
  expression_arg.arg_type = eArgTypeExpression;
  expression_arg.arg_repetition = eArgRepeatPlain;

  // There is only one variant this argument could be; put it into the argument
  // entry.
  arg.push_back(expression_arg);

  // Push the data for the first argument into the m_arguments vector.
  m_arguments.push_back(arg);

  // Add the "--format" and "--gdb-format"
  m_option_group.Append(&m_format_options,
                        OptionGroupFormat::OPTION_GROUP_FORMAT |
                            OptionGroupFormat::OPTION_GROUP_GDB_FMT,
                        LLDB_OPT_SET_1);
  m_option_group.Append(&m_command_options);
  m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL,
                        LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
  m_option_group.Append(&m_repl_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
  m_option_group.Finalize();
}

CommandObjectExpression::~CommandObjectExpression() = default;

Options *CommandObjectExpression::GetOptions() { return &m_option_group; }

static lldb_private::Status
CanBeUsedForElementCountPrinting(ValueObject &valobj) {
  CompilerType type(valobj.GetCompilerType());
  CompilerType pointee;
  if (!type.IsPointerType(&pointee))
    return Status("as it does not refer to a pointer");
  if (pointee.IsVoidType())
    return Status("as it refers to a pointer to void");
  return Status();
}

bool CommandObjectExpression::EvaluateExpression(const char *expr,
                                                 Stream *output_stream,
                                                 Stream *error_stream,
                                                 CommandReturnObject *result) {
  // Don't use m_exe_ctx as this might be called asynchronously after the
  // command object DoExecute has finished when doing multi-line expression
  // that use an input reader...
  ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());

  Target *target = exe_ctx.GetTargetPtr();

  if (!target)
    target = GetDummyTarget();

  if (target) {
    lldb::ValueObjectSP result_valobj_sp;
    bool keep_in_memory = true;
    StackFrame *frame = exe_ctx.GetFramePtr();

    EvaluateExpressionOptions options;
    options.SetCoerceToId(m_varobj_options.use_objc);
    options.SetUnwindOnError(m_command_options.unwind_on_error);
    options.SetIgnoreBreakpoints(m_command_options.ignore_breakpoints);
    options.SetKeepInMemory(keep_in_memory);
    options.SetUseDynamic(m_varobj_options.use_dynamic);
    options.SetTryAllThreads(m_command_options.try_all_threads);
    options.SetDebug(m_command_options.debug);
    options.SetLanguage(m_command_options.language);
    options.SetExecutionPolicy(
        m_command_options.allow_jit
            ? EvaluateExpressionOptions::default_execution_policy
            : lldb_private::eExecutionPolicyNever);

    bool auto_apply_fixits;
    if (m_command_options.auto_apply_fixits == eLazyBoolCalculate)
      auto_apply_fixits = target->GetEnableAutoApplyFixIts();
    else
      auto_apply_fixits =
          m_command_options.auto_apply_fixits == eLazyBoolYes ? true : false;

    options.SetAutoApplyFixIts(auto_apply_fixits);

    if (m_command_options.top_level)
      options.SetExecutionPolicy(eExecutionPolicyTopLevel);

    // If there is any chance we are going to stop and want to see what went
    // wrong with our expression, we should generate debug info
    if (!m_command_options.ignore_breakpoints ||
        !m_command_options.unwind_on_error)
      options.SetGenerateDebugInfo(true);

    if (m_command_options.timeout > 0)
      options.SetTimeout(std::chrono::microseconds(m_command_options.timeout));
    else
      options.SetTimeout(llvm::None);

    ExpressionResults success = target->EvaluateExpression(
        expr, frame, result_valobj_sp, options, &m_fixed_expression);

    // We only tell you about the FixIt if we applied it.  The compiler errors
    // will suggest the FixIt if it parsed.
    if (error_stream && !m_fixed_expression.empty() &&
        target->GetEnableNotifyAboutFixIts()) {
      if (success == eExpressionCompleted)
        error_stream->Printf(
            "  Fix-it applied, fixed expression was: \n    %s\n",
            m_fixed_expression.c_str());
    }

    if (result_valobj_sp) {
      Format format = m_format_options.GetFormat();

      if (result_valobj_sp->GetError().Success()) {
        if (format != eFormatVoid) {
          if (format != eFormatDefault)
            result_valobj_sp->SetFormat(format);

          if (m_varobj_options.elem_count > 0) {
            Status error(CanBeUsedForElementCountPrinting(*result_valobj_sp));
            if (error.Fail()) {
              result->AppendErrorWithFormat(
                  "expression cannot be used with --element-count %s\n",
                  error.AsCString(""));
              result->SetStatus(eReturnStatusFailed);
              return false;
            }
          }

          DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
              m_command_options.m_verbosity, format));
          options.SetVariableFormatDisplayLanguage(
              result_valobj_sp->GetPreferredDisplayLanguage());

          result_valobj_sp->Dump(*output_stream, options);

          if (result)
            result->SetStatus(eReturnStatusSuccessFinishResult);
        }
      } else {
        if (result_valobj_sp->GetError().GetError() ==
            UserExpression::kNoResult) {
          if (format != eFormatVoid &&
              m_interpreter.GetDebugger().GetNotifyVoid()) {
            error_stream->PutCString("(void)\n");
          }

          if (result)
            result->SetStatus(eReturnStatusSuccessFinishResult);
        } else {
          const char *error_cstr = result_valobj_sp->GetError().AsCString();
          if (error_cstr && error_cstr[0]) {
            const size_t error_cstr_len = strlen(error_cstr);
            const bool ends_with_newline =
                error_cstr[error_cstr_len - 1] == '\n';
            if (strstr(error_cstr, "error:") != error_cstr)
              error_stream->PutCString("error: ");
            error_stream->Write(error_cstr, error_cstr_len);
            if (!ends_with_newline)
              error_stream->EOL();
          } else {
            error_stream->PutCString("error: unknown error\n");
          }

          if (result)
            result->SetStatus(eReturnStatusFailed);
        }
      }
    }
  } else {
    error_stream->Printf("error: invalid execution context for expression\n");
    return false;
  }

  return true;
}

void CommandObjectExpression::IOHandlerInputComplete(IOHandler &io_handler,
                                                     std::string &line) {
  io_handler.SetIsDone(true);
  //    StreamSP output_stream =
  //    io_handler.GetDebugger().GetAsyncOutputStream();
  //    StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream();
  StreamFileSP output_sp(io_handler.GetOutputStreamFile());
  StreamFileSP error_sp(io_handler.GetErrorStreamFile());

  EvaluateExpression(line.c_str(), output_sp.get(), error_sp.get());
  if (output_sp)
    output_sp->Flush();
  if (error_sp)
    error_sp->Flush();
}

bool CommandObjectExpression::IOHandlerIsInputComplete(IOHandler &io_handler,
                                                       StringList &lines) {
  // An empty lines is used to indicate the end of input
  const size_t num_lines = lines.GetSize();
  if (num_lines > 0 && lines[num_lines - 1].empty()) {
    // Remove the last empty line from "lines" so it doesn't appear in our
    // resulting input and return true to indicate we are done getting lines
    lines.PopBack();
    return true;
  }
  return false;
}

void CommandObjectExpression::GetMultilineExpression() {
  m_expr_lines.clear();
  m_expr_line_count = 0;

  Debugger &debugger = GetCommandInterpreter().GetDebugger();
  bool color_prompt = debugger.GetUseColor();
  const bool multiple_lines = true; // Get multiple lines
  IOHandlerSP io_handler_sp(
      new IOHandlerEditline(debugger, IOHandler::Type::Expression,
                            "lldb-expr", // Name of input reader for history
                            llvm::StringRef(), // No prompt
                            llvm::StringRef(), // Continuation prompt
                            multiple_lines, color_prompt,
                            1, // Show line numbers starting at 1
                            *this));

  StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile());
  if (output_sp) {
    output_sp->PutCString(
        "Enter expressions, then terminate with an empty line to evaluate:\n");
    output_sp->Flush();
  }
  debugger.PushIOHandler(io_handler_sp);
}

bool CommandObjectExpression::DoExecute(const char *command,
                                        CommandReturnObject &result) {
  m_fixed_expression.clear();
  auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
  m_option_group.NotifyOptionParsingStarting(&exe_ctx);

  const char *expr = nullptr;

  if (command[0] == '\0') {
    GetMultilineExpression();
    return result.Succeeded();
  }

  if (command[0] == '-') {
    // We have some options and these options MUST end with --.
    const char *end_options = nullptr;
    const char *s = command;
    while (s && s[0]) {
      end_options = ::strstr(s, "--");
      if (end_options) {
        end_options += 2; // Get past the "--"
        if (::isspace(end_options[0])) {
          expr = end_options;
          while (::isspace(*expr))
            ++expr;
          break;
        }
      }
      s = end_options;
    }

    if (end_options) {
      Args args(llvm::StringRef(command, end_options - command));
      if (!ParseOptions(args, result))
        return false;

      Status error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
      if (error.Fail()) {
        result.AppendError(error.AsCString());
        result.SetStatus(eReturnStatusFailed);
        return false;
      }

      if (m_repl_option.GetOptionValue().GetCurrentValue()) {
        Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
        if (target) {
          // Drop into REPL
          m_expr_lines.clear();
          m_expr_line_count = 0;

          Debugger &debugger = target->GetDebugger();

          // Check if the LLDB command interpreter is sitting on top of a REPL
          // that launched it...
          if (debugger.CheckTopIOHandlerTypes(
                  IOHandler::Type::CommandInterpreter, IOHandler::Type::REPL)) {
            // the LLDB command interpreter is sitting on top of a REPL that
            // launched it, so just say the command interpreter is done and
            // fall back to the existing REPL
            m_interpreter.GetIOHandler(false)->SetIsDone(true);
          } else {
            // We are launching the REPL on top of the current LLDB command
            // interpreter, so just push one
            bool initialize = false;
            Status repl_error;
            REPLSP repl_sp(target->GetREPL(
                repl_error, m_command_options.language, nullptr, false));

            if (!repl_sp) {
              initialize = true;
              repl_sp = target->GetREPL(repl_error, m_command_options.language,
                                        nullptr, true);
              if (!repl_error.Success()) {
                result.SetError(repl_error);
                return result.Succeeded();
              }
            }

            if (repl_sp) {
              if (initialize) {
                repl_sp->SetCommandOptions(m_command_options);
                repl_sp->SetFormatOptions(m_format_options);
                repl_sp->SetValueObjectDisplayOptions(m_varobj_options);
              }

              IOHandlerSP io_handler_sp(repl_sp->GetIOHandler());

              io_handler_sp->SetIsDone(false);

              debugger.PushIOHandler(io_handler_sp);
            } else {
              repl_error.SetErrorStringWithFormat(
                  "Couldn't create a REPL for %s",
                  Language::GetNameForLanguageType(m_command_options.language));
              result.SetError(repl_error);
              return result.Succeeded();
            }
          }
        }
      }
      // No expression following options
      else if (expr == nullptr || expr[0] == '\0') {
        GetMultilineExpression();
        return result.Succeeded();
      }
    }
  }

  if (expr == nullptr)
    expr = command;

  Target *target = GetSelectedOrDummyTarget();
  if (EvaluateExpression(expr, &(result.GetOutputStream()),
                         &(result.GetErrorStream()), &result)) {

    if (!m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts()) {
      CommandHistory &history = m_interpreter.GetCommandHistory();
      // FIXME: Can we figure out what the user actually typed (e.g. some alias
      // for expr???)
      // If we can it would be nice to show that.
      std::string fixed_command("expression ");
      if (expr == command)
        fixed_command.append(m_fixed_expression);
      else {
        // Add in any options that might have been in the original command:
        fixed_command.append(command, expr - command);
        fixed_command.append(m_fixed_expression);
      }
      history.AppendString(fixed_command);
    }
    // Increment statistics to record this expression evaluation success.
    target->IncrementStats(StatisticKind::ExpressionSuccessful);
    return true;
  }

  // Increment statistics to record this expression evaluation failure.
  target->IncrementStats(StatisticKind::ExpressionFailure);
  result.SetStatus(eReturnStatusFailed);
  return false;
}
