//===-- GoUserExpression.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
#include <stdio.h>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif

// C++ Includes
#include <cstdlib>
#include <memory>
#include <string>
#include <vector>

// Other libraries and framework includes
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"

// Project includes
#include "GoUserExpression.h"

#include "lldb/Core/ConstString.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataEncoder.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Symbol/GoASTContext.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanCallUserExpression.h"
#include "lldb/lldb-private.h"

#include "Plugins/ExpressionParser/Go/GoAST.h"
#include "Plugins/ExpressionParser/Go/GoParser.h"

using namespace lldb_private;
using namespace lldb;

class GoUserExpression::GoInterpreter {
public:
  GoInterpreter(ExecutionContext &exe_ctx, const char *expr)
      : m_exe_ctx(exe_ctx), m_frame(exe_ctx.GetFrameSP()), m_parser(expr) {
    if (m_frame) {
      const SymbolContext &ctx =
          m_frame->GetSymbolContext(eSymbolContextFunction);
      ConstString fname = ctx.GetFunctionName();
      if (fname.GetLength() > 0) {
        size_t dot = fname.GetStringRef().find('.');
        if (dot != llvm::StringRef::npos)
          m_package = llvm::StringRef(fname.AsCString(), dot);
      }
    }
  }

  void set_use_dynamic(DynamicValueType use_dynamic) {
    m_use_dynamic = use_dynamic;
  }

  bool Parse();
  lldb::ValueObjectSP Evaluate(ExecutionContext &exe_ctx);
  lldb::ValueObjectSP EvaluateStatement(const GoASTStmt *s);
  lldb::ValueObjectSP EvaluateExpr(const GoASTExpr *e);

  ValueObjectSP VisitBadExpr(const GoASTBadExpr *e) {
    m_parser.GetError(m_error);
    return nullptr;
  }

  ValueObjectSP VisitParenExpr(const GoASTParenExpr *e);
  ValueObjectSP VisitIdent(const GoASTIdent *e);
  ValueObjectSP VisitStarExpr(const GoASTStarExpr *e);
  ValueObjectSP VisitSelectorExpr(const GoASTSelectorExpr *e);
  ValueObjectSP VisitBasicLit(const GoASTBasicLit *e);
  ValueObjectSP VisitIndexExpr(const GoASTIndexExpr *e);
  ValueObjectSP VisitUnaryExpr(const GoASTUnaryExpr *e);
  ValueObjectSP VisitCallExpr(const GoASTCallExpr *e);

  ValueObjectSP VisitTypeAssertExpr(const GoASTTypeAssertExpr *e) {
    return NotImplemented(e);
  }

  ValueObjectSP VisitBinaryExpr(const GoASTBinaryExpr *e) {
    return NotImplemented(e);
  }

  ValueObjectSP VisitArrayType(const GoASTArrayType *e) {
    return NotImplemented(e);
  }

  ValueObjectSP VisitChanType(const GoASTChanType *e) {
    return NotImplemented(e);
  }

  ValueObjectSP VisitCompositeLit(const GoASTCompositeLit *e) {
    return NotImplemented(e);
  }

  ValueObjectSP VisitEllipsis(const GoASTEllipsis *e) {
    return NotImplemented(e);
  }

  ValueObjectSP VisitFuncType(const GoASTFuncType *e) {
    return NotImplemented(e);
  }

  ValueObjectSP VisitFuncLit(const GoASTFuncLit *e) {
    return NotImplemented(e);
  }

  ValueObjectSP VisitInterfaceType(const GoASTInterfaceType *e) {
    return NotImplemented(e);
  }

  ValueObjectSP VisitKeyValueExpr(const GoASTKeyValueExpr *e) {
    return NotImplemented(e);
  }

  ValueObjectSP VisitMapType(const GoASTMapType *e) {
    return NotImplemented(e);
  }

