// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/developer/debug/zxdb/expr/expr_node.h"

#include <stdlib.h>

#include <ostream>

#include "src/developer/debug/shared/message_loop.h"
#include "src/developer/debug/zxdb/common/err.h"
#include "src/developer/debug/zxdb/expr/cast.h"
#include "src/developer/debug/zxdb/expr/eval_context.h"
#include "src/developer/debug/zxdb/expr/eval_operators.h"
#include "src/developer/debug/zxdb/expr/expr_value.h"
#include "src/developer/debug/zxdb/expr/number_parser.h"
#include "src/developer/debug/zxdb/expr/pretty_type.h"
#include "src/developer/debug/zxdb/expr/pretty_type_manager.h"
#include "src/developer/debug/zxdb/expr/resolve_array.h"
#include "src/developer/debug/zxdb/expr/resolve_collection.h"
#include "src/developer/debug/zxdb/expr/resolve_ptr_ref.h"
#include "src/developer/debug/zxdb/symbols/arch.h"
#include "src/developer/debug/zxdb/symbols/array_type.h"
#include "src/developer/debug/zxdb/symbols/base_type.h"
#include "src/developer/debug/zxdb/symbols/collection.h"
#include "src/developer/debug/zxdb/symbols/data_member.h"
#include "src/developer/debug/zxdb/symbols/modified_type.h"
#include "src/developer/debug/zxdb/symbols/symbol_data_provider.h"
#include "src/developer/debug/zxdb/symbols/symbol_utils.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {

namespace {

std::string IndentFor(int value) { return std::string(value, ' '); }

bool BaseTypeCanBeArrayIndex(const BaseType* type) {
  int bt = type->base_type();
  return bt == BaseType::kBaseTypeBoolean || bt == BaseType::kBaseTypeSigned ||
         bt == BaseType::kBaseTypeSignedChar || bt == BaseType::kBaseTypeUnsigned ||
         bt == BaseType::kBaseTypeUnsignedChar;
}

void DoResolveConcreteMember(const fxl::RefPtr<EvalContext>& context, const ExprValue& value,
                             const ParsedIdentifier& member, EvalCallback cb) {
  if (PrettyType* pretty = context->GetPrettyTypeManager().GetForType(value.type())) {
    if (auto getter = pretty->GetMember(member.GetFullName())) {
      return getter(context, value, std::move(cb));
    }
  }

  return ResolveMember(context, value, member, std::move(cb));
}

}  // namespace

void ExprNode::EvalFollowReferences(const fxl::RefPtr<EvalContext>& context,
                                    EvalCallback cb) const {
  Eval(context, [context, cb = std::move(cb)](ErrOrValue value) mutable {
    if (value.has_error())
      return cb(value);
    EnsureResolveReference(context, std::move(value.value()), std::move(cb));
  });
}

void AddressOfExprNode::Eval(const fxl::RefPtr<EvalContext>& context, EvalCallback cb) const {
  expr_->EvalFollowReferences(context, [cb = std::move(cb)](ErrOrValue value) mutable {
    if (value.has_error()) {
      cb(value);
    } else if (value.value().source().type() != ExprValueSource::Type::kMemory) {
      cb(Err("Can't take the address of a temporary."));
    } else if (value.value().source().bit_size() != 0) {
      cb(Err("Can't take the address of a bitfield."));
    } else {
      // Construct a pointer type to the variable.
      auto ptr_type =
          fxl::MakeRefCounted<ModifiedType>(DwarfTag::kPointerType, value.value().type_ref());

      std::vector<uint8_t> contents;
      contents.resize(kTargetPointerSize);
      TargetPointer address = value.value().source().address();
      memcpy(&contents[0], &address, sizeof(kTargetPointerSize));

      cb(ExprValue(std::move(ptr_type), std::move(contents)));
    }
  });
}

