// 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 <lib/syslog/cpp/macros.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"

// 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.
    FX_DCHECK(info.bits % 8 == 0);
    FX_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.
  FX_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:                                                            \
      FX_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:                                                          \
      FX_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:                                                             \
      FX_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