  ValueObjectSP VisitSliceExpr(const GoASTSliceExpr *e) {
    return NotImplemented(e);
  }

  ValueObjectSP VisitStructType(const GoASTStructType *e) {
    return NotImplemented(e);
  }

  CompilerType EvaluateType(const GoASTExpr *e);

  Error &error() { return m_error; }

private:
  std::nullptr_t NotImplemented(const GoASTExpr *e) {
    m_error.SetErrorStringWithFormat("%s node not implemented",
                                     e->GetKindName());
    return nullptr;
  }

  ExecutionContext m_exe_ctx;
  lldb::StackFrameSP m_frame;
  GoParser m_parser;
  DynamicValueType m_use_dynamic;
  Error m_error;
  llvm::StringRef m_package;
  std::vector<std::unique_ptr<GoASTStmt>> m_statements;
};

VariableSP FindGlobalVariable(TargetSP target, llvm::Twine name) {
  ConstString fullname(name.str());
  VariableList variable_list;
  const bool append = true;
  if (!target) {
    return nullptr;
  }
  const uint32_t match_count = target->GetImages().FindGlobalVariables(
      fullname, append, 1, variable_list);
  if (match_count == 1) {
    return variable_list.GetVariableAtIndex(0);
  }
  return nullptr;
}

CompilerType LookupType(TargetSP target, ConstString name) {
  if (!target)
    return CompilerType();
  SymbolContext sc;
  TypeList type_list;
  llvm::DenseSet<SymbolFile *> searched_symbol_files;
  uint32_t num_matches = target->GetImages().FindTypes(
      sc, name, false, 2, searched_symbol_files, type_list);
  if (num_matches > 0) {
    return type_list.GetTypeAtIndex(0)->GetFullCompilerType();
  }
  return CompilerType();
}

GoUserExpression::GoUserExpression(ExecutionContextScope &exe_scope,
                                   llvm::StringRef expr, llvm::StringRef prefix,
                                   lldb::LanguageType language,
                                   ResultType desired_type,
                                   const EvaluateExpressionOptions &options)
    : UserExpression(exe_scope, expr, prefix, language, desired_type, options) {
}

bool GoUserExpression::Parse(DiagnosticManager &diagnostic_manager,
                             ExecutionContext &exe_ctx,
                             lldb_private::ExecutionPolicy execution_policy,
                             bool keep_result_in_memory,
                             bool generate_debug_info) {
  InstallContext(exe_ctx);
  m_interpreter.reset(new GoInterpreter(exe_ctx, GetUserText()));
  if (m_interpreter->Parse())
    return true;
  const char *error_cstr = m_interpreter->error().AsCString();
  if (error_cstr && error_cstr[0])
    diagnostic_manager.PutString(eDiagnosticSeverityError, error_cstr);
  else
    diagnostic_manager.Printf(eDiagnosticSeverityError,
                              "expression can't be interpreted or run");
  return false;
}

lldb::ExpressionResults
GoUserExpression::DoExecute(DiagnosticManager &diagnostic_manager,
                            ExecutionContext &exe_ctx,
                            const EvaluateExpressionOptions &options,
                            lldb::UserExpressionSP &shared_ptr_to_me,
                            lldb::ExpressionVariableSP &result) {
  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS |
                                                  LIBLLDB_LOG_STEP));

  lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
  lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;

  Process *process = exe_ctx.GetProcessPtr();
  Target *target = exe_ctx.GetTargetPtr();

  if (target == nullptr || process == nullptr ||
      process->GetState() != lldb::eStateStopped) {
    if (execution_policy == eExecutionPolicyAlways) {
      if (log)
        log->Printf("== [GoUserExpression::Evaluate] Expression may not run, "
                    "but is not constant ==");

      diagnostic_manager.PutString(eDiagnosticSeverityError,
                                   "expression needed to run but couldn't");

      return execution_results;
    }
  }

  m_interpreter->set_use_dynamic(options.GetUseDynamic());
  ValueObjectSP result_val_sp = m_interpreter->Evaluate(exe_ctx);
  Error err = m_interpreter->error();
  m_interpreter.reset();

  if (!result_val_sp) {
    const char *error_cstr = err.AsCString();
    if (error_cstr && error_cstr[0])
      diagnostic_manager.PutString(eDiagnosticSeverityError, error_cstr);
    else
      diagnostic_manager.PutString(eDiagnosticSeverityError,
                                   "expression can't be interpreted or run");
    return lldb::eExpressionDiscarded;
  }
  result.reset(new ExpressionVariable(ExpressionVariable::eKindGo));
  result->m_live_sp = result->m_frozen_sp = result_val_sp;
  result->m_flags |= ExpressionVariable::EVIsProgramReference;
  PersistentExpressionState *pv =
      target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo);
  if (pv != nullptr) {
    result->SetName(pv->GetNextPersistentVariableName());
    pv->AddVariable(result);
  }
  return lldb::eExpressionCompleted;
}