void AddressOfExprNode::Print(std::ostream& out, int indent) const {
  out << IndentFor(indent) << "ADDRESS_OF\n";
  expr_->Print(out, indent + 1);
}

void ArrayAccessExprNode::Eval(const fxl::RefPtr<EvalContext>& context, EvalCallback cb) const {
  left_->EvalFollowReferences(context, [inner = inner_, context,
                                        cb = std::move(cb)](ErrOrValue left_value) mutable {
    if (left_value.has_error()) {
      cb(left_value);
    } else {
      // "left" has been evaluated, now do "inner".
      inner->EvalFollowReferences(context, [context, left_value = left_value.take_value(),
                                            cb = std::move(cb)](ErrOrValue inner_value) mutable {
        if (inner_value.has_error()) {
          cb(inner_value);
        } else {
          // Both "left" and "inner" has been evaluated.
          int64_t offset = 0;
          if (Err err = InnerValueToOffset(context, inner_value.value(), &offset); err.has_error())
            cb(err);
          else
            ResolveArrayItem(std::move(context), std::move(left_value), offset, std::move(cb));
        }
      });
    }
  });
}

// static
Err ArrayAccessExprNode::InnerValueToOffset(const fxl::RefPtr<EvalContext>& context,
                                            const ExprValue& inner, int64_t* offset) {
  // Type should be some kind of number.
  const Type* abstract_type = inner.type();
  if (!abstract_type)
    return Err("Bad type, please file a bug with a repro.");

  // Skip "const", etc.
  fxl::RefPtr<Type> concrete_type = context->GetConcreteType(abstract_type);

  const BaseType* base_type = concrete_type->AsBaseType();
  if (!base_type || !BaseTypeCanBeArrayIndex(base_type))
    return Err("Bad type for array index.");

  // This uses signed integers to explicitly allow negative indexing which the user may want to do
  // for some reason.
  Err promote_err = inner.PromoteTo64(offset);
  if (promote_err.has_error())
    return promote_err;
  return Err();
}

void ArrayAccessExprNode::Print(std::ostream& out, int indent) const {
  out << IndentFor(indent) << "ARRAY_ACCESS\n";
  left_->Print(out, indent + 1);
  inner_->Print(out, indent + 1);
}

void BinaryOpExprNode::Eval(const fxl::RefPtr<EvalContext>& context, EvalCallback cb) const {
  EvalBinaryOperator(std::move(context), left_, op_, right_, std::move(cb));
}

void BinaryOpExprNode::Print(std::ostream& out, int indent) const {
  out << IndentFor(indent) << "BINARY_OP(" + op_.value() + ")\n";
  left_->Print(out, indent + 1);
  right_->Print(out, indent + 1);
}

void BlockExprNode::Eval(const fxl::RefPtr<EvalContext>& context, EvalCallback cb) const {
  EvalBlockFrom(RefPtrTo(this), 0, context, std::move(cb));
}

void BlockExprNode::Print(std::ostream& out, int indent) const {
  out << IndentFor(indent) << "BLOCK\n";
  for (const auto& stmt : statements_)
    stmt->Print(out, indent + 1);
}

// static
void BlockExprNode::EvalBlockFrom(fxl::RefPtr<BlockExprNode> node, size_t index,
                                  const fxl::RefPtr<EvalContext>& context, EvalCallback cb) {
  if (index >= node->statements_.size())
    return cb(ExprValue());

  if (index + 1 == node->statements_.size()) {
    // The last statement in a block.
    switch (context->GetLanguage()) {
      case ExprLanguage::kC:
        // Discard the result since blocks in C aren't expressions.
        node->statements_[index]->Eval(context, [cb = std::move(cb)](ErrOrValue result) mutable {
          cb(result.value_or_empty());
        });
        break;
      case ExprLanguage::kRust:
        // The result of a block expression is the result of the last statement inside it.
        node->statements_[index]->Eval(context, std::move(cb));
        break;
    }
  } else {
    // Need to evaluate a sequence of operations following this.
    node->statements_[index]->Eval(context, [node = std::move(node), context, index,
                                             cb = std::move(cb)](ErrOrValue result) mutable {
      if (result.has_error())
        return cb(std::move(result));

      // If we called EvalBlock() directly here, block evaluation would be recursive. For blocks
      // with several lines this will be fine, but this will fall down in the general case because
      // there can be many statements in a block and we can overflow the stack. Instead, resume
      // evaluation of the next statement back from the message loop. This will be slower but more
      // predictable.
      debug_ipc::MessageLoop::Current()->PostTask(
          FROM_HERE, [node = std::move(node), context, index, cb = std::move(cb)]() mutable {
            EvalBlockFrom(std::move(node), index + 1, context, std::move(cb));
          });
    });
  }
}

