// Copyright 2022 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "./invoke.h"

#include <functional>
#include <unordered_map>

#include "./hal.h"
#include "./vm.h"
#include "iree/base/api.h"
#include "iree/hal/api.h"
#include "iree/modules/hal/module.h"
#include "iree/vm/api.h"

namespace iree {
namespace python {

namespace {

class InvokeContext {
 public:
  InvokeContext(HalDevice& device) : device_(device) {}

  HalDevice& device() { return device_; }
  HalAllocator allocator() {
    // TODO: Unfortunate that we inc ref here but that is how our object model
    // is set up.
    return HalAllocator::BorrowFromRawPtr(device().allocator());
  }

 private:
  HalDevice device_;
};

using PackCallback =
    std::function<void(InvokeContext&, iree_vm_list_t*, py::handle)>;

class InvokeStatics {
 public:
  ~InvokeStatics() {
    for (auto it : py_type_to_pack_callbacks_) {
      py::handle(it.first).dec_ref();
    }
  }

  py::str kNamedTag = py::str("named");
  py::str kSlistTag = py::str("slist");
  py::str kStupleTag = py::str("stuple");
  py::str kSdictTag = py::str("sdict");

  py::int_ kZero = py::int_(0);
  py::int_ kOne = py::int_(1);
  py::int_ kTwo = py::int_(2);
  py::str kAsArray = py::str("asarray");
  py::str kMapDtypeToElementTypeAttr = py::str("map_dtype_to_element_type");
  py::str kContiguousArg = py::str("C");
  py::str kArrayProtocolAttr = py::str("__array__");
  py::str kDtypeAttr = py::str("dtype");

  // Primitive type names.
  py::str kF32 = py::str("f32");
  py::str kF64 = py::str("f64");
  py::str kI1 = py::str("i1");
  py::str kI8 = py::str("i8");
  py::str kI16 = py::str("i16");
  py::str kI32 = py::str("i32");
  py::str kI64 = py::str("i64");

  // Compound types names.
  py::str kNdarray = py::str("ndarray");

  // Attribute names.
  py::str kAttrBufferView = py::str("_buffer_view");

  // Module 'numpy'.
  py::module_& numpy_module() { return numpy_module_; }

  py::object& runtime_module() {
    if (!runtime_module_) {
      runtime_module_ = py::module_::import_("iree.runtime");
    }
    return *runtime_module_;
  }

  py::module_& array_interop_module() {
    if (!array_interop_module_) {
      array_interop_module_ =
          py::module_::import_("iree.runtime.array_interop");
    }
    return *array_interop_module_;
  }

  py::object& device_array_type() {
    if (!device_array_type_) {
      device_array_type_ = runtime_module().attr("DeviceArray");
    }
    return *device_array_type_;
  }

  py::type_object& hal_buffer_view_type() { return hal_buffer_view_type_; }

  py::object MapElementAbiTypeToDtype(py::object& element_abi_type) {
    try {
      return abi_type_to_dtype_[element_abi_type];
    } catch (std::exception&) {
      std::string msg("could not map abi type ");
      msg.append(py::cast<std::string>(py::repr(element_abi_type)));
      msg.append(" to numpy dtype");
      throw std::invalid_argument(std::move(msg));
    }
  }

  enum iree_hal_element_types_t MapDtypeToElementType(py::object dtype) {
    // TODO: Consider porting this from a py func to C++ as it can be on
    // the critical path.
    try {
      py::object element_type =
          array_interop_module().attr(kMapDtypeToElementTypeAttr)(dtype);
      if (element_type.is_none()) {
        throw std::invalid_argument("mapping not found");
      }
      return py::cast<enum iree_hal_element_types_t>(element_type);
    } catch (std::exception& e) {
      std::string msg("could not map dtype ");
      msg.append(py::cast<std::string>(py::repr(dtype)));
      msg.append(" to element type: ");
      msg.append(e.what());
      throw std::invalid_argument(std::move(msg));
    }
  }