bool GoUserExpression::GoInterpreter::Parse() {
  for (std::unique_ptr<GoASTStmt> stmt(m_parser.Statement()); stmt;
       stmt.reset(m_parser.Statement())) {
    if (m_parser.Failed())
      break;
    m_statements.emplace_back(std::move(stmt));
  }
  if (m_parser.Failed() || !m_parser.AtEOF())
    m_parser.GetError(m_error);

  return m_error.Success();
}

ValueObjectSP
GoUserExpression::GoInterpreter::Evaluate(ExecutionContext &exe_ctx) {
  m_exe_ctx = exe_ctx;
  ValueObjectSP result;
  for (const std::unique_ptr<GoASTStmt> &stmt : m_statements) {
    result = EvaluateStatement(stmt.get());
    if (m_error.Fail())
      return nullptr;
  }
  return result;
}

ValueObjectSP GoUserExpression::GoInterpreter::EvaluateStatement(
    const lldb_private::GoASTStmt *stmt) {
  ValueObjectSP result;
  switch (stmt->GetKind()) {
  case GoASTNode::eBlockStmt: {
    const GoASTBlockStmt *block = llvm::cast<GoASTBlockStmt>(stmt);
    for (size_t i = 0; i < block->NumList(); ++i)
      result = EvaluateStatement(block->GetList(i));
    break;
  }
  case GoASTNode::eBadStmt:
    m_parser.GetError(m_error);
    break;
  case GoASTNode::eExprStmt: {
    const GoASTExprStmt *expr = llvm::cast<GoASTExprStmt>(stmt);
    return EvaluateExpr(expr->GetX());
  }
  default:
    m_error.SetErrorStringWithFormat("%s node not supported",
                                     stmt->GetKindName());
  }
  return result;
}

ValueObjectSP GoUserExpression::GoInterpreter::EvaluateExpr(
    const lldb_private::GoASTExpr *e) {
  if (e)
    return e->Visit<ValueObjectSP>(this);
  return ValueObjectSP();
}

ValueObjectSP GoUserExpression::GoInterpreter::VisitParenExpr(
    const lldb_private::GoASTParenExpr *e) {
  return EvaluateExpr(e->GetX());
}

