// Copyright (c) 2013 The Chromium 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 "gn/operators.h"

#include <stddef.h>
#include <algorithm>
#include <iterator>

#include "base/strings/string_number_conversions.h"
#include "gn/err.h"
#include "gn/parse_tree.h"
#include "gn/scope.h"
#include "gn/token.h"
#include "gn/value.h"

namespace {

// Helper class used for assignment operations: =, +=, and -= to generalize
// writing to various types of destinations.
class ValueDestination {
 public:
  ValueDestination();

  bool Init(Scope* exec_scope,
            const ParseNode* dest,
            const BinaryOpNode* op_node,
            Err* err);

  // Returns the value in the destination scope if it already exists, or null
  // if it doesn't. This is for validation and does not count as a "use".
  // Other nested scopes will be searched.
  const Value* GetExistingValue() const;

  // Returns an existing version of the output if it can be modified. This will
  // not search nested scopes since writes only go into the current scope.
  // Returns null if the value does not exist, or is not in the current scope
  // (meaning assignments won't go to this value and it's not mutable). This
  // is for implementing += and -=.
  //
  // If it exists, this will mark the origin of the value to be the passed-in
  // node, and the value will be also marked unused (if possible) under the
  // assumption that it will be modified in-place.
  Value* GetExistingMutableValueIfExists(const ParseNode* origin);

  // Returns a pointer to the value that was set.
  Value* SetValue(Value value, const ParseNode* set_node);

  // Fills the Err with an undefined value error appropriate for modification
  // operators: += and -= (where the source is also the dest).
  void MakeUndefinedIdentifierForModifyError(Err* err);

 private:
  enum Type { UNINITIALIZED, SCOPE, LIST };

  Type type_;

  // Valid when type_ == SCOPE.
  Scope* scope_;
  const Token* name_token_;