  PackCallback AbiTypeToPackCallback(py::handle desc) {
    return AbiTypeToPackCallback(
        std::move(desc), /*desc_is_list=*/py::isinstance<py::list>(desc));
  }

  // Given an ABI desc, return a callback that can pack a corresponding py
  // value into a list. For efficiency, the caller must specify whether the
  // desc is a list (this check already needs to be done typically so
  // passed in).
  PackCallback AbiTypeToPackCallback(py::handle desc, bool desc_is_list) {
    // Switch based on descriptor type.
    if (desc_is_list) {
      // Compound type.
      py::object compound_type = desc[kZero];
      if (compound_type.equal(kNdarray)) {
        // Has format:
        //   ["ndarray", "f32", dim0, dim1, ...]
        // Extract static information about the target.
        std::vector<int64_t> abi_shape(py::len(desc) - 2);
        for (size_t i = 0, e = abi_shape.size(); i < e; ++i) {
          py::handle dim = desc[py::int_(i + 2)];
          abi_shape[i] = dim.is_none() ? -1 : py::cast<int64_t>(dim);
        }

        // Map abi element type to dtype.
        py::object abi_type = desc[kOne];
        py::object target_dtype = MapElementAbiTypeToDtype(abi_type);
        auto hal_element_type = MapDtypeToElementType(target_dtype);

        return [this, target_dtype = std::move(target_dtype), hal_element_type,
                abi_shape = std::move(abi_shape)](InvokeContext& c,
                                                  iree_vm_list_t* list,
                                                  py::handle py_value) {
          IREE_TRACE_SCOPE_NAMED("ArgumentPacker::ReflectionNdarray");
          HalBufferView* bv = nullptr;
          py::object retained_bv;
          if (is_instance_of_type_object(py_value, device_array_type())) {
            // Short-circuit: If a DeviceArray is provided, assume it is
            // correct.
            IREE_TRACE_SCOPE_NAMED("PackDeviceArray");
            bv = py::cast<HalBufferView*>(py_value.attr(kAttrBufferView));
          } else if (is_instance_of_type_object(py_value,
                                                hal_buffer_view_type())) {
            // Short-circuit: If a HalBufferView is provided directly.
            IREE_TRACE_SCOPE_NAMED("PackBufferView");
            bv = py::cast<HalBufferView*>(py_value);
          } else {
            // Fall back to the array protocol to generate a host side
            // array and then convert that.
            IREE_TRACE_SCOPE_NAMED("PackHostArray");
            py::object host_array;
            try {
              host_array = numpy_module().attr(kAsArray)(py_value, target_dtype,
                                                         kContiguousArg);
            } catch (std::exception& e) {
              std::string msg("could not convert value to numpy array: dtype=");
              msg.append(py::cast<std::string>(py::repr(target_dtype)));
              msg.append(", error='");
              msg.append(e.what());
              msg.append("', value=");
              msg.append(py::cast<std::string>(py::repr(py_value)));
              throw std::invalid_argument(std::move(msg));
            }

            retained_bv = c.allocator().AllocateBufferCopy(
                IREE_HAL_MEMORY_TYPE_DEVICE_LOCAL,
                IREE_HAL_BUFFER_USAGE_DEFAULT | IREE_HAL_BUFFER_USAGE_MAPPING,
                c.device(), host_array, hal_element_type);
            bv = py::cast<HalBufferView*>(retained_bv);
          }

          // TODO: Add some shape verification. Not strictly necessary as the VM
          // will check, but may make error reporting nicer.
          // TODO: It is theoretically possible to enqueue further conversions
          // on the device, but for now we require things to line up closely.
          // TODO: If adding further manipulation here, please make this common
          // with the generic access case.
          iree_vm_ref_t buffer_view_ref =
              iree_hal_buffer_view_retain_ref(bv->raw_ptr());
          CheckApiStatus(iree_vm_list_push_ref_move(list, &buffer_view_ref),
                         "could not push buffer view to list");
        };
      } else if (compound_type.equal(kSlistTag) ||
                 compound_type.equal(kStupleTag)) {
        // Tuple/list extraction.
        // When decoding a list or tuple, the desc object is like:
        // ['slist', [...value_type_0...], ...]
        // Where the type is either 'slist' or 'stuple'.
        std::vector<PackCallback> sub_packers(py::len(desc) - 1);
        for (size_t i = 0; i < sub_packers.size(); i++) {
          sub_packers[i] = AbiTypeToPackCallback(desc[py::int_(i + 1)]);
        }
        return [sub_packers = std::move(sub_packers)](InvokeContext& c,
                                                      iree_vm_list_t* list,
                                                      py::handle py_value) {
          if (py::len(py_value) != sub_packers.size()) {
            std::string msg("expected a sequence with ");
            msg.append(std::to_string(sub_packers.size()));
            msg.append(" values. got: ");
            msg.append(py::cast<std::string>(py::repr(py_value)));
            throw std::invalid_argument(std::move(msg));
          }
          VmVariantList item_list = VmVariantList::Create(sub_packers.size());
          for (size_t i = 0; i < sub_packers.size(); ++i) {
            py::object item_py_value;
            try {
              item_py_value = py_value[py::int_(i)];
            } catch (std::exception& e) {
              std::string msg("could not get item ");
              msg.append(std::to_string(i));
              msg.append(" from: ");
              msg.append(py::cast<std::string>(py::repr(py_value)));
              msg.append(": ");
              msg.append(e.what());
              throw std::invalid_argument(std::move(msg));
            }
            sub_packers[i](c, item_list.raw_ptr(), item_py_value);
          }

          // Push the sub list.
          iree_vm_ref_t retained =
              iree_vm_list_move_ref(item_list.steal_raw_ptr());
          iree_vm_list_push_ref_move(list, &retained);
        };
      } else if (compound_type.equal(kSdictTag)) {
        // Dict extraction.
        // The descriptor for an sdict is like:
        //   ['sdict', ['key1', value1], ...]
        std::vector<std::pair<py::object, PackCallback>> sub_packers(
            py::len(desc) - 1);
        for (size_t i = 0; i < sub_packers.size(); i++) {
          py::object sub_desc = desc[py::int_(i + 1)];
          py::object key = sub_desc[kZero];
          py::object value_desc = sub_desc[kOne];
          sub_packers[i] =
              std::make_pair(std::move(key), AbiTypeToPackCallback(value_desc));
        }
        return [sub_packers = std::move(sub_packers)](InvokeContext& c,
                                                      iree_vm_list_t* list,
                                                      py::handle py_value) {
          if (py::len(py_value) != sub_packers.size()) {
            std::string msg("expected a dict with ");
            msg.append(std::to_string(sub_packers.size()));
            msg.append(" values. got: ");
            msg.append(py::cast<std::string>(py::repr(py_value)));
            throw std::invalid_argument(std::move(msg));
          }
          VmVariantList item_list = VmVariantList::Create(sub_packers.size());
          for (size_t i = 0; i < sub_packers.size(); ++i) {
            py::object item_py_value;
            try {
              item_py_value = py_value[sub_packers[i].first];
            } catch (std::exception& e) {
              std::string msg("could not get item ");
              msg.append(py::cast<std::string>(py::repr(sub_packers[i].first)));
              msg.append(" from: ");
              msg.append(py::cast<std::string>(py::repr(py_value)));
              msg.append(": ");
              msg.append(e.what());
              throw std::invalid_argument(std::move(msg));
            }
            sub_packers[i].second(c, item_list.raw_ptr(), item_py_value);
          }

          // Push the sub list.
          iree_vm_ref_t retained =
              iree_vm_list_move_ref(item_list.steal_raw_ptr());
          iree_vm_list_push_ref_move(list, &retained);
        };
      } else {
        std::string message("Unrecognized reflection compound type: ");
        message.append(py::cast<std::string>(compound_type));
        throw std::invalid_argument(message);
      }
    } else {
      // Primitive type.
      py::str prim_type = py::cast<py::str>(desc);
      if (prim_type.equal(kF32)) {
        // f32
        return [](InvokeContext& c, iree_vm_list_t* list, py::handle py_value) {
          iree_vm_value_t vm_value =
              iree_vm_value_make_f32(py::cast<float>(py_value));
          CheckApiStatus(iree_vm_list_push_value(list, &vm_value),
                         "could not append value");
        };
      } else if (prim_type.equal(kF64)) {
        // f64
        return [](InvokeContext& c, iree_vm_list_t* list, py::handle py_value) {
          iree_vm_value_t vm_value =
              iree_vm_value_make_f64(py::cast<double>(py_value));
          CheckApiStatus(iree_vm_list_push_value(list, &vm_value),
                         "could not append value");
        };
      } else if (prim_type.equal(kI32)) {
        // i32.
        return [](InvokeContext& c, iree_vm_list_t* list, py::handle py_value) {
          iree_vm_value_t vm_value =
              iree_vm_value_make_i32(py::cast<int32_t>(py_value));
          CheckApiStatus(iree_vm_list_push_value(list, &vm_value),
                         "could not append value");
        };
      } else if (prim_type.equal(kI64)) {
        // i64.
        return [](InvokeContext& c, iree_vm_list_t* list, py::handle py_value) {
          iree_vm_value_t vm_value =
              iree_vm_value_make_i64(py::cast<int64_t>(py_value));
          CheckApiStatus(iree_vm_list_push_value(list, &vm_value),
                         "could not append value");
        };
      } else if (prim_type.equal(kI8)) {
        // i8.
        return [](InvokeContext& c, iree_vm_list_t* list, py::handle py_value) {
          iree_vm_value_t vm_value =
              iree_vm_value_make_i8(py::cast<int8_t>(py_value));
          CheckApiStatus(iree_vm_list_push_value(list, &vm_value),
                         "could not append value");
        };
      } else if (prim_type.equal(kI16)) {
        // i16.
        return [](InvokeContext& c, iree_vm_list_t* list, py::handle py_value) {
          iree_vm_value_t vm_value =
              iree_vm_value_make_i16(py::cast<int16_t>(py_value));
          CheckApiStatus(iree_vm_list_push_value(list, &vm_value),
                         "could not append value");
        };
      } else {
        std::string message("Unrecognized reflection primitive type: ");
        message.append(py::cast<std::string>(prim_type));
        throw std::invalid_argument(message);
      }
    }
  }