ValueObjectSP GoUserExpression::GoInterpreter::VisitIdent(const GoASTIdent *e) {
  ValueObjectSP val;
  if (m_frame) {
    VariableSP var_sp;
    std::string varname = e->GetName().m_value.str();
    if (varname.size() > 1 && varname[0] == '$') {
      RegisterContextSP reg_ctx_sp = m_frame->GetRegisterContext();
      const RegisterInfo *reg =
          reg_ctx_sp->GetRegisterInfoByName(varname.c_str() + 1);
      if (reg) {
        std::string type;
        switch (reg->encoding) {
        case lldb::eEncodingSint:
          type.append("int");
          break;
        case lldb::eEncodingUint:
          type.append("uint");
          break;
        case lldb::eEncodingIEEE754:
          type.append("float");
          break;
        default:
          m_error.SetErrorString("Invalid register encoding");
          return nullptr;
        }
        switch (reg->byte_size) {
        case 8:
          type.append("64");
          break;
        case 4:
          type.append("32");
          break;
        case 2:
          type.append("16");
          break;
        case 1:
          type.append("8");
          break;
        default:
          m_error.SetErrorString("Invalid register size");
          return nullptr;
        }
        ValueObjectSP regVal = ValueObjectRegister::Create(
            m_frame.get(), reg_ctx_sp, reg->kinds[eRegisterKindLLDB]);
        CompilerType goType =
            LookupType(m_frame->CalculateTarget(), ConstString(type));
        if (regVal) {
          regVal = regVal->Cast(goType);
          return regVal;
        }
      }
      m_error.SetErrorString("Invalid register name");
      return nullptr;
    }
    VariableListSP var_list_sp(m_frame->GetInScopeVariableList(false));
    if (var_list_sp) {
      var_sp = var_list_sp->FindVariable(ConstString(varname));
      if (var_sp)
        val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic);
      else {
        // When a variable is on the heap instead of the stack, go records a
        // variable
        // '&x' instead of 'x'.
        var_sp = var_list_sp->FindVariable(ConstString("&" + varname));
        if (var_sp) {
          val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic);
          if (val)
            val = val->Dereference(m_error);
          if (m_error.Fail())
            return nullptr;
        }
      }
    }
    if (!val) {
      m_error.Clear();
      TargetSP target = m_frame->CalculateTarget();
      if (!target) {
        m_error.SetErrorString("No target");
        return nullptr;
      }
      var_sp =
          FindGlobalVariable(target, m_package + "." + e->GetName().m_value);
      if (var_sp)
        return m_frame->TrackGlobalVariable(var_sp, m_use_dynamic);
    }
  }
  if (!val)
    m_error.SetErrorStringWithFormat("Unknown variable %s",
                                     e->GetName().m_value.str().c_str());
  return val;
}

ValueObjectSP
GoUserExpression::GoInterpreter::VisitStarExpr(const GoASTStarExpr *e) {
  ValueObjectSP target = EvaluateExpr(e->GetX());
  if (!target)
    return nullptr;
  return target->Dereference(m_error);
}

ValueObjectSP GoUserExpression::GoInterpreter::VisitSelectorExpr(
    const lldb_private::GoASTSelectorExpr *e) {
  ValueObjectSP target = EvaluateExpr(e->GetX());
  if (target) {
    if (target->GetCompilerType().IsPointerType()) {
      target = target->Dereference(m_error);
      if (m_error.Fail())
        return nullptr;
    }
    ConstString field(e->GetSel()->GetName().m_value);
    ValueObjectSP result = target->GetChildMemberWithName(field, true);
    if (!result)
      m_error.SetErrorStringWithFormat("Unknown child %s", field.AsCString());
    return result;
  }
  if (const GoASTIdent *package = llvm::dyn_cast<GoASTIdent>(e->GetX())) {
    if (VariableSP global = FindGlobalVariable(
            m_exe_ctx.GetTargetSP(), package->GetName().m_value + "." +
                                         e->GetSel()->GetName().m_value)) {
      if (m_frame) {
        m_error.Clear();
        return m_frame->GetValueObjectForFrameVariable(global, m_use_dynamic);
      }
    }
  }
  if (const GoASTBasicLit *packageLit =
          llvm::dyn_cast<GoASTBasicLit>(e->GetX())) {
    if (packageLit->GetValue().m_type == GoLexer::LIT_STRING) {
      std::string value = packageLit->GetValue().m_value.str();
      value = value.substr(1, value.size() - 2);
      if (VariableSP global = FindGlobalVariable(
              m_exe_ctx.GetTargetSP(),
              value + "." + e->GetSel()->GetName().m_value)) {
        if (m_frame) {
          m_error.Clear();
          return m_frame->TrackGlobalVariable(global, m_use_dynamic);
        }
      }
    }
  }
  // EvaluateExpr should have already set m_error.
  return target;
}