void CastExprNode::Eval(const fxl::RefPtr<EvalContext>& context, EvalCallback cb) const {
  from_->Eval(context, [context, cast_type = cast_type_, to_type = to_type_->type(),
                        cb = std::move(cb)](ErrOrValue value) mutable {
    if (value.has_error())
      cb(value);
    else
      CastExprValue(context, cast_type, value.value(), to_type, ExprValueSource(), std::move(cb));
  });
}

void CastExprNode::Print(std::ostream& out, int indent) const {
  out << IndentFor(indent) << "CAST(" << CastTypeToString(cast_type_) << ")\n";
  to_type_->Print(out, indent + 1);
  from_->Print(out, indent + 1);
}

void ConditionExprNode::Eval(const fxl::RefPtr<EvalContext>& context, EvalCallback cb) const {
  EvalFromCond(RefPtrTo(this), 0, context, std::move(cb));
}

void ConditionExprNode::Print(std::ostream& out, int indent) const {
  out << IndentFor(indent) << "CONDITION\n";
  for (size_t i = 0; i < conds_.size(); i++) {
    if (i == 0)
      out << IndentFor(indent + 1) << "IF\n";
    else
      out << IndentFor(indent + 1) << "ELSEIF\n";
    conds_[i].cond->Print(out, indent + 2);

    if (conds_[i].then) {
      out << IndentFor(indent + 1) << "THEN\n";
      conds_[i].then->Print(out, indent + 2);
    }
  }
  if (else_) {
    out << IndentFor(indent + 1) << "ELSE\n";
    else_->Print(out, indent + 2);
  }
}

void ConditionExprNode::EvalFromCond(fxl::RefPtr<ConditionExprNode> node, size_t index,
                                     const fxl::RefPtr<EvalContext>& context, EvalCallback cb) {
  if (index >= node->conds_.size()) {
    // Evaluate "else" block.
    if (node->else_) {
      node->else_->Eval(std::move(context), std::move(cb));
    } else {
      // No "else" block given, the result is empty.
      cb(ExprValue());
    }
    return;
  }

  node->conds_[index].cond->EvalFollowReferences(
      context,
      [node = std::move(node), index, context, cb = std::move(cb)](ErrOrValue cond_result) mutable {
        if (cond_result.has_error()) {
          cb(cond_result);
          return;
        }

        ErrOr<bool> bool_result = CastNumericExprValueToBool(context, cond_result.value());
        if (bool_result.has_error()) {
          cb(bool_result.err());
          return;
        }

        if (bool_result.value()) {
          // Condition succeeded, evaluate the current block.
          node->conds_[index].then->Eval(context, std::move(cb));
        } else {
          // Condition failed, go to next one or else block.
          EvalFromCond(node, index + 1, context, std::move(cb));
        }
      });
}