  PackCallback GetGenericPackCallbackFor(py::handle arg) {
    PopulatePyTypeToPackCallbacks();
    py::handle clazz = arg.type();
    auto found_it = py_type_to_pack_callbacks_.find(clazz.ptr());
    if (found_it == py_type_to_pack_callbacks_.end()) {
      // Probe to see if we have a host array.
      if (py::hasattr(arg, kArrayProtocolAttr)) {
        return GetGenericPackCallbackForNdarray();
      }
      return {};
    }

    return found_it->second;
  }

 private:
  PackCallback GetGenericPackCallbackForNdarray() {
    return [this](InvokeContext& c, iree_vm_list_t* list, py::handle py_value) {
      IREE_TRACE_SCOPE_NAMED("ArgumentPacker::GenericNdarray");
      py::object host_array;
      try {
        host_array = numpy_module().attr(kAsArray)(
            py_value, /*dtype=*/py::none(), kContiguousArg);
      } catch (std::exception& e) {
        std::string msg("could not convert value to numpy array: ");
        msg.append("error='");
        msg.append(e.what());
        msg.append("', value=");
        msg.append(py::cast<std::string>(py::repr(py_value)));
        throw std::invalid_argument(std::move(msg));
      }

      auto hal_element_type =
          MapDtypeToElementType(host_array.attr(kDtypeAttr));

      // Put it on the device.
      py::object retained_bv = c.allocator().AllocateBufferCopy(
          IREE_HAL_MEMORY_TYPE_DEVICE_LOCAL,
          IREE_HAL_BUFFER_USAGE_DEFAULT | IREE_HAL_BUFFER_USAGE_MAPPING,
          c.device(), host_array, hal_element_type);
      HalBufferView* bv = py::cast<HalBufferView*>(retained_bv);

      // TODO: If adding further manipulation here, please make this common
      // with the reflection access case.
      iree_vm_ref_t buffer_view_ref =
          iree_hal_buffer_view_retain_ref(bv->raw_ptr());
      CheckApiStatus(iree_vm_list_push_ref_move(list, &buffer_view_ref),
                     "could not append value");
    };
  }