ValueObjectSP GoUserExpression::GoInterpreter::VisitBasicLit(
    const lldb_private::GoASTBasicLit *e) {
  std::string value = e->GetValue().m_value.str();
  if (e->GetValue().m_type != GoLexer::LIT_INTEGER) {
    m_error.SetErrorStringWithFormat("Unsupported literal %s", value.c_str());
    return nullptr;
  }
  errno = 0;
  int64_t intvalue = strtol(value.c_str(), nullptr, 0);
  if (errno != 0) {
    m_error.SetErrorToErrno();
    return nullptr;
  }
  DataBufferSP buf(new DataBufferHeap(sizeof(intvalue), 0));
  TargetSP target = m_exe_ctx.GetTargetSP();
  if (!target) {
    m_error.SetErrorString("No target");
    return nullptr;
  }
  ByteOrder order = target->GetArchitecture().GetByteOrder();
  uint8_t addr_size = target->GetArchitecture().GetAddressByteSize();
  DataEncoder enc(buf, order, addr_size);
  enc.PutU64(0, static_cast<uint64_t>(intvalue));
  DataExtractor data(buf, order, addr_size);

  CompilerType type = LookupType(target, ConstString("int64"));
  return ValueObject::CreateValueObjectFromData(llvm::StringRef(), data,
                                                m_exe_ctx, type);
}

ValueObjectSP GoUserExpression::GoInterpreter::VisitIndexExpr(
    const lldb_private::GoASTIndexExpr *e) {
  ValueObjectSP target = EvaluateExpr(e->GetX());
  if (!target)
    return nullptr;
  ValueObjectSP index = EvaluateExpr(e->GetIndex());
  if (!index)
    return nullptr;
  bool is_signed;
  if (!index->GetCompilerType().IsIntegerType(is_signed)) {
    m_error.SetErrorString("Unsupported index");
    return nullptr;
  }
  size_t idx;
  if (is_signed)
    idx = index->GetValueAsSigned(0);
  else
    idx = index->GetValueAsUnsigned(0);
  if (GoASTContext::IsGoSlice(target->GetCompilerType())) {
    target = target->GetStaticValue();
    ValueObjectSP cap =
        target->GetChildMemberWithName(ConstString("cap"), true);
    if (cap) {
      uint64_t capval = cap->GetValueAsUnsigned(0);
      if (idx >= capval) {
        m_error.SetErrorStringWithFormat("Invalid index %" PRIu64
                                         " , cap = %" PRIu64,
                                         uint64_t(idx), capval);
        return nullptr;
      }
    }
    target = target->GetChildMemberWithName(ConstString("array"), true);
    if (target && m_use_dynamic != eNoDynamicValues) {
      ValueObjectSP dynamic = target->GetDynamicValue(m_use_dynamic);
      if (dynamic)
        target = dynamic;
    }
    if (!target)
      return nullptr;
    return target->GetSyntheticArrayMember(idx, true);
  }
  return target->GetChildAtIndex(idx, true);
}

ValueObjectSP
GoUserExpression::GoInterpreter::VisitUnaryExpr(const GoASTUnaryExpr *e) {
  ValueObjectSP x = EvaluateExpr(e->GetX());
  if (!x)
    return nullptr;
  switch (e->GetOp()) {
  case GoLexer::OP_AMP: {
    CompilerType type = x->GetCompilerType().GetPointerType();
    uint64_t address = x->GetAddressOf();
    return ValueObject::CreateValueObjectFromAddress(llvm::StringRef(), address,
                                                     m_exe_ctx, type);
  }
  case GoLexer::OP_PLUS:
    return x;
  default:
    m_error.SetErrorStringWithFormat(
        "Operator %s not supported",
        GoLexer::LookupToken(e->GetOp()).str().c_str());
    return nullptr;
  }
}