void DereferenceExprNode::Eval(const fxl::RefPtr<EvalContext>& context, EvalCallback cb) const {
  expr_->EvalFollowReferences(context, [context, cb = std::move(cb)](ErrOrValue value) mutable {
    if (value.has_error())
      return cb(std::move(value));

    // First check for pretty-printers for this type.
    if (PrettyType* pretty = context->GetPrettyTypeManager().GetForType(value.value().type())) {
      if (auto derefer = pretty->GetDereferencer()) {
        // The pretty type supplies dereference function.
        return derefer(context, value.value(), std::move(cb));
      }
    }

    // Normal dereferencing operation.
    ResolvePointer(context, value.value(), std::move(cb));
  });
}

void DereferenceExprNode::Print(std::ostream& out, int indent) const {
  out << IndentFor(indent) << "DEREFERENCE\n";
  expr_->Print(out, indent + 1);
}

void FunctionCallExprNode::Eval(const fxl::RefPtr<EvalContext>& context, EvalCallback cb) const {
  // Actually calling functions in the target is not supported.
  const char kNotSupportedMsg[] =
      "Arbitrary function calls are not supported. Only certain built-in getters will work.";
  if (!args_.empty())
    return cb(Err(kNotSupportedMsg));

  if (const MemberAccessExprNode* access = call_->AsMemberAccess()) {
    // Object member calls, check for getters provided by pretty-printers.
    std::string fn_name = access->member().GetFullName();
    access->left()->EvalFollowReferences(
        context,
        [context, cb = std::move(cb), op = access->accessor(), fn_name](ErrOrValue value) mutable {
          if (value.has_error())
            return cb(value);

          if (op.type() == ExprTokenType::kArrow)
            EvalMemberPtrCall(context, value.value(), fn_name, std::move(cb));
          else  // Assume ".".
            EvalMemberCall(context, value.value(), fn_name, std::move(cb));
        });
    return;
  }

  cb(Err(kNotSupportedMsg));
}

void FunctionCallExprNode::Print(std::ostream& out, int indent) const {
  out << IndentFor(indent) << "FUNCTIONCALL\n";
  call_->Print(out, indent + 1);
  for (const auto& arg : args_)
    arg->Print(out, indent + 1);
}

// static
bool FunctionCallExprNode::IsValidCall(const fxl::RefPtr<ExprNode>& call) {
  return call && (call->AsIdentifier() || call->AsMemberAccess());
}

// static
void FunctionCallExprNode::EvalMemberCall(const fxl::RefPtr<EvalContext>& context,
                                          const ExprValue& object, const std::string& fn_name,
                                          EvalCallback cb) {
  if (!object.type())
    return cb(Err("No type information."));

  if (PrettyType* pretty = context->GetPrettyTypeManager().GetForType(object.type())) {
    // Have a PrettyType for the object type.
    if (auto getter = pretty->GetGetter(fn_name)) {
      return getter(context, object,
                    [type_name = object.type()->GetFullName(), fn_name,
                     cb = std::move(cb)](ErrOrValue value) mutable {
                      // This lambda exists just to rewrite the error message so it's clear the
                      // error is coming from the PrettyType and not the users's input. Otherwise
                      // it can look quite confusing.
                      if (value.has_error()) {
                        cb(
                            Err("When evaluating the internal pretty getter '%s()' on the type:\n  "
                                "%s\nGot the error:\n  %s\nPlease file a bug.",
                                fn_name.c_str(), type_name.c_str(), value.err().msg().c_str()));
                      } else {
                        cb(std::move(value));
                      }
                    });
    }
  }

  cb(Err("No built-in getter '%s()' for the type\n  %s", fn_name.c_str(),
         object.type()->GetFullName().c_str()));
}