  void PopulatePyTypeToPackCallbacks() {
    if (!py_type_to_pack_callbacks_.empty()) return;

    // We only care about int and double in the numeric hierarchy. Since Python
    // has no further refinement of these, just treat them as vm 64 bit int and
    // floats and let the VM take care of it. There isn't much else we can do.
    AddPackCallback(
        py::cast(1).type(),
        [](InvokeContext& c, iree_vm_list_t* list, py::handle py_value) {
          iree_vm_value_t vm_value =
              iree_vm_value_make_i64(py::cast<int64_t>(py_value));
          CheckApiStatus(iree_vm_list_push_value(list, &vm_value),
                         "could not append value");
        });

    AddPackCallback(
        py::cast(1.0).type(),
        [](InvokeContext& c, iree_vm_list_t* list, py::handle py_value) {
          iree_vm_value_t vm_value =
              iree_vm_value_make_f64(py::cast<double>(py_value));
          CheckApiStatus(iree_vm_list_push_value(list, &vm_value),
                         "could not append value");
        });

    // List/tuple.
    auto sequence_callback = [this](InvokeContext& c, iree_vm_list_t* list,
                                    py::handle py_value) {
      auto py_seq = py::cast<py::sequence>(py_value);
      VmVariantList item_list = VmVariantList::Create(py::len(py_seq));
      for (py::handle py_item : py_seq) {
        PackCallback sub_packer = GetGenericPackCallbackFor(py_item);
        if (!sub_packer) {
          std::string message("could not convert python value to VM: ");
          message.append(py::cast<std::string>(py::repr(py_item)));
          throw std::invalid_argument(std::move(message));
        }
        sub_packer(c, item_list.raw_ptr(), py_item);
      }
      // Push the sub list.
      iree_vm_ref_t retained = iree_vm_list_move_ref(item_list.steal_raw_ptr());
      iree_vm_list_push_ref_move(list, &retained);
    };
    AddPackCallback((py::list{}).type(), sequence_callback);
    AddPackCallback((create_empty_tuple()).type(), sequence_callback);

    // Dict.
    auto dict_callback = [this](InvokeContext& c, iree_vm_list_t* list,
                                py::handle py_value) {
      // Gets all dict items and sorts (by key).
      auto py_dict = py::cast<py::dict>(py_value);
      py::list py_keys;
      for (std::pair<py::handle, py::handle> it : py_dict) {
        py_keys.append(it.first);
      }
      py_keys.attr("sort")();

      VmVariantList item_list = VmVariantList::Create(py_keys.size());
      for (auto py_key : py_keys) {
        py::object py_item = py_dict[py_key];
        PackCallback sub_packer = GetGenericPackCallbackFor(py_item);
        if (!sub_packer) {
          std::string message("could not convert python value to VM: ");
          message.append(py::cast<std::string>(py::repr(py_item)));
          throw std::invalid_argument(std::move(message));
        }
        sub_packer(c, item_list.raw_ptr(), py_item);
      }
      // Push the sub list.
      iree_vm_ref_t retained = iree_vm_list_move_ref(item_list.steal_raw_ptr());
      iree_vm_list_push_ref_move(list, &retained);
    };
    AddPackCallback((py::dict{}).type(), dict_callback);

    // HalBufferView.
    AddPackCallback(
        py::type<HalBufferView>(),
        [](InvokeContext& c, iree_vm_list_t* list, py::handle py_value) {
          HalBufferView* bv = py::cast<HalBufferView*>(py_value);
          iree_vm_ref_t buffer_view_ref =
              iree_hal_buffer_view_retain_ref(bv->raw_ptr());
          CheckApiStatus(iree_vm_list_push_ref_move(list, &buffer_view_ref),
                         "could not append value");
        });

    // DeviceArray.
    AddPackCallback(
        device_array_type(),
        [this](InvokeContext& c, iree_vm_list_t* list, py::handle py_value) {
          HalBufferView* bv =
              py::cast<HalBufferView*>(py_value.attr(kAttrBufferView));
          iree_vm_ref_t buffer_view_ref =
              iree_hal_buffer_view_retain_ref(bv->raw_ptr());
          CheckApiStatus(iree_vm_list_push_ref_move(list, &buffer_view_ref),
                         "could not append value");
        });
  }