CompilerType GoUserExpression::GoInterpreter::EvaluateType(const GoASTExpr *e) {
  TargetSP target = m_exe_ctx.GetTargetSP();
  if (auto *id = llvm::dyn_cast<GoASTIdent>(e)) {
    CompilerType result =
        LookupType(target, ConstString(id->GetName().m_value));
    if (result.IsValid())
      return result;
    std::string fullname = (m_package + "." + id->GetName().m_value).str();
    result = LookupType(target, ConstString(fullname));
    if (!result)
      m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str());
    return result;
  }
  if (auto *sel = llvm::dyn_cast<GoASTSelectorExpr>(e)) {
    std::string package;
    if (auto *pkg_node = llvm::dyn_cast<GoASTIdent>(sel->GetX())) {
      package = pkg_node->GetName().m_value.str();
    } else if (auto *str_node = llvm::dyn_cast<GoASTBasicLit>(sel->GetX())) {
      if (str_node->GetValue().m_type == GoLexer::LIT_STRING) {
        package = str_node->GetValue().m_value.substr(1).str();
        package.resize(package.length() - 1);
      }
    }
    if (package.empty()) {
      m_error.SetErrorStringWithFormat("Invalid %s in type expression",
                                       sel->GetX()->GetKindName());
      return CompilerType();
    }
    std::string fullname =
        (package + "." + sel->GetSel()->GetName().m_value).str();
    CompilerType result = LookupType(target, ConstString(fullname));
    if (!result)
      m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str());
    return result;
  }
  if (auto *star = llvm::dyn_cast<GoASTStarExpr>(e)) {
    CompilerType elem = EvaluateType(star->GetX());
    return elem.GetPointerType();
  }
  if (auto *paren = llvm::dyn_cast<GoASTParenExpr>(e))
    return EvaluateType(paren->GetX());
  if (auto *array = llvm::dyn_cast<GoASTArrayType>(e)) {
    CompilerType elem = EvaluateType(array->GetElt());
  }

  m_error.SetErrorStringWithFormat("Invalid %s in type expression",
                                   e->GetKindName());
  return CompilerType();
}

ValueObjectSP GoUserExpression::GoInterpreter::VisitCallExpr(
    const lldb_private::GoASTCallExpr *e) {
  ValueObjectSP x = EvaluateExpr(e->GetFun());
  if (x || e->NumArgs() != 1) {
    m_error.SetErrorStringWithFormat("Code execution not supported");
    return nullptr;
  }
  m_error.Clear();
  CompilerType type = EvaluateType(e->GetFun());
  if (!type) {
    return nullptr;
  }
  ValueObjectSP value = EvaluateExpr(e->GetArgs(0));
  if (!value)
    return nullptr;
  // TODO: Handle special conversions
  return value->Cast(type);
}

GoPersistentExpressionState::GoPersistentExpressionState()
    : PersistentExpressionState(eKindGo) {}

ConstString GoPersistentExpressionState::GetNextPersistentVariableName() {
  char name_cstr[256];
  // We can't use the same variable format as clang.
  ::snprintf(name_cstr, sizeof(name_cstr), "$go%u",
             m_next_persistent_variable_id++);
  ConstString name(name_cstr);
  return name;
}

void GoPersistentExpressionState::RemovePersistentVariable(
    lldb::ExpressionVariableSP variable) {
  RemoveVariable(variable);

  const char *name = variable->GetName().AsCString();

  if (*(name++) != '$')
    return;
  if (*(name++) != 'g')
    return;
  if (*(name++) != 'o')
    return;

  if (strtoul(name, nullptr, 0) == m_next_persistent_variable_id - 1)
    m_next_persistent_variable_id--;
}