  // Valid when type_ == LIST.
  Value* list_;
  size_t index_;  // Guaranteed in-range when Init() succeeds.
};

ValueDestination::ValueDestination()
    : type_(UNINITIALIZED),
      scope_(nullptr),
      name_token_(nullptr),
      list_(nullptr),
      index_(0) {}

bool ValueDestination::Init(Scope* exec_scope,
                            const ParseNode* dest,
                            const BinaryOpNode* op_node,
                            Err* err) {
  // Check for standard variable set.
  const IdentifierNode* dest_identifier = dest->AsIdentifier();
  if (dest_identifier) {
    type_ = SCOPE;
    scope_ = exec_scope;
    name_token_ = &dest_identifier->value();
    return true;
  }

  // Check for array and scope accesses. The base (array or scope variable
  // name) must always be defined ahead of time.
  const AccessorNode* dest_accessor = dest->AsAccessor();
  if (!dest_accessor) {
    *err = Err(op_node, "Assignment requires a lvalue.",
               "This thing on the left is not an identifier or accessor.");
    err->AppendRange(dest->GetRange());
    return false;
  }

  // Known to be an accessor.
  std::string_view base_str = dest_accessor->base().value();
  Value* base =
      exec_scope->GetMutableValue(base_str, Scope::SEARCH_CURRENT, false);
  if (!base) {
    // Base is either undefined or it's defined but not in the current scope.
    // Make a good error message.
    if (exec_scope->GetValue(base_str, false)) {
      *err = Err(
          dest_accessor->base(), "Suspicious in-place modification.",
          "This variable exists in a containing scope. Normally, writing to it "
          "would\nmake a copy of it into the current scope with the modified "
          "version. But\nhere you're modifying only an element of a scope or "
          "list object. It's unlikely\nyou meant to copy the entire thing just "
          "to modify this part of it.\n"
          "\n"
          "If you really wanted to do this, do:\n"
          "  " +
              std::string(base_str) + " = " + std::string(base_str) +
              "\n"
              "to copy it into the current scope before doing this operation.");
    } else {
      *err = Err(dest_accessor->base(), "Undefined identifier.");
    }
    return false;
  }

  if (dest_accessor->subscript()) {
    // List access with an index.
    if (!base->VerifyTypeIs(Value::LIST, err)) {
      // Errors here will confusingly refer to the variable declaration (since
      // that's all Value knows) rather than the list access. So rewrite the
      // error location to refer to the base value's location.
      *err = Err(dest_accessor->base(), err->message(), err->help_text());
      return false;
    }

    type_ = LIST;
    list_ = base;
    return dest_accessor->ComputeAndValidateListIndex(
        exec_scope, base->list_value().size(), &index_, err);
  }

  // Scope access with a dot.
  if (!base->VerifyTypeIs(Value::SCOPE, err)) {
    // As the for the list index case above, rewrite the error location.
    *err = Err(dest_accessor->base(), err->message(), err->help_text());
    return false;
  }
  type_ = SCOPE;
  scope_ = base->scope_value();
  name_token_ = &dest_accessor->member()->value();
  return true;
}

const Value* ValueDestination::GetExistingValue() const {
  if (type_ == SCOPE)
    return scope_->GetValue(name_token_->value(), true);
  else if (type_ == LIST)
    return &list_->list_value()[index_];
  return nullptr;
}

Value* ValueDestination::GetExistingMutableValueIfExists(
    const ParseNode* origin) {
  if (type_ == SCOPE) {
    Value* value = scope_->GetMutableValue(name_token_->value(),
                                           Scope::SEARCH_CURRENT, false);
    if (value) {
      // The value will be written to, reset its tracking information.
      value->set_origin(origin);
      scope_->MarkUnused(name_token_->value());
    }
  }
  if (type_ == LIST)
    return &list_->list_value()[index_];
  return nullptr;
}

Value* ValueDestination::SetValue(Value value, const ParseNode* set_node) {
  if (type_ == SCOPE) {
    return scope_->SetValue(name_token_->value(), std::move(value), set_node);
  } else if (type_ == LIST) {
    Value* dest = &list_->list_value()[index_];
    *dest = std::move(value);
    return dest;
  }
  return nullptr;
}

void ValueDestination::MakeUndefinedIdentifierForModifyError(Err* err) {
  // When Init() succeeds, the base of any accessor has already been resolved
  // and that list indices are in-range. This means any undefined identifiers
  // are for scope accesses.
  DCHECK(type_ == SCOPE);
  *err = Err(*name_token_, "Undefined identifier.");
}

// Computes an error message for overwriting a nonempty list/scope with another.
Err MakeOverwriteError(const BinaryOpNode* op_node, const Value& old_value) {
  std::string type_name;
  std::string empty_def;

  if (old_value.type() == Value::LIST) {
    type_name = "list";
    empty_def = "[]";
  } else if (old_value.type() == Value::SCOPE) {
    type_name = "scope";
    empty_def = "{}";
  } else {
    NOTREACHED();
  }

  Err result(op_node->left()->GetRange(),
             "Replacing nonempty " + type_name + ".",
             "This overwrites a previously-defined nonempty " + type_name +
                 " with another nonempty " + type_name + ".");
  result.AppendSubErr(Err(
      old_value, "for previous definition",
      "Did you mean to append/modify instead? If you really want to overwrite, "
      "do:\n"
      "  foo = " +
          empty_def + "\nbefore reassigning."));
  return result;
}

// -----------------------------------------------------------------------------

Err MakeIncompatibleTypeError(const BinaryOpNode* op_node,
                              const Value& left,
                              const Value& right) {
  std::string msg = std::string("You can't do <") +
                    Value::DescribeType(left.type()) + "> " +
                    std::string(op_node->op().value()) + " <" +
                    Value::DescribeType(right.type()) + ">.";
  if (left.type() == Value::LIST) {
    // Append extra hint for list stuff.
    msg +=
        "\n\nHint: If you're attempting to add or remove a single item from "
        " a list, use \"foo + [ bar ]\".";
  }
  return Err(op_node, "Incompatible types for binary operator.", msg);
}

Value GetValueOrFillError(const BinaryOpNode* op_node,
                          const ParseNode* node,
                          const char* name,
                          Scope* scope,
                          Err* err) {
  Value value = node->Execute(scope, err);
  if (err->has_error())
    return Value();
  if (value.type() == Value::NONE) {
    *err = Err(op_node->op(), "Operator requires a value.",
               "This thing on the " + std::string(name) +
                   " does not evaluate to a value.");
    err->AppendRange(node->GetRange());
    return Value();
  }
  return value;
}

void RemoveMatchesFromList(const BinaryOpNode* op_node,
                           Value* list,
                           const Value& to_remove,
                           Err* err) {
  std::vector<Value>& v = list->list_value();
  switch (to_remove.type()) {
    case Value::BOOLEAN:
    case Value::INTEGER:  // Filter out the individual int/string.
    case Value::STRING:
    case Value::SCOPE: {
      bool found_match = false;
      for (size_t i = 0; i < v.size(); /* nothing */) {
        if (v[i] == to_remove) {
          found_match = true;
          v.erase(v.begin() + i);
        } else {
          i++;
        }
      }
      if (!found_match) {
        *err = Err(to_remove.origin()->GetRange(), "Item not found",
                   "You were trying to remove " + to_remove.ToString(true) +
                       "\nfrom the list but it wasn't there.");
      }
      break;
    }

    case Value::LIST:  // Filter out each individual thing.
      for (const auto& elem : to_remove.list_value()) {
        // TODO(brettw) if the nested item is a list, we may want to search
        // for the literal list rather than remote the items in it.
        RemoveMatchesFromList(op_node, list, elem, err);
        if (err->has_error())
          return;
      }
      break;

    case Value::NONE:
      break;
  }
}

// Assignment -----------------------------------------------------------------

// We return a null value from this rather than the result of doing the append.
// See ValuePlusEquals for rationale.
Value ExecuteEquals(Scope* exec_scope,
                    const BinaryOpNode* op_node,
                    ValueDestination* dest,
                    Value right,
                    Err* err) {
  const Value* old_value = dest->GetExistingValue();
  if (old_value) {
    // Check for overwriting nonempty scopes or lists with other nonempty
    // scopes or lists. This prevents mistakes that clobber a value rather than
    // appending to it. For cases where a user meant to clear a value, allow
    // overwriting a nonempty list/scope with an empty one, which can then be
    // modified.
    if (old_value->type() == Value::LIST && right.type() == Value::LIST &&
        !old_value->list_value().empty() && !right.list_value().empty()) {
      *err = MakeOverwriteError(op_node, *old_value);
      return Value();
    } else if (old_value->type() == Value::SCOPE &&
               right.type() == Value::SCOPE &&
               old_value->scope_value()->HasValues(Scope::SEARCH_CURRENT) &&
               right.scope_value()->HasValues(Scope::SEARCH_CURRENT)) {
      *err = MakeOverwriteError(op_node, *old_value);
      return Value();
    }
  }

  dest->SetValue(std::move(right), op_node->right());
  return Value();
}

// Plus/minus ------------------------------------------------------------------

// allow_left_type_conversion indicates if we're allowed to change the type of
// the left value. This is set to true when doing +, and false when doing +=.
Value ExecutePlus(const BinaryOpNode* op_node,
                  Value left,
                  Value right,
                  bool allow_left_type_conversion,
                  Err* err) {
  // Left-hand-side integer.
  if (left.type() == Value::INTEGER) {
    if (right.type() == Value::INTEGER) {
      // Int + int -> addition.
      return Value(op_node, left.int_value() + right.int_value());
    } else if (right.type() == Value::STRING && allow_left_type_conversion) {
      // Int + string -> string concat.
      return Value(op_node, base::Int64ToString(left.int_value()) +
                                right.string_value());
    }
    *err = MakeIncompatibleTypeError(op_node, left, right);
    return Value();
  }

  // Left-hand-side string.
  if (left.type() == Value::STRING) {
    if (right.type() == Value::INTEGER) {
      // String + int -> string concat.
      return Value(op_node, left.string_value() +
                                base::Int64ToString(right.int_value()));
    } else if (right.type() == Value::STRING) {
      // String + string -> string concat. Since the left is passed by copy
      // we can avoid realloc if there is enough buffer by appending to left
      // and assigning.
      left.string_value().append(right.string_value());
      return left;  // FIXME(brettw) des this copy?
    }
    *err = MakeIncompatibleTypeError(op_node, left, right);
    return Value();
  }

  // Left-hand-side list. The only valid thing is to add another list.
  if (left.type() == Value::LIST && right.type() == Value::LIST) {
    // Since left was passed by copy, avoid realloc by destructively appending
    // to it and using that as the result.
    auto& right_list = right.list_value();
    left.list_value().insert(left.list_value().end(),
                             std::make_move_iterator(right_list.begin()),
                             std::make_move_iterator(right_list.end()));
    return left;
  }

  *err = MakeIncompatibleTypeError(op_node, left, right);
  return Value();
}

// Left is passed by value because it will be modified in-place and returned
// for the list case.
Value ExecuteMinus(const BinaryOpNode* op_node,
                   Value left,
                   const Value& right,
                   Err* err) {
  // Left-hand-side int. The only thing to do is subtract another int.
  if (left.type() == Value::INTEGER && right.type() == Value::INTEGER) {
    // Int - int -> subtraction.
    return Value(op_node, left.int_value() - right.int_value());
  }

  // Left-hand-side list. The only thing to do is subtract another list.
  if (left.type() == Value::LIST && right.type() == Value::LIST) {
    // In-place modify left and return it.
    RemoveMatchesFromList(op_node, &left, right, err);
    return left;
  }

  *err = MakeIncompatibleTypeError(op_node, left, right);
  return Value();
}

// In-place plus/minus ---------------------------------------------------------

void ExecutePlusEquals(Scope* exec_scope,
                       const BinaryOpNode* op_node,
                       ValueDestination* dest,
                       Value right,
                       Err* err) {
  // There are several cases. Some things we can convert "foo += bar" to
  // "foo = foo + bar". Some cases we can't (the 'sources' variable won't
  // get the right filtering on the list). Some cases we don't want to (lists
  // and strings will get unnecessary copying so we can to optimize these).
  //
  //  - Value is already mutable in the current scope:
  //     1. List/string append: use it.
  //     2. Other types: fall back to "foo = foo + bar"
  //
  //  - Value is not mutable in the current scope:
  //     3. List/string append: copy into current scope and append to that.
  //     4. Other types: fall back to "foo = foo + bar"
  //
  // The common case is to use += for list and string appends in the local
  // scope, so this is written to avoid multiple variable lookups in that case.
  Value* mutable_dest = dest->GetExistingMutableValueIfExists(op_node);
  if (!mutable_dest) {
    const Value* existing_value = dest->GetExistingValue();
    if (!existing_value) {
      // Undefined left-hand-size for +=.
      dest->MakeUndefinedIdentifierForModifyError(err);
      return;
    }

    if (existing_value->type() != Value::STRING &&
        existing_value->type() != Value::LIST) {
      // Case #4 above.
      dest->SetValue(
          ExecutePlus(op_node, *existing_value, std::move(right), false, err),
          op_node);
      return;
    }

    // Case #3 above, copy to current scope and fall-through to appending.
    mutable_dest = dest->SetValue(*existing_value, op_node);
  } else if (mutable_dest->type() != Value::STRING &&
             mutable_dest->type() != Value::LIST) {
    // Case #2 above.
    dest->SetValue(
        ExecutePlus(op_node, *mutable_dest, std::move(right), false, err),
        op_node);
    return;
  }  // "else" is case #1 above.

  if (mutable_dest->type() == Value::STRING) {
    if (right.type() == Value::INTEGER) {
      // String + int -> string concat.
      mutable_dest->string_value().append(
          base::Int64ToString(right.int_value()));
    } else if (right.type() == Value::STRING) {
      // String + string -> string concat.
      mutable_dest->string_value().append(right.string_value());
    } else {
      *err = MakeIncompatibleTypeError(op_node, *mutable_dest, right);
    }
  } else if (mutable_dest->type() == Value::LIST) {
    // List concat.
    if (right.type() == Value::LIST) {
      // Normal list concat. This is a destructive move.
      for (Value& value : right.list_value())
        mutable_dest->list_value().push_back(std::move(value));
    } else {
      *err = Err(op_node->op(), "Incompatible types to add.",
                 "To append a single item to a list do \"foo += [ bar ]\".");
    }
  }
}

void ExecuteMinusEquals(const BinaryOpNode* op_node,
                        ValueDestination* dest,
                        const Value& right,
                        Err* err) {
  // Like the += case, we can convert "foo -= bar" to "foo = foo - bar". Since
  // there is no sources filtering, this is always semantically valid. The
  // only case we don't do it is for lists in the current scope which is the
  // most common case, and also the one that can be optimized the most by
  // doing it in-place.
  Value* mutable_dest = dest->GetExistingMutableValueIfExists(op_node);
  if (!mutable_dest ||
      (mutable_dest->type() != Value::LIST || right.type() != Value::LIST)) {
    const Value* existing_value = dest->GetExistingValue();
    if (!existing_value) {
      // Undefined left-hand-size for -=.
      dest->MakeUndefinedIdentifierForModifyError(err);
      return;
    }
    dest->SetValue(ExecuteMinus(op_node, *existing_value, right, err), op_node);
    return;
  }

  // In-place removal of items from "right".
  RemoveMatchesFromList(op_node, mutable_dest, right, err);
}

// Comparison -----------------------------------------------------------------

Value ExecuteEqualsEquals(Scope* scope,
                          const BinaryOpNode* op_node,
                          const Value& left,
                          const Value& right,
                          Err* err) {
  if (left == right)
    return Value(op_node, true);
  return Value(op_node, false);
}

Value ExecuteNotEquals(Scope* scope,
                       const BinaryOpNode* op_node,
                       const Value& left,
                       const Value& right,
                       Err* err) {
  // Evaluate in terms of ==.
  Value result = ExecuteEqualsEquals(scope, op_node, left, right, err);
  result.boolean_value() = !result.boolean_value();
  return result;
}

Value FillNeedsTwoIntegersError(const BinaryOpNode* op_node,
                                const Value& left,
                                const Value& right,
                                Err* err) {
  *err = Err(op_node, "Comparison requires two integers.",
             "This operator can only compare two integers.");
  err->AppendRange(left.origin()->GetRange());
  err->AppendRange(right.origin()->GetRange());
  return Value();
}

Value ExecuteLessEquals(Scope* scope,
                        const BinaryOpNode* op_node,
                        const Value& left,
                        const Value& right,
                        Err* err) {
  if (left.type() != Value::INTEGER || right.type() != Value::INTEGER)
    return FillNeedsTwoIntegersError(op_node, left, right, err);
  return Value(op_node, left.int_value() <= right.int_value());
}

Value ExecuteGreaterEquals(Scope* scope,
                           const BinaryOpNode* op_node,
                           const Value& left,
                           const Value& right,
                           Err* err) {
  if (left.type() != Value::INTEGER || right.type() != Value::INTEGER)
    return FillNeedsTwoIntegersError(op_node, left, right, err);
  return Value(op_node, left.int_value() >= right.int_value());
}

Value ExecuteGreater(Scope* scope,
                     const BinaryOpNode* op_node,
                     const Value& left,
                     const Value& right,
                     Err* err) {
  if (left.type() != Value::INTEGER || right.type() != Value::INTEGER)
    return FillNeedsTwoIntegersError(op_node, left, right, err);
  return Value(op_node, left.int_value() > right.int_value());
}

Value ExecuteLess(Scope* scope,
                  const BinaryOpNode* op_node,
                  const Value& left,
                  const Value& right,
                  Err* err) {
  if (left.type() != Value::INTEGER || right.type() != Value::INTEGER)
    return FillNeedsTwoIntegersError(op_node, left, right, err);
  return Value(op_node, left.int_value() < right.int_value());
}

// Binary ----------------------------------------------------------------------

Value ExecuteOr(Scope* scope,
                const BinaryOpNode* op_node,
                const ParseNode* left_node,
                const ParseNode* right_node,
                Err* err) {
  Value left = GetValueOrFillError(op_node, left_node, "left", scope, err);
  if (err->has_error())
    return Value();
  if (left.type() != Value::BOOLEAN) {
    *err = Err(op_node->left(), "Left side of || operator is not a boolean.",
               "Type is \"" + std::string(Value::DescribeType(left.type())) +
                   "\" instead.");
    return Value();
  }
  if (left.boolean_value())
    return Value(op_node, left.boolean_value());

  Value right = GetValueOrFillError(op_node, right_node, "right", scope, err);
  if (err->has_error())
    return Value();
  if (right.type() != Value::BOOLEAN) {
    *err = Err(op_node->right(), "Right side of || operator is not a boolean.",
               "Type is \"" + std::string(Value::DescribeType(right.type())) +
                   "\" instead.");
    return Value();
  }

  return Value(op_node, left.boolean_value() || right.boolean_value());
}

Value ExecuteAnd(Scope* scope,
                 const BinaryOpNode* op_node,
                 const ParseNode* left_node,
                 const ParseNode* right_node,
                 Err* err) {
  Value left = GetValueOrFillError(op_node, left_node, "left", scope, err);
  if (err->has_error())
    return Value();
  if (left.type() != Value::BOOLEAN) {
    *err = Err(op_node->left(), "Left side of && operator is not a boolean.",
               "Type is \"" + std::string(Value::DescribeType(left.type())) +
                   "\" instead.");
    return Value();
  }
  if (!left.boolean_value())
    return Value(op_node, left.boolean_value());

  Value right = GetValueOrFillError(op_node, right_node, "right", scope, err);
  if (err->has_error())
    return Value();
  if (right.type() != Value::BOOLEAN) {
    *err = Err(op_node->right(), "Right side of && operator is not a boolean.",
               "Type is \"" + std::string(Value::DescribeType(right.type())) +
                   "\" instead.");
    return Value();
  }
  return Value(op_node, left.boolean_value() && right.boolean_value());
}

}  // namespace