  void AddPackCallback(py::handle t, PackCallback pcb) {
    assert(py_type_to_pack_callbacks_.count(t.ptr()) == 0 && "duplicate types");
    t.inc_ref();
    py_type_to_pack_callbacks_.insert(std::make_pair(t.ptr(), std::move(pcb)));
  }

  py::dict BuildAbiTypeToDtype() {
    auto d = py::dict();
    d[kF32] = numpy_module().attr("float32");
    d[kF64] = numpy_module().attr("float64");
    d[kI1] = numpy_module().attr("bool_");
    d[kI8] = numpy_module().attr("int8");
    d[kI16] = numpy_module().attr("int16");
    d[kI64] = numpy_module().attr("int64");
    d[kI32] = numpy_module().attr("int32");
    return d;
  }

  // Cached modules and types. Those that involve recursive lookup within
  // our top level module, we defer. Those outside, we cache at creation.
  py::module_ numpy_module_ = py::module_::import_("numpy");
  std::optional<py::object> runtime_module_;
  std::optional<py::module_> array_interop_module_;
  std::optional<py::object> device_array_type_;
  py::type_object hal_buffer_view_type_ =
      py::cast<py::type_object>(py::type<HalBufferView>());

  // Maps Python type to a PackCallback that can generically code it.
  // This will have inc_ref() called on them when added.
  std::unordered_map<PyObject*, PackCallback> py_type_to_pack_callbacks_;

