// 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.h"

#include <lib/syslog/cpp/macros.h>

#include "src/developer/debug/zxdb/expr/eval_context.h"
#include "src/developer/debug/zxdb/expr/expr_node.h"
#include "src/developer/debug/zxdb/expr/expr_parser.h"
#include "src/developer/debug/zxdb/expr/expr_tokenizer.h"
#include "src/developer/debug/zxdb/symbols/modified_type.h"

namespace zxdb {

namespace {

class MultiEvalTracking {
 public:
  using OutputVector = std::vector<ErrOrValue>;
  using Completion = fit::callback<void(OutputVector)>;

  MultiEvalTracking(size_t count, Completion cb) : remaining_(count), completion_(std::move(cb)) {
    data_.resize(count, ErrOrValue(ExprValue()));
  }

  void SetResult(size_t index, ErrOrValue value) {
    FX_DCHECK(index < data_.size());
    FX_DCHECK(remaining_ > 0);

    // Nothing should be set on this slot yet.
    FX_DCHECK(!data_[index].has_error());
    FX_DCHECK(data_[index].value() == ExprValue());

    data_[index] = std::move(value);

    remaining_--;
    if (remaining_ == 0)
      completion_(std::move(data_));
  }

 private:
  size_t remaining_;  // # callbacks remaining before completion.
  OutputVector data_;
  Completion completion_;
};

}  // namespace

void EvalExpression(const std::string& input, const fxl::RefPtr<EvalContext>& context,
                    bool follow_references, EvalCallback cb) {
  ExprTokenizer tokenizer(input, context->GetLanguage());
  if (!tokenizer.Tokenize())
    return cb(tokenizer.err());

  ExprParser parser(tokenizer.TakeTokens(), tokenizer.language(),
                    context->GetSymbolNameLookupCallback());
  auto node = parser.Parse();
  if (parser.err().has_error()) {
    // Add context information since we have the original input string (the
    // parser doesn't have this).
    ExprToken error_token = parser.error_token();
    if (error_token.type() != ExprTokenType::kInvalid) {
      Err context_err(parser.err().type(),
                      parser.err().msg() + "\n" +
                          ExprTokenizer::GetErrorContext(input, error_token.byte_offset()));
      cb(context_err);
    } else {
      cb(parser.err());
    }
    return;
  }

  if (follow_references)
    node->Eval(context, std::move(cb));
  else
    node->EvalFollowReferences(context, std::move(cb));
}

void EvalExpressions(const std::vector<std::string>& inputs,
                     const fxl::RefPtr<EvalContext>& context, bool follow_references,
                     fit::callback<void(std::vector<ErrOrValue>)> cb) {
  FX_DCHECK(!inputs.empty());

  auto tracking = std::make_shared<MultiEvalTracking>(inputs.size(), std::move(cb));
  for (size_t i = 0; i < inputs.size(); i++) {
    EvalExpression(inputs[i], context, follow_references,
                   [tracking, i](ErrOrValue value) { tracking->SetResult(i, std::move(value)); });
  }
}

// TODO(bug 44074) support non-pointer values and take their address implicitly.
Err ValueToAddressAndSize(const fxl::RefPtr<EvalContext>& eval_context, const ExprValue& value,
                          uint64_t* address, std::optional<uint32_t>* size) {
  fxl::RefPtr<Type> concrete_type = value.GetConcreteType(eval_context.get());
  if (concrete_type->AsCollection()) {
    // Don't allow structs and classes that are <= 64 bits to be converted
    // to addresses.
    return Err("Can't convert '%s' to an address.", concrete_type->GetFullName().c_str());
  }

  // See if there's an intrinsic size to the object being pointed to. This is true for pointers.
  // References should have been followed and stripped before here.
  if (auto modified = concrete_type->AsModifiedType();
      modified && modified->tag() == DwarfTag::kPointerType) {
    if (auto modified_type = modified->modified().Get()->AsType())
      *size = modified_type->byte_size();
  }

  // Convert anything else <= 64 bits to a number.
  return value.PromoteTo64(address);
}

}  // namespace zxdb
