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

#include <type_traits>

#include "src/developer/debug/zxdb/common/err.h"
#include "src/developer/debug/zxdb/expr/bitfield.h"
#include "src/developer/debug/zxdb/expr/cast.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_token.h"
#include "src/developer/debug/zxdb/expr/expr_value.h"
#include "src/developer/debug/zxdb/expr/resolve_ptr_ref.h"
#include "src/developer/debug/zxdb/symbols/base_type.h"
#include "src/developer/debug/zxdb/symbols/modified_type.h"
#include "src/developer/debug/zxdb/symbols/symbol_data_provider.h"
#include "src/lib/fxl/logging.h"

// About math handling
// -------------------
//
// C++ applies "integer promotion" to doing arithmetic operations. This is a set of rules for
// promoting the parameters to larger types. See:
//   https://en.cppreference.com/w/cpp/language/operator_arithmetic#Conversions
//
// When evaluating expressions in a debugger, the user expects more calculator-like behavior and
// cares less about specific types and truncation rules. As an example, in C++ multiplying two
// integers will yield an integer type that may overflow. But in a debugger expression truncating
// an overflowing value is extremely undesirable.
//
// As a result we upcast all integer operations to 64-bit. This is in contrast to C++ which often
// prefers "int" which are often 32 bits.
//
// We still more-or-less follow the signed/unsigned rules since sometimes those behaviors are
// important to the result being computed. Effectively, this means using the larger of the two types
// if the type sizes differ, and converting to unsigned if the sizes but sign-edness of the types
// differ.