  // Dict of str (ABI dtype like 'f32') to numpy dtype.
  py::dict abi_type_to_dtype_ = BuildAbiTypeToDtype();
};

/// Object that can pack Python arguments into a VM List for a specific
/// function.
class ArgumentPacker {
 public:
  ArgumentPacker(InvokeStatics& statics, std::optional<py::list> arg_descs)
      : statics_(statics) {
    IREE_TRACE_SCOPE_NAMED("ArgumentPacker::Init");
    if (!arg_descs) {
      dynamic_dispatch_ = true;
    } else {
      // Reflection dispatch.
      for (py::handle desc : *arg_descs) {
        int arg_index = flat_arg_packers_.size();
        std::optional<std::string> kwarg_name;
        py::object retained_sub_desc;

        bool desc_is_list = py::isinstance<py::list>(desc);

        // Check if named.
        //   ["named", "kwarg_name", sub_desc]
        // If found, then we set kwarg_name and reset desc to the sub_desc.
        if (desc_is_list) {
          py::object maybe_named_field = desc[statics.kZero];
          if (maybe_named_field.equal(statics.kNamedTag)) {
            py::object name_field = desc[statics.kOne];
            retained_sub_desc = desc[statics.kTwo];
            kwarg_name = py::cast<std::string>(name_field);
            desc = retained_sub_desc;
            desc_is_list = py::isinstance<py::list>(desc);

            kwarg_to_index_[name_field] = arg_index;
          }
        }

        if (!kwarg_name) {
          pos_only_arg_count_ += 1;
        }

        flat_arg_packers_.push_back(
            statics.AbiTypeToPackCallback(desc, desc_is_list));
      }
    }
  }

