void write_method_functions()

in src/tool/python/code_writers.h [902:1071]


    void write_method_functions(writer& w, TypeDef const& type)
    {
        // create a map of methods to determine overloads + ensure all overloads match instance/static 
        std::map<std::string_view, bool> method_map{};
        enumerate_methods(w, type, [&](auto const& method)
        {
            XLANG_ASSERT(contains(method_map, method.Name()) ? method_map[method.Name()] == is_static(method) : true);
            method_map[method.Name()] = is_static(method);
        });

        for (auto&&[method_name, method_is_static] : method_map)
        {
            w.write("\nstatic PyObject* @_%(%, PyObject* args) noexcept\n{\n",
                type.TypeName(),
                method_name,
                bind<write_method_self_param>(type, method_is_static));
            {
                writer::indent_guard g{ w };

                if (is_ptype(type))
                {
                    w.write("return self->obj->%(args);\n", method_name);
                }
                else
                {
                    write_method_overloads(w, type, method_name);
                }
            }
            w.write("}\n");
        }

        enumerate_properties(w, type, [&](auto const& prop)
        {
            auto&&[get_method, put_method] = get_property_methods(prop);
            write_get_property_function(w, type, get_method);
            write_put_property_function(w, type, put_method);
        });

        enumerate_events(w, type, [&](auto const& evt)
        {
            auto&&[add_method, remove_method] = get_event_methods(evt);
            write_event_function(w, type, add_method);
            write_event_function(w, type, remove_method);
        });

        if (!(is_ptype(type) || is_static_class(type)))
        {
            w.write("\nstatic PyObject* _from_@(PyObject* /*unused*/, PyObject* arg) noexcept\n{\n", type.TypeName());
            {
                writer::indent_guard g{ w };
                write_try_catch(w, [&](writer& w)
                {
                    auto format = "auto return_value = py::convert_to<winrt::Windows::Foundation::IInspectable>(arg);\nreturn py::convert(return_value.as<%>());\n";
                    w.write(format, type);
                });
            }
            w.write("}\n");
        }

        if (implements_iclosable(type))
        {
            w.write(strings::enter_function, type.TypeName(), bind<write_pywrapper_type>(type));

            w.write("\nstatic PyObject* _exit_@(%* self) noexcept\n{\n", type.TypeName(), bind<write_pywrapper_type>(type));
            {
                writer::indent_guard g{ w };
                write_try_catch(w, [](auto& w) { w.write("self->obj.Close();\nPy_RETURN_FALSE;\n"); });
            }
            w.write("}\n");
        }

        if (implements_istringable(type))
        {
            w.write("\nstatic PyObject* _str_@(%* self) noexcept\n{\n", type.TypeName(), bind<write_pywrapper_type>(type));
            {
                writer::indent_guard g{ w };
                write_try_catch(w, [](auto& w) { w.write("return py::convert(self->obj.ToString());\n"); });
            }
            w.write("}\n");
        }

        auto write_ptype_body = [&](std::string_view ptype_func_call, std::function<void(writer&)> ctype_func)
        {
            writer::indent_guard g{ w };

            if (is_ptype(type))
            {
                w.write("return self->obj->%;\n", ptype_func_call);
            }
            else
            {
                ctype_func(w);
            }
        };

        if (implements_iasync(type))
        {
            w.write("\nstatic PyObject* _await_@(%* self) noexcept\n{\n", type.TypeName(), bind<write_pywrapper_type>(type));
            {
                write_ptype_body("dunder_await()", [&](auto& w) { w.write("return py::dunder_await(self->obj);\n"); });
            }
            w.write("}\n");
        }

        if (implements_iiterable(type) || implements_iiterator(type))
        {
            w.write("\nstatic PyObject* _iterator_@(%* self) noexcept\n{\n", type.TypeName(), bind<write_pywrapper_type>(type));
            {
                write_ptype_body("dunder_iter()", [&](auto& w) { write_dunder_iter_body(w, type); });
            }
            w.write("}\n");
        }

        if (implements_iiterator(type))
        {
            w.write("\nstatic PyObject* _iterator_next_@(%* self) noexcept\n{\n", type.TypeName(), bind<write_pywrapper_type>(type));
            {
                write_ptype_body("dunder_iternext()", [&](auto& w) { write_dunder_iter_next_body(w, type); });
            }
            w.write("}\n");
        }

        if (implements_sequence(type))
        {
            w.write("\nstatic Py_ssize_t _seq_length_@(%* self) noexcept\n{\n", type.TypeName(), bind<write_pywrapper_type>(type));
            {
                write_ptype_body("seq_length()", [&](auto& w) { write_seq_length_body(w, type); });
            }
            w.write("}\n");

            w.write("\nstatic PyObject* _seq_item_@(%* self, Py_ssize_t i) noexcept\n{\n", type.TypeName(), bind<write_pywrapper_type>(type));
            {
                write_ptype_body("seq_item(i)", [&](auto& w) { write_seq_item_body(w, type); });
            }
            w.write("}\n");

            if (implements_ivector(type))
            {
                w.write("\nstatic int _seq_assign_@(%* self, Py_ssize_t i, PyObject* value) noexcept\n{\n", type.TypeName(), bind<write_pywrapper_type>(type));
                {
                    write_ptype_body("seq_assign(i, value)", [&](auto& w) { write_seq_assign_body(w, type); });
                }
                w.write("}\n");
            }
        }

        if (implements_mapping(type))
        {
            w.write("\nstatic Py_ssize_t _map_length_@(%* self) noexcept\n{\n", type.TypeName(), bind<write_pywrapper_type>(type));
            {
                write_ptype_body("map_length()", [&](auto& w) { write_map_length_body(w, type); });
            }
            w.write("}\n");

            w.write("\nstatic PyObject* _map_subscript_@(%* self, PyObject* key) noexcept\n{\n", type.TypeName(), bind<write_pywrapper_type>(type));
            {
                write_ptype_body("map_subscript(key)", [&](auto& w) { write_map_subscript_body(w, type); });
            }
            w.write("}\n");

            if (implements_imap(type))
            {
                w.write("\nstatic int _map_assign_@(%* self, PyObject* key, PyObject* value) noexcept\n{\n", type.TypeName(), bind<write_pywrapper_type>(type));
                {
                    write_ptype_body("map_assign(key, value)", [&](auto& w) { write_map_assign_body(w, type); });
                }
                w.write("}\n");
            }
        }
    }