// static
void FunctionCallExprNode::EvalMemberPtrCall(const fxl::RefPtr<EvalContext>& context,
                                             const ExprValue& object_ptr,
                                             const std::string& fn_name, EvalCallback cb) {
  // Callback executed on the object once the pointer has been dereferenced.
  auto on_pointer_resolved = [context, fn_name, cb = std::move(cb)](ErrOrValue value) mutable {
    if (value.has_error())
      cb(value);
    else
      EvalMemberCall(std::move(context), value.value(), fn_name, std::move(cb));
  };

  // The base object could itself have a dereference operator. For example, if you have a:
  //   std::unique_ptr<std::vector<int>> foo;
  // and do:
  //   foo->size()
  // It needs to use the pretty dereferencer on foo before trying to access the size() function
  // on the resulting object.
  if (PrettyType* pretty = context->GetPrettyTypeManager().GetForType(object_ptr.type())) {
    if (auto derefer = pretty->GetDereferencer()) {
      // The pretty type supplies dereference function.
      return derefer(context, object_ptr, std::move(on_pointer_resolved));
    }
  }

  // Regular, assume the base is a pointer.
  ResolvePointer(context, object_ptr, std::move(on_pointer_resolved));
}

void IdentifierExprNode::Eval(const fxl::RefPtr<EvalContext>& context, EvalCallback cb) const {
  context->GetNamedValue(ident_, std::move(cb));
}

void IdentifierExprNode::Print(std::ostream& out, int indent) const {
  out << IndentFor(indent) << "IDENTIFIER(" << ident_.GetDebugName() << ")\n";
}

void LiteralExprNode::Eval(const fxl::RefPtr<EvalContext>& context, EvalCallback cb) const {
  switch (token_.type()) {
    case ExprTokenType::kInteger: {
      cb(StringToNumber(token_.value()));
      break;
    }
    case ExprTokenType::kFloat: {
      cb(ValueForFloatToken(context->GetLanguage(), token_));
      break;
    }
    case ExprTokenType::kStringLiteral: {
      // Include the null terminator in the string array as C would.
      std::vector<uint8_t> string_as_array;
      string_as_array.reserve(token_.value().size() + 1);
      string_as_array.assign(token_.value().begin(), token_.value().end());
      string_as_array.push_back(0);
      cb(ExprValue(MakeStringLiteralType(token_.value().size() + 1), std::move(string_as_array)));
      break;
    }
    case ExprTokenType::kTrue: {
      cb(ExprValue(true));
      break;
    }
    case ExprTokenType::kFalse: {
      cb(ExprValue(false));
      break;
    }
    default:
      FX_NOTREACHED();
  }
}

void LiteralExprNode::Print(std::ostream& out, int indent) const {
  out << IndentFor(indent) << "LITERAL(" << token_.value() << ")\n";
}

void MemberAccessExprNode::Eval(const fxl::RefPtr<EvalContext>& context, EvalCallback cb) const {
  bool by_pointer = accessor_.type() == ExprTokenType::kArrow;
  left_->EvalFollowReferences(context, [context, by_pointer, member = member_,
                                        cb = std::move(cb)](ErrOrValue base) mutable {
    if (base.has_error())
      return cb(base);

    auto base_value = base.value();

    // Rust references can be accessed with '.'
    if (!by_pointer) {
      fxl::RefPtr<Type> concrete_base = base_value.GetConcreteType(context.get());

      if (!concrete_base || concrete_base->tag() != DwarfTag::kPointerType ||
          concrete_base->GetLanguage() != DwarfLang::kRust ||
          concrete_base->GetAssignedName().substr(0, 1) != "&") {
        return DoResolveConcreteMember(context, base_value, member, std::move(cb));
      }
    }

    PrettyType::EvalFunction getter = [member](const fxl::RefPtr<EvalContext>& context,
                                               const ExprValue& value, EvalCallback cb) {
      DoResolveConcreteMember(context, value, member, std::move(cb));
    };
    PrettyType::EvalFunction derefer = ResolvePointer;

    if (PrettyType* pretty = context->GetPrettyTypeManager().GetForType(base_value.type())) {
      derefer = pretty->GetDereferencer();
    } else {
      fxl::RefPtr<Collection> coll;
      if (Err err = GetConcretePointedToCollection(context, base_value.type(), &coll);
          err.has_error()) {
        return cb(err);
      }

      if (PrettyType* pretty = context->GetPrettyTypeManager().GetForType(coll.get())) {
        getter = pretty->GetMember(member.GetFullName());
      } else {
        getter = nullptr;
      }
    }

    if (getter && derefer) {
      return derefer(context, base_value,
                     [context, member, getter = std::move(getter),
                      cb = std::move(cb)](ErrOrValue non_ptr_base) mutable {
                       if (non_ptr_base.has_error())
                         return cb(non_ptr_base);
                       getter(context, non_ptr_base.value(), std::move(cb));
                     });
    }

    // Normal collection resolution.
    ResolveMemberByPointer(context, base.value(), member,
                           [cb = std::move(cb)](ErrOrValue result, const FoundMember&) mutable {
                             // Discard resolved symbol, we only need the value.
                             cb(std::move(result));
                           });
  });
}