  /// Packs positional/kw arguments into a suitable VmVariantList and returns
  /// it.
  VmVariantList Pack(InvokeContext& invoke_context, py::sequence pos_args,
                     py::dict kw_args) {
    // Dynamic dispatch.
    if (dynamic_dispatch_) {
      IREE_TRACE_SCOPE_NAMED("ArgumentPacker::PackDynamic");
      if (kw_args.size() != 0) {
        throw std::invalid_argument(
            "kwargs not supported for dynamic dispatch functions");
      }

      VmVariantList arg_list = VmVariantList::Create(py::len(pos_args));
      for (py::handle py_arg : pos_args) {
        PackCallback packer = statics_.GetGenericPackCallbackFor(py_arg);
        if (!packer) {
          std::string message("could not convert python value to VM: ");
          message.append(py::cast<std::string>(py::repr(py_arg)));
          throw std::invalid_argument(std::move(message));
        }
        // TODO: Better error handling by catching the exception and
        // reporting which arg has a problem.
        packer(invoke_context, arg_list.raw_ptr(), py_arg);
      }
      return arg_list;
    } else {
      IREE_TRACE_SCOPE_NAMED("ArgumentPacker::PackReflection");

      // Reflection based dispatch.
      std::vector<py::handle> py_args(flat_arg_packers_.size());

      auto pos_args_size = py::len(pos_args);
      if (pos_args_size > pos_only_arg_count_) {
        std::string message("mismatched call arity: expected ");
        message.append(std::to_string(pos_only_arg_count_));
        message.append(" got ");
        message.append(std::to_string(pos_args_size));
        throw std::invalid_argument(std::move(message));
      }

      // Positional args.
      size_t pos_index = 0;
      for (py::handle py_arg : pos_args) {
        py_args[pos_index++] = py_arg;
      }

      // Keyword args.
      for (auto it : kw_args) {
        int found_index;
        try {
          found_index = py::cast<int>(kwarg_to_index_[it.first]);
        } catch (std::exception&) {
          std::string message("specified kwarg '");
          message.append(py::cast<std::string>(it.first));
          message.append("' is unknown");
          throw std::invalid_argument(std::move(message));
        }
        if (py_args[found_index]) {
          std::string message(
              "mismatched call arity: duplicate keyword argument '");
          message.append(py::cast<std::string>(it.first));
          message.append("'");
          throw std::invalid_argument(std::move(message));
        }
        py_args[found_index] = it.second;
      }

      // Now check to see that all args are set.
      for (size_t i = 0; i < py_args.size(); ++i) {
        if (!py_args[i]) {
          std::string message(
              "mismatched call arity: expected a value for argument ");
          message.append(std::to_string(i));
          throw std::invalid_argument(std::move(message));
        }
      }

      // Start packing into the list.
      VmVariantList arg_list = VmVariantList::Create(flat_arg_packers_.size());
      for (size_t i = 0; i < py_args.size(); ++i) {
        // TODO: Better error handling by catching the exception and
        // reporting which arg has a problem.
        flat_arg_packers_[i](invoke_context, arg_list.raw_ptr(), py_args[i]);
      }
      return arg_list;
    }
  }

 private:
  InvokeStatics& statics_;

  int pos_only_arg_count_ = 0;

  // Dictionary of py::str -> py::int_ mapping kwarg names to position in
  // the argument list. We store this as a py::dict because it is optimized
  // for py::str lookup.
  py::dict kwarg_to_index_;

  std::vector<PackCallback> flat_arg_packers_;

  // If true, then there is no dispatch metadata and we process fully
  // dynamically.
  bool dynamic_dispatch_ = false;
};

}  // namespace

void SetupInvokeBindings(nanobind::module_& m) {
  py::class_<InvokeStatics>(m, "_InvokeStatics");
  py::class_<InvokeContext>(m, "InvokeContext").def(py::init<HalDevice&>());
  py::class_<ArgumentPacker>(m, "ArgumentPacker")
      .def(py::init<InvokeStatics&, std::optional<py::list>>(),
           py::arg("statics"), py::arg("arg_descs") = py::none())
      .def("pack", &ArgumentPacker::Pack);

  m.attr("_invoke_statics") = py::cast(InvokeStatics());
}

}  // namespace python
}  // namespace iree