namespace zxdb {

namespace {

using debug_ipc::RegisterCategory;
using debug_ipc::RegisterID;
using debug_ipc::RegisterInfo;

// Backend for register assignment that takes the known current value of the destination register
// as well as the new value (possibly in a subrange) and updates the value. This is updated
// according to the used bits and shift amount.
void AssignRegisterWithExistingValue(const fxl::RefPtr<EvalContext>& context,
                                     const ExprValueSource& dest,
                                     std::vector<uint8_t> existing_data, const RegisterInfo& info,
                                     const ExprValue& source,
                                     SymbolDataProvider::WriteCallback cb) {
  // Here we want to support vector registers so can't always bring the result into a numeric
  // variable. These large values are always multiples of bytes (not random bit ranges within
  // bytes). Sometimes bitfields with arbitrary ranges can be brought into registers, but this will
  // always be normal smaller ones that can be used with numbers.
  //
  // These computations assume little-endian.
  if (dest.bit_shift() % 8 == 0 && dest.bit_size() % 8 == 0) {
    // Easy case of everything being byte-aligned. This can handle all vector registers.

    // We expect all non-canonical registers to be byte-aligned inside their canonical one.
    FXL_DCHECK(info.bits % 8 == 0);
    FXL_DCHECK(info.shift % 8 == 0);

    // In little-endian, the byte shift (from the low bit) just measures from the [0] byte.
    //
    // Do these computations in signed numbers because weird symbol data could give
    // data.size() - offset => negative number.
    int byte_shift = static_cast<int>((dest.bit_shift() + info.shift) / 8);
    int byte_length = std::min(static_cast<int>(dest.bit_size()), info.bits) / 8;

    // Clamp the range to within the buffer in case anything is corrupted.
    byte_length = std::min(byte_length, std::max(0, static_cast<int>(existing_data.size()) -
                                                        byte_shift - byte_length));

    if (byte_length > 0) {
      memcpy(&existing_data[byte_shift], &source.data()[0], byte_length);
      context->GetDataProvider()->WriteRegister(info.canonical_id, std::move(existing_data),
                                                std::move(cb));
    } else {
      // Nothing to write, the symbol shifts seem messed up.
      cb(Err("Could not write register data of %d bytes at offset %d bytes.", byte_length,
             byte_shift));
    }
  } else if (existing_data.size() < sizeof(uint128_t) && source.data().size() < sizeof(uint128_t)) {
    // Have non-byte-sized shifts, the source is probably a bitfield. This assumes little-endian.
    uint128_t existing_value = 0;
    memcpy(&existing_value, &existing_data[0], existing_data.size());

    uint128_t write_value = 0;
    memcpy(&write_value, &source.data()[0], source.data().size());

    // This ExprValueSource takes into account any non-canonical register shifts on top of what
    // may already be there.
    ExprValueSource new_dest(info.canonical_id,
                             std::max(dest.bit_size(), static_cast<uint32_t>(info.bits)),
                             dest.bit_shift() + info.shift);

    uint128_t new_value = new_dest.SetBits(existing_value, write_value);
    memcpy(&existing_data[0], &new_value, existing_data.size());

    context->GetDataProvider()->WriteRegister(info.canonical_id, std::move(existing_data),
                                              std::move(cb));
  } else {
    cb(Err("Can't write bitfield of size %zu to register of size %zu.", source.data().size(),
           existing_data.size()));
  }
}

void DoRegisterAssignment(const fxl::RefPtr<EvalContext>& context, const ExprValueSource& dest,
                          const ExprValue& source, EvalCallback cb) {
  const RegisterInfo* info = debug_ipc::InfoForRegister(dest.register_id());
  if (!info)
    return cb(Err("Assignment to invalid register %u.", dest.register_id()));

  // Transforms a register write callback (Err only) to a EvalCallback (ErrOr<ExprValue>).
  SymbolDataProvider::WriteCallback write_cb = [source,
                                                cb = std::move(cb)](const Err& err) mutable {
    if (err.has_error())
      cb(err);
    else
      cb(source);
  };

  if (info->canonical_id == dest.register_id() && !dest.is_bitfield()) {
    // Normal register write with no masking or shifting.
    context->GetDataProvider()->WriteRegister(dest.register_id(), source.data(),
                                              std::move(write_cb));
  } else {
    // This write requires some masking and shifting, and therefore needs the current register
    // value.
    context->GetDataProvider()->GetRegisterAsync(
        info->canonical_id, [context, source, dest, info = *info, write_cb = std::move(write_cb)](
                                const Err& err, std::vector<uint8_t> data) mutable {
          if (err.has_error()) {
            write_cb(err);
          } else {
            AssignRegisterWithExistingValue(context, dest, std::move(data), info, source,
                                            std::move(write_cb));
          }
        });
  }
}

void DoMemoryAssignment(const fxl::RefPtr<EvalContext>& context, const ExprValueSource& dest,
                        const ExprValue& source, EvalCallback cb) {
  // Update the memory with the new data. The result of the expression is the coerced value.
  auto write_callback = [source, cb = std::move(cb)](const Err& err) mutable {
    if (err.has_error())
      cb(err);
    else
      cb(source);
  };
  if (dest.is_bitfield()) {
    WriteBitfieldToMemory(context, dest, source.data(), std::move(write_callback));
  } else {
    // Normal case for non-bitfields.
    context->GetDataProvider()->WriteMemory(dest.address(), source.data(),
                                            std::move(write_callback));
  }
}

void DoAssignment(const fxl::RefPtr<EvalContext>& context, const ExprValue& left_value,
                  const ExprValue& right_value, EvalCallback cb) {
  if (left_value.data().size() == 0)
    return cb(Err("Can't assign 0-size value."));

  // Note: the calling code will have evaluated the value of the left node. Often this isn't
  // strictly necessary: we only need the "source", but optimizing in that way would complicate
  // things.
  const ExprValueSource& dest = left_value.source();
  if (dest.type() == ExprValueSource::Type::kTemporary)
    return cb(Err("Can't assign to a temporary."));
  if (dest.type() == ExprValueSource::Type::kConstant)
    return cb(Err("Can't assign to a constant."));
  if (dest.type() == ExprValueSource::Type::kComposite) {
    // TODO(bug 39630) implement composite variable locations.
    return cb(Err("Can't assign to a composite variable location (see bug 39630)."));
  }

  // The coerced value will be the result. It should have the "source" of the left-hand-side since
  // the location being assigned to doesn't change.
  CastExprValue(context, CastType::kImplicit, right_value, left_value.type_ref(), ExprValueSource(),
                [context, dest, cb = std::move(cb)](ErrOrValue coerced) mutable {
                  if (coerced.has_error())
                    return cb(coerced);

                  if (dest.type() == ExprValueSource::Type::kRegister) {
                    DoRegisterAssignment(context, dest, coerced.value(), std::move(cb));
                  } else {
                    DoMemoryAssignment(context, dest, coerced.value(), std::move(cb));
                  }
                });
}

// This is used as the return type for comparison operations.
fxl::RefPtr<BaseType> MakeBoolType() {
  return fxl::MakeRefCounted<BaseType>(BaseType::kBaseTypeBoolean, 1, "bool");
}

// The "math realm" is the type of operation being done, since operators in these different spaces
// have very different behaviors.
enum class MathRealm { kSigned, kUnsigned, kFloat, kPointer };

bool IsIntegerRealm(MathRealm realm) {
  return realm == MathRealm::kSigned || realm == MathRealm::kUnsigned;
}

// Computes how math should be done on the given type. The type should be concrete.
Err GetRealm(const Type* type, MathRealm* realm) {
  // Check for pointers.
  if (const ModifiedType* mod = type->AsModifiedType()) {
    if (mod->tag() == DwarfTag::kPointerType) {
      *realm = MathRealm::kPointer;
      return Err();
    }
  } else if (const BaseType* base = type->AsBaseType()) {
    // Everything else should be a base type.
    switch (base->base_type()) {
      case BaseType::kBaseTypeNone:
        break;  // Error, fall through to bottom of function.

      case BaseType::kBaseTypeAddress:
        *realm = MathRealm::kPointer;
        return Err();

      case BaseType::kBaseTypeFloat:
        *realm = MathRealm::kFloat;
        return Err();
    }

    if (BaseType::IsSigned(base->base_type()))
      *realm = MathRealm::kSigned;
    else
      *realm = MathRealm::kUnsigned;
    return Err();
  }

  return Err("Invalid non-numeric type '%s' for operator.", type->GetFullName().c_str());
}

// Collects the computed information for one parameter for passing around more conveniently.
struct OpValue {
  const ExprValue* value = nullptr;
  fxl::RefPtr<Type> concrete_type;  // Extracted from value.type().
  MathRealm realm = MathRealm::kUnsigned;
};

Err FillOpValue(EvalContext* context, const ExprValue& in, OpValue* out) {
  out->value = &in;

  out->concrete_type = context->GetConcreteType(in.type());
  if (!out->concrete_type)
    return Err("No type information");
  if (out->concrete_type->byte_size() == 0 || in.data().empty())
    return Err("Empty type size for operator.");

  return GetRealm(out->concrete_type.get(), &out->realm);
}

// Given a binary operation of the two parameters, computes the realm that the operation should be
// done in, and computes which of the types is larger. This larger type does not take into account
// integral promotion described at the top of this file, it will always be one of the two inputs.
Err GetOpRealm(const fxl::RefPtr<EvalContext>& context, const OpValue& left, const OpValue& right,
               MathRealm* op_realm, fxl::RefPtr<Type>* larger_type) {
  // Pointer always takes precedence.
  if (left.realm == MathRealm::kPointer) {
    *op_realm = left.realm;
    *larger_type = left.concrete_type;
    return Err();
  }
  if (right.realm == MathRealm::kPointer) {
    *op_realm = right.realm;
    *larger_type = right.concrete_type;
    return Err();
  }

  // Floating-point is next.
  if (left.realm == MathRealm::kFloat && right.realm == MathRealm::kFloat) {
    // Both float: pick the biggest one (defaulting to the left on a tie).
    *op_realm = MathRealm::kFloat;
    if (right.concrete_type->byte_size() > left.concrete_type->byte_size())
      *larger_type = right.concrete_type;
    else
      *larger_type = left.concrete_type;
    return Err();
  }
  if (left.realm == MathRealm::kFloat) {
    *op_realm = MathRealm::kFloat;
    *larger_type = left.concrete_type;
    return Err();
  }
  if (right.realm == MathRealm::kFloat) {
    *op_realm = MathRealm::kFloat;
    *larger_type = right.concrete_type;
    return Err();
  }

  // Integer math. Pick the larger one if the sizes are different.
  if (left.concrete_type->byte_size() > right.concrete_type->byte_size()) {
    *op_realm = left.realm;
    *larger_type = left.concrete_type;
    return Err();
  }
  if (right.concrete_type->byte_size() > left.concrete_type->byte_size()) {
    *op_realm = right.realm;
    *larger_type = right.concrete_type;
    return Err();
  }

  // Same size and both are integers, pick the unsigned one if they disagree.
  if (left.realm != right.realm) {
    if (left.realm == MathRealm::kUnsigned) {
      *op_realm = left.realm;
      *larger_type = left.concrete_type;
    } else {
      *op_realm = right.realm;
      *larger_type = right.concrete_type;
    }
    return Err();
  }

  // Pick the left one if everything else agrees.
  *op_realm = left.realm;
  *larger_type = left.concrete_type;
  return Err();
}

// Applies the given operator to two integers. The type T can be either uint64_t for unsigned, or
// int64_t for signed operation.
//
// The flag "check_for_zero_right" will issue a divide-by-zero error if the right-hand-side is zero.
// Error checking could be generalized more in the "op" callback, but this is currently the only
// error case and it keeps all of the op implementations simpler to do it this way.
template <typename T, typename ResultT>
ErrOrValue DoIntBinaryOp(const OpValue& left, const OpValue& right, bool check_for_zero_right,
                         ResultT (*op)(T, T), fxl::RefPtr<Type> result_type) {
  T left_val;
  if (Err err = left.value->PromoteTo64(&left_val); err.has_error())
    return err;

  T right_val;
  if (Err err = right.value->PromoteTo64(&right_val); err.has_error())
    return err;
  if (check_for_zero_right) {
    if (right_val == 0)
      return Err("Division by 0.");
  }

  ResultT result_val = op(left_val, right_val);

  // Never expect to generate larger output than our internal result.
  FXL_DCHECK(result_type->byte_size() <= sizeof(ResultT));

  // Convert to a base type of the correct size.
  std::vector<uint8_t> result_data;
  result_data.resize(result_type->byte_size());
  memcpy(&result_data[0], &result_val, result_type->byte_size());

  return ExprValue(std::move(result_type), std::move(result_data));
}

// Converts the given value to a double if possible when
Err OpValueToDouble(const fxl::RefPtr<EvalContext>& context, const OpValue& in, double* out) {
  if (in.realm == MathRealm::kFloat)
    return in.value->PromoteToDouble(out);  // Already floating-point.

  // Needs casting to a float.
  auto double_type = fxl::MakeRefCounted<BaseType>(BaseType::kBaseTypeFloat, 8, "double");
  ErrOrValue casted = CastNumericExprValue(context, *in.value, std::move(double_type));
  if (casted.has_error())
    return casted.err();

  return casted.value().PromoteToDouble(out);
}

// Applies the given operator to two values that should be done in floating-point. The templated
// result type should be either a double (for math) or bool (for comparison). In the boolean case,
// the result_typee may be null since this will be the autmoatically created one.
template <typename ResultT>
ErrOrValue DoFloatBinaryOp(const fxl::RefPtr<EvalContext>& context, const OpValue& left,
                           const OpValue& right, ResultT (*op)(double, double),
                           fxl::RefPtr<Type> result_type) {
  // The inputs could be various types like signed or unsigned integers or even bools. Use the
  // casting infrastructure to convert these when necessary.
  double left_double = 0.0;
  if (Err err = OpValueToDouble(context, left, &left_double); err.has_error())
    return err;
  double right_double = 0.0;
  if (Err err = OpValueToDouble(context, right, &right_double); err.has_error())
    return err;

  // The actual operation.
  ResultT result_val = op(left_double, right_double);

  // Convert to raw bytes.
  std::vector<uint8_t> result_data;
  if (std::is_same<ResultT, bool>::value)  // Result wants a boolean.
    return ExprValue(result_val);
  if (result_type->byte_size() == sizeof(double))  // Result wants a double.
    return ExprValue(result_val, std::move(result_type));
  if (result_type->byte_size() == sizeof(float))  // Convert down to 32-bit float.
    return ExprValue(static_cast<float>(result_val), std::move(result_type));

  // No other floating-point sizes are supported.
  return Err("Invalid floating point operation.");
}

// Returns a language-appropriate 64-bit signed or unsigned (according to the realm) type. The
// language is taken from the given language reference type.
fxl::RefPtr<Type> Make64BitIntegerType(MathRealm realm, fxl::RefPtr<Type> lang_reference) {
  bool is_rust = lang_reference->GetLanguage() == DwarfLang::kRust;

  if (realm == MathRealm::kSigned) {
    if (is_rust)
      return fxl::MakeRefCounted<BaseType>(BaseType::kBaseTypeSigned, 8, "i64");
    return fxl::MakeRefCounted<BaseType>(BaseType::kBaseTypeSigned, 8, "int64_t");
  } else if (realm == MathRealm::kUnsigned) {
    if (is_rust)
      return fxl::MakeRefCounted<BaseType>(BaseType::kBaseTypeUnsigned, 8, "u64");
    return fxl::MakeRefCounted<BaseType>(BaseType::kBaseTypeUnsigned, 8, "uint64_t");
  }
  return fxl::RefPtr<Type>();
}

// Computes a possibly-new larger type for the given math realm. This is so we can avoid overflow
// when using expressions in "calculator" mode regardless of the input type.
fxl::RefPtr<Type> ExpandTypeTo64(MathRealm realm, fxl::RefPtr<Type> input) {
  if (input->byte_size() >= 8)
    return input;  // 64-bit input is large enough, don't mess with it.

  // Smaller ints get a synthesized type.
  if (realm == MathRealm::kSigned || realm == MathRealm::kUnsigned)
    return Make64BitIntegerType(realm, input);

  // No change necessary. Don't change floats or pointers.
  return input;
}

// Returns the byte size of the type pointed to by the given type. If anything fails or if the size
// is 0, returns an error.
Err GetPointedToByteSize(const fxl::RefPtr<EvalContext>& context, const Type* type,
                         uint32_t* size) {
  *size = 0;

  fxl::RefPtr<Type> pointed_to;
  if (Err err = GetPointedToType(context, type, &pointed_to); err.has_error())
    return err;

  // Need to make concrete to get the size.
  pointed_to = context->GetConcreteType(pointed_to.get());
  *size = pointed_to->byte_size();
  if (*size == 0)
    return Err("Can't do pointer arithmetic on a type of size 0.");
  return Err();
}

ErrOrValue DoPointerOperation(const fxl::RefPtr<EvalContext>& context, const OpValue& left_value,
                              const ExprToken& op, const OpValue& right_value) {
  // Adding or subtracting a pointer and an integer or and integer to a pointer advances the pointer
  // by the size of the pointed-to type.
  const OpValue* int_value = nullptr;
  const OpValue* ptr_value = nullptr;
  if (left_value.realm == MathRealm::kPointer && IsIntegerRealm(right_value.realm)) {
    // pointer <op> int: Addition and subtraction are supported.
    if (op.type() != ExprTokenType::kMinus && op.type() != ExprTokenType::kPlus)
      return Err("Unsupported operator '%s' for pointer.", op.value().c_str());

    ptr_value = &left_value;
    int_value = &right_value;
  } else if (IsIntegerRealm(left_value.realm) && right_value.realm == MathRealm::kPointer) {
    // int <op> pointer: Only addition is supported.
    if (op.type() != ExprTokenType::kPlus)
      return Err("Unsupported operator '%s' for pointer.", op.value().c_str());

    int_value = &left_value;
    ptr_value = &right_value;
  }
  if (int_value && ptr_value) {
    uint32_t pointed_to_size = 0;
    if (Err err = GetPointedToByteSize(context, ptr_value->concrete_type.get(), &pointed_to_size);
        err.has_error())
      return err;

    uint64_t ptr_number = 0;
    if (Err err = ptr_value->value->PromoteTo64(&ptr_number); err.has_error())
      return err;

    int64_t int_number = 0;
    if (Err err = int_value->value->PromoteTo64(&int_number); err.has_error())
      return err;

    uint64_t result_number;
    if (op.type() == ExprTokenType::kMinus) {
      // For minus everything was checked above so we know this is <pointer> - <number>.
      result_number = ptr_number - pointed_to_size * int_number;
    } else {
      // Everything else should be addition.
      result_number = ptr_number + pointed_to_size * int_number;
    }

    // Convert to the result. Use the type from the pointer on the value to keep things like C-V
    // qualifiers from the original.
    return ExprValue(result_number, ptr_value->value->type_ref());
  }

  // The only other pointer operation to support is subtraction.
  if (op.type() != ExprTokenType::kMinus)
    return Err("Unsupported operator '%s' for pointer.", op.value().c_str());

  // For subtraction, both pointers need to be the same type.
  if (left_value.concrete_type->GetFullName() != right_value.concrete_type->GetFullName()) {
    return Err("Can't subtract pointers of different types '%s' and '%s'.",
               left_value.concrete_type->GetFullName().c_str(),
               right_value.concrete_type->GetFullName().c_str());
  }

  // Validate the pointed-to type sizes.
  uint32_t left_pointed_to_size = 0;
  if (Err err =
          GetPointedToByteSize(context, left_value.concrete_type.get(), &left_pointed_to_size);
      err.has_error())
    return err;
  uint32_t right_pointed_to_size = 0;
  if (Err err =
          GetPointedToByteSize(context, right_value.concrete_type.get(), &right_pointed_to_size);
      err.has_error())
    return err;
  if (left_pointed_to_size != right_pointed_to_size) {
    return Err("Can't subtract pointers of different sizes %" PRIu32 " and %" PRIu32 ".",
               left_pointed_to_size, right_pointed_to_size);
  }

  // Do the operation in signed so that subtraction makes sense (ptrdiff_t is signed).
  int64_t left_number = 0;
  if (Err err = left_value.value->PromoteTo64(&left_number); err.has_error())
    return err;
  int64_t right_number = 0;
  if (Err err = right_value.value->PromoteTo64(&right_number); err.has_error())
    return err;

  return ExprValue(static_cast<uint64_t>((left_number - right_number) / left_pointed_to_size),
                   Make64BitIntegerType(MathRealm::kSigned, left_value.concrete_type));
}

ErrOrValue DoLogicalBinaryOp(const fxl::RefPtr<EvalContext>& context, const OpValue& left_value,
                             const ExprToken& op, const OpValue& right_value) {
  // In general the left will have already been converted to a bool and checks to implement
  // short-ciruiting for these operators. But reevaluate anyway which is useful for tests.
  ErrOrValue left_as_bool = CastNumericExprValue(context, *left_value.value, MakeBoolType());
  if (left_as_bool.has_error())
    return left_as_bool;

  ErrOrValue right_as_bool = CastNumericExprValue(context, *right_value.value, MakeBoolType());
  if (right_as_bool.has_error())
    return right_as_bool;

  if (op.type() == ExprTokenType::kDoubleAnd) {
    return ExprValue(left_as_bool.value().GetAs<uint8_t>() &&
                     right_as_bool.value().GetAs<uint8_t>());
  }
  if (op.type() == ExprTokenType::kLogicalOr) {
    return ExprValue(left_as_bool.value().GetAs<uint8_t>() ||
                     right_as_bool.value().GetAs<uint8_t>());
  }
  return Err("Internal error.");
}

}  // namespace

void EvalBinaryOperator(const fxl::RefPtr<EvalContext>& context, const ExprValue& left_value,
                        const ExprToken& op, const ExprValue& right_value, EvalCallback cb) {
  if (!left_value.type() || !right_value.type())
    return cb(Err("No type information."));

  // Handle assignement specially.
  if (op.type() == ExprTokenType::kEquals)
    return DoAssignment(std::move(context), left_value, right_value, std::move(cb));

  // Left info.
  OpValue left_op_value;
  if (Err err = FillOpValue(context.get(), left_value, &left_op_value); err.has_error())
    return cb(err);

  // Right info.
  OpValue right_op_value;
  if (Err err = FillOpValue(context.get(), right_value, &right_op_value); err.has_error())
    return cb(err);

  // Operation info.
  MathRealm realm;
  fxl::RefPtr<Type> larger_type;
  if (Err err = GetOpRealm(context, left_op_value, right_op_value, &realm, &larger_type);
      err.has_error())
    return cb(err);

  // Special-case pointer operations since they work differently.
  if (realm == MathRealm::kPointer)
    return cb(DoPointerOperation(context, left_op_value, op, right_op_value));

  // Implements the type expansion described at the top of this file.
  larger_type = ExpandTypeTo64(realm, larger_type);

// Implements support for a given operator that only works for integer types.
#define IMPLEMENT_INTEGER_BINARY_OP(c_op, is_divide)                                     \
  switch (realm) {                                                                       \
    case MathRealm::kSigned:                                                             \
      result = DoIntBinaryOp<int64_t, int64_t>(                                          \
          left_op_value, right_op_value, is_divide,                                      \
          [](int64_t left, int64_t right) { return left c_op right; }, larger_type);     \
      break;                                                                             \
    case MathRealm::kUnsigned:                                                           \
      result = DoIntBinaryOp<uint64_t, uint64_t>(                                        \
          left_op_value, right_op_value, is_divide,                                      \
          [](uint64_t left, uint64_t right) { return left c_op right; }, larger_type);   \
      break;                                                                             \
    case MathRealm::kFloat:                                                              \
      result = Err("Operator '%s' not defined for floating point.", op.value().c_str()); \
      break;                                                                             \
    case MathRealm::kPointer:                                                            \
      FXL_NOTREACHED();                                                                  \
      break;                                                                             \
  }

// Implements support for a given operator that only works for integer or floating point types.
// Pointers should have been handled specially above.
#define IMPLEMENT_BINARY_OP(c_op, is_divide)                                           \
  switch (realm) {                                                                     \
    case MathRealm::kSigned:                                                           \
      result = DoIntBinaryOp<int64_t, int64_t>(                                        \
          left_op_value, right_op_value, is_divide,                                    \
          [](int64_t left, int64_t right) { return left c_op right; }, larger_type);   \
      break;                                                                           \
    case MathRealm::kUnsigned:                                                         \
      result = DoIntBinaryOp<uint64_t, uint64_t>(                                      \
          left_op_value, right_op_value, is_divide,                                    \
          [](uint64_t left, uint64_t right) { return left c_op right; }, larger_type); \
      break;                                                                           \
    case MathRealm::kFloat:                                                            \
      result = DoFloatBinaryOp<double>(                                                \
          context, left_op_value, right_op_value,                                      \
          [](double left, double right) { return left c_op right; }, larger_type);     \
      break;                                                                           \
    case MathRealm::kPointer:                                                          \
      FXL_NOTREACHED();                                                                \
      break;                                                                           \
  }

// Implements support for a given comparison operator.
#define IMPLEMENT_COMPARISON_BINARY_OP(c_op)                                              \
  switch (realm) {                                                                        \
    case MathRealm::kSigned:                                                              \
      result = DoIntBinaryOp<int64_t, bool>(                                              \
          left_op_value, right_op_value, false,                                           \
          [](int64_t left, int64_t right) { return left c_op right; }, MakeBoolType());   \
      break;                                                                              \
    case MathRealm::kUnsigned:                                                            \
      result = DoIntBinaryOp<uint64_t, bool>(                                             \
          left_op_value, right_op_value, false,                                           \
          [](uint64_t left, uint64_t right) { return left c_op right; }, MakeBoolType()); \
      break;                                                                              \
    case MathRealm::kFloat:                                                               \
      result = DoFloatBinaryOp<bool>(                                                     \
          context, left_op_value, right_op_value,                                         \
          [](double left, double right) { return left c_op right; }, nullptr);            \
      break;                                                                              \
    case MathRealm::kPointer:                                                             \
      FXL_NOTREACHED();                                                                   \
      break;                                                                              \
  }

  ErrOrValue result((ExprValue()));
  switch (op.type()) {
    case ExprTokenType::kPlus:
      IMPLEMENT_BINARY_OP(+, false);
      break;
    case ExprTokenType::kMinus:
      IMPLEMENT_BINARY_OP(-, false);
      break;
    case ExprTokenType::kSlash:
      IMPLEMENT_BINARY_OP(/, true);
      break;
    case ExprTokenType::kStar:
      IMPLEMENT_BINARY_OP(*, false);
      break;
    case ExprTokenType::kPercent:
      IMPLEMENT_INTEGER_BINARY_OP(%, true);
      break;
    case ExprTokenType::kAmpersand:
      IMPLEMENT_INTEGER_BINARY_OP(&, false);
      break;
    case ExprTokenType::kBitwiseOr:
      IMPLEMENT_INTEGER_BINARY_OP(|, false);
      break;
    case ExprTokenType::kCaret:
      IMPLEMENT_INTEGER_BINARY_OP(^, false);
      break;
    case ExprTokenType::kShiftLeft:
      IMPLEMENT_INTEGER_BINARY_OP(<<, false);
      break;
    case ExprTokenType::kShiftRight:
      IMPLEMENT_INTEGER_BINARY_OP(>>, false);
      break;

    case ExprTokenType::kEquality:
      IMPLEMENT_COMPARISON_BINARY_OP(==);
      break;
    case ExprTokenType::kInequality:
      IMPLEMENT_COMPARISON_BINARY_OP(!=);
      break;
    case ExprTokenType::kLessEqual:
      IMPLEMENT_COMPARISON_BINARY_OP(<=);
      break;
    case ExprTokenType::kGreaterEqual:
      IMPLEMENT_COMPARISON_BINARY_OP(>=);
      break;
    case ExprTokenType::kLess:
      IMPLEMENT_COMPARISON_BINARY_OP(<);
      break;
    case ExprTokenType::kGreater:
      IMPLEMENT_COMPARISON_BINARY_OP(>);
      break;

    case ExprTokenType::kSpaceship:
      // The three-way comparison isn't useful in a debugger, and isn't really implementable anyway
      // because it returns some kind of special std constant that we would rather not count on.
      result = Err("Sorry, no UFOs allowed here.");
      break;

    case ExprTokenType::kDoubleAnd:
    case ExprTokenType::kLogicalOr:
      result = DoLogicalBinaryOp(context, left_op_value, op, right_op_value);
      break;

    default:
      result = Err("Unsupported binary operator '%s', sorry!", op.value().c_str());
      break;
  }

  cb(std::move(result));
}

void EvalBinaryOperator(const fxl::RefPtr<EvalContext>& context, const fxl::RefPtr<ExprNode>& left,
                        const ExprToken& op, const fxl::RefPtr<ExprNode>& right, EvalCallback cb) {
  left->Eval(context, [context, op, right, cb = std::move(cb)](ErrOrValue left_value) mutable {
    if (left_value.has_error())
      return cb(left_value);

    if (op.type() == ExprTokenType::kLogicalOr || op.type() == ExprTokenType::kDoubleAnd) {
      // Short-circuit for || and &&.
      ErrOrValue left_as_bool = CastNumericExprValue(context, left_value.value(), MakeBoolType());
      if (left_as_bool.has_error())
        return cb(left_as_bool.err());

      if (left_as_bool.value().GetAs<uint8_t>()) {
        if (op.type() == ExprTokenType::kLogicalOr)
          return cb(left_as_bool);  // Computation complete, skip evaluating the right side.

        // Fall through to evaluating the right side given the left already casted to a bool.
        left_value = left_as_bool.value();
      } else {
        if (op.type() == ExprTokenType::kDoubleAnd)
          return cb(left_as_bool);  // Computation complete, skip evaluating the right side.

        // Fall through to evaluating the right side given the left already casted to a bool.
        left_value = left_as_bool.value();
      }
    }

    right->Eval(context, [context, left_value = left_value.take_value(), op,
                          cb = std::move(cb)](ErrOrValue right_value) mutable {
      if (right_value.has_error())
        cb(right_value);
      else
        EvalBinaryOperator(std::move(context), left_value, op, right_value.value(), std::move(cb));
    });
  });
}

void EvalUnaryOperator(const fxl::RefPtr<EvalContext>& context, const ExprToken& op_token,
                       const ExprValue& value, EvalCallback cb) {
  if (!value.type())
    return cb(Err("No type information."));

  OpValue op_value;
  if (Err err = FillOpValue(context.get(), value, &op_value); err.has_error())
    return cb(err);

    // Implements a unary operator that applies C rules for the 4 different sized types. The types
    // are passed in so that this can work with both signed and unsigned input.
    //
    // C has a bunch of rules (see "integer promotion" at the top of this file).
    //
    // This logic implicitly takes advantage of the C rules but the type names produced will be the
    // sized C++ stdint.h types rather than what C would use (int/unsigned, etc.) or whatever the
    // current language would produce (e.g. u32 on Rust). Since these are temporaries, the type
    // names usually aren't very important so the simplicity of this approach is preferrable.
#define IMPLEMENT_UNARY_INTEGER_OP(c_op, type8, type16, type32, type64)                    \
  switch (value.data().size()) {                                                           \
    case sizeof(type8):                                                                    \
      result = ExprValue(c_op value.GetAs<type8>());                                       \
      break;                                                                               \
    case sizeof(type16):                                                                   \
      result = ExprValue(c_op value.GetAs<type16>());                                      \
      break;                                                                               \
    case sizeof(type32):                                                                   \
      result = ExprValue(c_op value.GetAs<type32>());                                      \
      break;                                                                               \
    case sizeof(type64):                                                                   \
      result = ExprValue(c_op value.GetAs<type64>());                                      \
      break;                                                                               \
    default:                                                                               \
      result = Err("Unsupported size for unary operator '%s'.", op_token.value().c_str()); \
      break;                                                                               \
  }

  ErrOrValue result((ExprValue()));
  switch (op_token.type()) {
    // -
    case ExprTokenType::kMinus:
      switch (op_value.realm) {
        case MathRealm::kSigned:
          IMPLEMENT_UNARY_INTEGER_OP(-, int8_t, int16_t, int32_t, int64_t);
          break;
        case MathRealm::kUnsigned:
          IMPLEMENT_UNARY_INTEGER_OP(-, uint8_t, uint16_t, uint32_t, uint64_t);
          break;
        default:
          result =
              Err("Invalid type '%s' for unary operator '-'.", value.type()->GetFullName().c_str());
          break;
      }
      break;

    // !
    case ExprTokenType::kBang:
      switch (op_value.realm) {
        case MathRealm::kSigned:
          IMPLEMENT_UNARY_INTEGER_OP(!, int8_t, int16_t, int32_t, int64_t);
          break;
        case MathRealm::kPointer:  // ! can treat a pointer like an unsigned int.
        case MathRealm::kUnsigned:
          IMPLEMENT_UNARY_INTEGER_OP(!, uint8_t, uint16_t, uint32_t, uint64_t);
          break;
        case MathRealm::kFloat:
          switch (value.data().size()) {
            case sizeof(float):
              result = ExprValue(!value.GetAs<float>());
              break;
            case sizeof(double):
              result = ExprValue(!value.GetAs<double>());
              break;
          }
          break;
      }
      break;

    default:
      result = Err("Invalid unary operator '%s'.", op_token.value().c_str());
      break;
  }
  cb(result);
}

}  // namespace zxdb