void MemberAccessExprNode::Print(std::ostream& out, int indent) const {
  out << IndentFor(indent) << "ACCESSOR(" << accessor_.value() << ")\n";
  left_->Print(out, indent + 1);
  out << IndentFor(indent + 1) << member_.GetFullName() << "\n";
}

void SizeofExprNode::Eval(const fxl::RefPtr<EvalContext>& context, EvalCallback cb) const {
  if (const TypeExprNode* type_node = const_cast<ExprNode*>(expr_.get())->AsType()) {
    // Types just get used directly.
    SizeofType(context, type_node->type().get(), std::move(cb));
  } else {
    // Everything else gets evaluated. Strictly C++ won't do this because it's statically typed, but
    // our expression system is not. This doesn't need to follow references because we only need the
    // type and the
    expr_->Eval(context, [context, cb = std::move(cb)](ErrOrValue value) mutable {
      if (value.has_error())
        return cb(value);
      SizeofType(context, value.value().type(), std::move(cb));
    });
  }
}

void SizeofExprNode::Print(std::ostream& out, int indent) const {
  out << IndentFor(indent) << "SIZEOF\n";
  expr_->Print(out, indent + 1);
}

// static
void SizeofExprNode::SizeofType(const fxl::RefPtr<EvalContext>& context, const Type* in_type,
                                EvalCallback cb) {
  // References should get stripped (sizeof(char&) = 1).
  if (!in_type)
    return cb(Err("Can't do sizeof on a null type."));

  fxl::RefPtr<Type> type = context->GetConcreteType(in_type);
  if (type->is_declaration())
    return cb(Err("Can't resolve forward declaration for '%s'.", in_type->GetFullName().c_str()));

  if (DwarfTagIsEitherReference(type->tag()))
    type = RefPtrTo(type->AsModifiedType()->modified().Get()->AsType());
  if (!type)
    return cb(Err("Symbol error for '%s'.", in_type->GetFullName().c_str()));

  cb(ExprValue(type->byte_size()));
}

void TypeExprNode::Eval(const fxl::RefPtr<EvalContext>& context, EvalCallback cb) const {
  // Doesn't make sense to evaluate a type, callers like casts that expect a type name will look
  // into the node themselves.
  cb(Err("Can not evaluate a type name."));
}

void TypeExprNode::Print(std::ostream& out, int indent) const {
  out << IndentFor(indent) << "TYPE(";
  if (type_)
    out << type_->GetFullName();
  out << ")\n";
}

void UnaryOpExprNode::Eval(const fxl::RefPtr<EvalContext>& context, EvalCallback cb) const {
  expr_->EvalFollowReferences(context,
                              [context, cb = std::move(cb), op = op_](ErrOrValue value) mutable {
                                if (value.has_error())
                                  cb(value);
                                else
                                  EvalUnaryOperator(context, op, value.value(), std::move(cb));
                              });
}

void UnaryOpExprNode::Print(std::ostream& out, int indent) const {
  out << IndentFor(indent) << "UNARY(" << op_.value() << ")\n";
  expr_->Print(out, indent + 1);
}

}  // namespace zxdb