// ----------------------------------------------------------------------------

Value ExecuteUnaryOperator(Scope* scope,
                           const UnaryOpNode* op_node,
                           const Value& expr,
                           Err* err) {
  DCHECK(op_node->op().type() == Token::BANG);

  if (expr.type() != Value::BOOLEAN) {
    *err = Err(op_node, "Operand of ! operator is not a boolean.",
               "Type is \"" + std::string(Value::DescribeType(expr.type())) +
                   "\" instead.");
    return Value();
  }
  // TODO(scottmg): Why no unary minus?
  return Value(op_node, !expr.boolean_value());
}

Value ExecuteBinaryOperator(Scope* scope,
                            const BinaryOpNode* op_node,
                            const ParseNode* left,
                            const ParseNode* right,
                            Err* err) {
  const Token& op = op_node->op();

  // First handle the ones that take an lvalue.
  if (op.type() == Token::EQUAL || op.type() == Token::PLUS_EQUALS ||
      op.type() == Token::MINUS_EQUALS) {
    // Compute the left side.
    ValueDestination dest;
    if (!dest.Init(scope, left, op_node, err))
      return Value();

    // Compute the right side.
    Value right_value = right->Execute(scope, err);
    if (err->has_error())
      return Value();
    if (right_value.type() == Value::NONE) {
      *err = Err(op, "Operator requires a rvalue.",
                 "This thing on the right does not evaluate to a value.");
      err->AppendRange(right->GetRange());
      return Value();
    }

    // "foo += bar" (same for "-=") is converted to "foo = foo + bar" here, but
    // we pass the original value of "foo" by pointer to avoid a copy.
    if (op.type() == Token::EQUAL) {
      ExecuteEquals(scope, op_node, &dest, std::move(right_value), err);
    } else if (op.type() == Token::PLUS_EQUALS) {
      ExecutePlusEquals(scope, op_node, &dest, std::move(right_value), err);
    } else if (op.type() == Token::MINUS_EQUALS) {
      ExecuteMinusEquals(op_node, &dest, right_value, err);
    } else {
      NOTREACHED();
    }
    return Value();
  }

  // ||, &&. Passed the node instead of the value so that they can avoid
  // evaluating the RHS on early-out.
  if (op.type() == Token::BOOLEAN_OR)
    return ExecuteOr(scope, op_node, left, right, err);
  if (op.type() == Token::BOOLEAN_AND)
    return ExecuteAnd(scope, op_node, left, right, err);

  // Everything else works on the evaluated left and right values.
  Value left_value = GetValueOrFillError(op_node, left, "left", scope, err);
  if (err->has_error())
    return Value();
  Value right_value = GetValueOrFillError(op_node, right, "right", scope, err);
  if (err->has_error())
    return Value();

  // +, -.
  if (op.type() == Token::MINUS)
    return ExecuteMinus(op_node, std::move(left_value), right_value, err);
  if (op.type() == Token::PLUS) {
    return ExecutePlus(op_node, std::move(left_value), std::move(right_value),
                       true, err);
  }

  // Comparisons.
  if (op.type() == Token::EQUAL_EQUAL)
    return ExecuteEqualsEquals(scope, op_node, left_value, right_value, err);
  if (op.type() == Token::NOT_EQUAL)
    return ExecuteNotEquals(scope, op_node, left_value, right_value, err);
  if (op.type() == Token::GREATER_EQUAL)
    return ExecuteGreaterEquals(scope, op_node, left_value, right_value, err);
  if (op.type() == Token::LESS_EQUAL)
    return ExecuteLessEquals(scope, op_node, left_value, right_value, err);
  if (op.type() == Token::GREATER_THAN)
    return ExecuteGreater(scope, op_node, left_value, right_value, err);
  if (op.type() == Token::LESS_THAN)
    return ExecuteLess(scope, op_node, left_value, right_value, err);

  return Value();
}
