<commit_before>// Copyright 2015 The go-python Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package bind

import (
	"fmt"
	"strings"

	"golang.org/x/tools/go/types"
)

func (g *cpyGen) genStruct(cpy Struct) {
	pkgname := cpy.Package().Name()

	//fmt.Printf("obj: %#v\ntyp: %#v\n", obj, typ)
	g.decl.Printf("\n/* --- decls for struct %s.%v --- */\n", pkgname, cpy.GoName())
	g.decl.Printf("typedef void* %s;\n\n", cpy.sym.cgoname)
	g.decl.Printf("/* Python type for struct %s.%v\n", pkgname, cpy.GoName())
	g.decl.Printf(" */\ntypedef struct {\n")
	g.decl.Indent()
	g.decl.Printf("PyObject_HEAD\n")
	g.decl.Printf("%[1]s cgopy; /* unsafe.Pointer to %[2]s */\n",
		cpy.sym.cgoname,
		cpy.ID(),
	)
	g.decl.Outdent()
	g.decl.Printf("} %s;\n", cpy.sym.cpyname)
	g.decl.Printf("\n\n")

	g.impl.Printf("\n\n/* --- impl for %s.%v */\n\n", pkgname, cpy.GoName())

	g.genStructNew(cpy)
	g.genStructDealloc(cpy)
	g.genStructInit(cpy)
	g.genStructMembers(cpy)
	g.genStructMethods(cpy)

	g.genStructProtocols(cpy)

	g.impl.Printf("static PyTypeObject %sType = {\n", cpy.sym.cpyname)
	g.impl.Indent()
	g.impl.Printf("PyObject_HEAD_INIT(NULL)\n")
	g.impl.Printf("0,\t/*ob_size*/\n")
	g.impl.Printf("\"%s.%s\",\t/*tp_name*/\n", pkgname, cpy.GoName())
	g.impl.Printf("sizeof(%s),\t/*tp_basicsize*/\n", cpy.sym.cpyname)
	g.impl.Printf("0,\t/*tp_itemsize*/\n")
	g.impl.Printf("(destructor)%s_dealloc,\t/*tp_dealloc*/\n", cpy.sym.cpyname)
	g.impl.Printf("0,\t/*tp_print*/\n")
	g.impl.Printf("0,\t/*tp_getattr*/\n")
	g.impl.Printf("0,\t/*tp_setattr*/\n")
	g.impl.Printf("0,\t/*tp_compare*/\n")
	g.impl.Printf("0,\t/*tp_repr*/\n")
	g.impl.Printf("0,\t/*tp_as_number*/\n")
	g.impl.Printf("0,\t/*tp_as_sequence*/\n")
	g.impl.Printf("0,\t/*tp_as_mapping*/\n")
	g.impl.Printf("0,\t/*tp_hash */\n")
	g.impl.Printf("0,\t/*tp_call*/\n")
	g.impl.Printf("cpy_func_%s_tp_str,\t/*tp_str*/\n", cpy.sym.id)
	g.impl.Printf("0,\t/*tp_getattro*/\n")
	g.impl.Printf("0,\t/*tp_setattro*/\n")
	g.impl.Printf("0,\t/*tp_as_buffer*/\n")
	g.impl.Printf("Py_TPFLAGS_DEFAULT,\t/*tp_flags*/\n")
	g.impl.Printf("%q,\t/* tp_doc */\n", cpy.Doc())
	g.impl.Printf("0,\t/* tp_traverse */\n")
	g.impl.Printf("0,\t/* tp_clear */\n")
	g.impl.Printf("0,\t/* tp_richcompare */\n")
	g.impl.Printf("0,\t/* tp_weaklistoffset */\n")
	g.impl.Printf("0,\t/* tp_iter */\n")
	g.impl.Printf("0,\t/* tp_iternext */\n")
	g.impl.Printf("%s_methods,             /* tp_methods */\n", cpy.sym.cpyname)
	g.impl.Printf("0,\t/* tp_members */\n")
	g.impl.Printf("%s_getsets,\t/* tp_getset */\n", cpy.sym.cpyname)
	g.impl.Printf("0,\t/* tp_base */\n")
	g.impl.Printf("0,\t/* tp_dict */\n")
	g.impl.Printf("0,\t/* tp_descr_get */\n")
	g.impl.Printf("0,\t/* tp_descr_set */\n")
	g.impl.Printf("0,\t/* tp_dictoffset */\n")
	g.impl.Printf("(initproc)cpy_func_%s_init,      /* tp_init */\n", cpy.sym.id)
	g.impl.Printf("0,                         /* tp_alloc */\n")
	g.impl.Printf("cpy_func_%s_new,\t/* tp_new */\n", cpy.sym.id)
	g.impl.Outdent()
	g.impl.Printf("};\n\n")

	g.genStructConverters(cpy)
	g.genStructTypeCheck(cpy)

}

func (g *cpyGen) genStructNew(cpy Struct) {
	g.genTypeNew(cpy.sym)
}

func (g *cpyGen) genStructDealloc(cpy Struct) {
	g.genTypeDealloc(cpy.sym)
}

func (g *cpyGen) genStructInit(cpy Struct) {
	pkgname := cpy.Package().Name()

	g.decl.Printf("\n/* tp_init for %s.%v */\n", pkgname, cpy.GoName())
	g.decl.Printf(
		"static int\ncpy_func_%[1]s_init(%[2]s *self, PyObject *args, PyObject *kwds);\n",
		cpy.sym.id,
		cpy.sym.cpyname,
	)

	g.impl.Printf("\n/* tp_init */\n")
	g.impl.Printf(
		"static int\ncpy_func_%[1]s_init(%[2]s *self, PyObject *args, PyObject *kwds) {\n",
		cpy.sym.id,
		cpy.sym.cpyname,
	)
	g.impl.Indent()

	nfields := cpy.Struct().NumFields()
	kwds := make(map[string]int)
	g.impl.Printf("static char *kwlist[] = {\n")
	g.impl.Indent()
	for i := 0; i < nfields; i++ {
		field := cpy.Struct().Field(i)
		kwds[field.Name()] = i
		g.impl.Printf("%q, /* py_kwd_%03d */\n", field.Name(), i)
	}
	g.impl.Printf("NULL\n")
	g.impl.Outdent()
	g.impl.Printf("};\n")

	for i := 0; i < nfields; i++ {
		g.impl.Printf("PyObject *py_kwd_%03d = NULL;\n", i)
	}

	g.impl.Printf("Py_ssize_t nkwds = (kwds != NULL) ? PyDict_Size(kwds) : 0;\n")
	g.impl.Printf("Py_ssize_t nargs = (args != NULL) ? PySequence_Size(args) : 0;\n")
	g.impl.Printf("if ((nkwds + nargs) > %d) {\n", nfields)
	g.impl.Indent()
	g.impl.Printf("PyErr_SetString(PyExc_TypeError, ")
	g.impl.Printf("\"%s.__init__ takes at most %d argument(s)\");\n",
		cpy.GoName(),
		nfields,
	)
	g.impl.Printf("goto cpy_label_%s_init_fail;\n", cpy.sym.cpyname)
	g.impl.Outdent()
	g.impl.Printf("}\n\n")

	g.impl.Printf("if (!PyArg_ParseTupleAndKeywords(args, kwds, ")
	format := []string{"|"}
	addrs := []string{}
	for i := 0; i < nfields; i++ {
		format = append(format, "O")
		addrs = append(addrs, fmt.Sprintf("&py_kwd_%03d", i))
	}
	g.impl.Printf("%q, kwlist, %s)) {\n",
		strings.Join(format, ""),
		strings.Join(addrs, ", "),
	)
	g.impl.Indent()
	g.impl.Printf("goto cpy_label_%s_init_fail;\n", cpy.sym.cpyname)
	g.impl.Outdent()
	g.impl.Printf("}\n\n")

	for i := 0; i < nfields; i++ {
		g.impl.Printf("if (py_kwd_%03d != NULL) {\n", i)
		g.impl.Indent()
		g.impl.Printf(
			"if (cpy_func_%[1]s_setter_%[2]d(self, py_kwd_%03[3]d, NULL)) {\n",
			cpy.sym.id,
			i+1,
			i,
		)
		g.impl.Indent()
		g.impl.Printf("goto cpy_label_%s_init_fail;\n", cpy.sym.cpyname)
		g.impl.Outdent()
		g.impl.Printf("}\n\n")

		g.impl.Outdent()
		g.impl.Printf("}\n\n")
	}

	g.impl.Printf("return 0;\n")
	g.impl.Outdent()
	g.impl.Printf("\ncpy_label_%s_init_fail:\n", cpy.sym.cpyname)
	g.impl.Indent()
	for i := 0; i < nfields; i++ {
		g.impl.Printf("Py_XDECREF(py_kwd_%03d);\n", i)
	}
	g.impl.Printf("\nreturn -1;\n")
	g.impl.Outdent()
	g.impl.Printf("}\n\n")
}

func (g *cpyGen) genStructMembers(cpy Struct) {
	pkgname := cpy.Package().Name()
	typ := cpy.Struct()

	g.decl.Printf("\n/* tp_getset for %s.%v */\n", pkgname, cpy.GoName())
	for i := 0; i < typ.NumFields(); i++ {
		f := typ.Field(i)
		if !f.Exported() {<commit_msg>bind: support for empty structs<commit_after>// Copyright 2015 The go-python Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package bind

import (
	"fmt"
	"strings"

	"golang.org/x/tools/go/types"
)

func (g *cpyGen) genStruct(cpy Struct) {
	pkgname := cpy.Package().Name()

	//fmt.Printf("obj: %#v\ntyp: %#v\n", obj, typ)
	g.decl.Printf("\n/* --- decls for struct %s.%v --- */\n", pkgname, cpy.GoName())
	g.decl.Printf("typedef void* %s;\n\n", cpy.sym.cgoname)
	g.decl.Printf("/* Python type for struct %s.%v\n", pkgname, cpy.GoName())
	g.decl.Printf(" */\ntypedef struct {\n")
	g.decl.Indent()
	g.decl.Printf("PyObject_HEAD\n")
	g.decl.Printf("%[1]s cgopy; /* unsafe.Pointer to %[2]s */\n",
		cpy.sym.cgoname,
		cpy.ID(),
	)
	g.decl.Outdent()
	g.decl.Printf("} %s;\n", cpy.sym.cpyname)
	g.decl.Printf("\n\n")

	g.impl.Printf("\n\n/* --- impl for %s.%v */\n\n", pkgname, cpy.GoName())

	g.genStructNew(cpy)
	g.genStructDealloc(cpy)
	g.genStructInit(cpy)
	g.genStructMembers(cpy)
	g.genStructMethods(cpy)

	g.genStructProtocols(cpy)

	g.impl.Printf("static PyTypeObject %sType = {\n", cpy.sym.cpyname)
	g.impl.Indent()
	g.impl.Printf("PyObject_HEAD_INIT(NULL)\n")
	g.impl.Printf("0,\t/*ob_size*/\n")
	g.impl.Printf("\"%s.%s\",\t/*tp_name*/\n", pkgname, cpy.GoName())
	g.impl.Printf("sizeof(%s),\t/*tp_basicsize*/\n", cpy.sym.cpyname)
	g.impl.Printf("0,\t/*tp_itemsize*/\n")
	g.impl.Printf("(destructor)%s_dealloc,\t/*tp_dealloc*/\n", cpy.sym.cpyname)
	g.impl.Printf("0,\t/*tp_print*/\n")
	g.impl.Printf("0,\t/*tp_getattr*/\n")
	g.impl.Printf("0,\t/*tp_setattr*/\n")
	g.impl.Printf("0,\t/*tp_compare*/\n")
	g.impl.Printf("0,\t/*tp_repr*/\n")
	g.impl.Printf("0,\t/*tp_as_number*/\n")
	g.impl.Printf("0,\t/*tp_as_sequence*/\n")
	g.impl.Printf("0,\t/*tp_as_mapping*/\n")
	g.impl.Printf("0,\t/*tp_hash */\n")
	g.impl.Printf("0,\t/*tp_call*/\n")
	g.impl.Printf("cpy_func_%s_tp_str,\t/*tp_str*/\n", cpy.sym.id)
	g.impl.Printf("0,\t/*tp_getattro*/\n")
	g.impl.Printf("0,\t/*tp_setattro*/\n")
	g.impl.Printf("0,\t/*tp_as_buffer*/\n")
	g.impl.Printf("Py_TPFLAGS_DEFAULT,\t/*tp_flags*/\n")
	g.impl.Printf("%q,\t/* tp_doc */\n", cpy.Doc())
	g.impl.Printf("0,\t/* tp_traverse */\n")
	g.impl.Printf("0,\t/* tp_clear */\n")
	g.impl.Printf("0,\t/* tp_richcompare */\n")
	g.impl.Printf("0,\t/* tp_weaklistoffset */\n")
	g.impl.Printf("0,\t/* tp_iter */\n")
	g.impl.Printf("0,\t/* tp_iternext */\n")
	g.impl.Printf("%s_methods,             /* tp_methods */\n", cpy.sym.cpyname)
	g.impl.Printf("0,\t/* tp_members */\n")
	g.impl.Printf("%s_getsets,\t/* tp_getset */\n", cpy.sym.cpyname)
	g.impl.Printf("0,\t/* tp_base */\n")
	g.impl.Printf("0,\t/* tp_dict */\n")
	g.impl.Printf("0,\t/* tp_descr_get */\n")
	g.impl.Printf("0,\t/* tp_descr_set */\n")
	g.impl.Printf("0,\t/* tp_dictoffset */\n")
	g.impl.Printf("(initproc)cpy_func_%s_init,      /* tp_init */\n", cpy.sym.id)
	g.impl.Printf("0,                         /* tp_alloc */\n")
	g.impl.Printf("cpy_func_%s_new,\t/* tp_new */\n", cpy.sym.id)
	g.impl.Outdent()
	g.impl.Printf("};\n\n")

	g.genStructConverters(cpy)
	g.genStructTypeCheck(cpy)

}

func (g *cpyGen) genStructNew(cpy Struct) {
	g.genTypeNew(cpy.sym)
}

func (g *cpyGen) genStructDealloc(cpy Struct) {
	g.genTypeDealloc(cpy.sym)
}

func (g *cpyGen) genStructInit(cpy Struct) {
	pkgname := cpy.Package().Name()

	g.decl.Printf("\n/* tp_init for %s.%v */\n", pkgname, cpy.GoName())
	g.decl.Printf(
		"static int\ncpy_func_%[1]s_init(%[2]s *self, PyObject *args, PyObject *kwds);\n",
		cpy.sym.id,
		cpy.sym.cpyname,
	)

	g.impl.Printf("\n/* tp_init */\n")
	g.impl.Printf(
		"static int\ncpy_func_%[1]s_init(%[2]s *self, PyObject *args, PyObject *kwds) {\n",
		cpy.sym.id,
		cpy.sym.cpyname,
	)
	g.impl.Indent()

	nfields := cpy.Struct().NumFields()
	if nfields > 0 {
		kwds := make(map[string]int)
		g.impl.Printf("static char *kwlist[] = {\n")
		g.impl.Indent()
		for i := 0; i < nfields; i++ {
			field := cpy.Struct().Field(i)
			kwds[field.Name()] = i
			g.impl.Printf("%q, /* py_kwd_%03d */\n", field.Name(), i)
		}
		g.impl.Printf("NULL\n")
		g.impl.Outdent()
		g.impl.Printf("};\n")

		for i := 0; i < nfields; i++ {
			g.impl.Printf("PyObject *py_kwd_%03d = NULL;\n", i)
		}

		g.impl.Printf("Py_ssize_t nkwds = (kwds != NULL) ? PyDict_Size(kwds) : 0;\n")
		g.impl.Printf("Py_ssize_t nargs = (args != NULL) ? PySequence_Size(args) : 0;\n")
		g.impl.Printf("if ((nkwds + nargs) > %d) {\n", nfields)
		g.impl.Indent()
		g.impl.Printf("PyErr_SetString(PyExc_TypeError, ")
		g.impl.Printf("\"%s.__init__ takes at most %d argument(s)\");\n",
			cpy.GoName(),
			nfields,
		)
		g.impl.Printf("goto cpy_label_%s_init_fail;\n", cpy.sym.cpyname)
		g.impl.Outdent()
		g.impl.Printf("}\n\n")

		g.impl.Printf("if (!PyArg_ParseTupleAndKeywords(args, kwds, ")
		format := []string{"|"}
		addrs := []string{}
		for i := 0; i < nfields; i++ {
			format = append(format, "O")
			addrs = append(addrs, fmt.Sprintf("&py_kwd_%03d", i))
		}
		g.impl.Printf("%q, kwlist, %s)) {\n",
			strings.Join(format, ""),
			strings.Join(addrs, ", "),
		)
		g.impl.Indent()
		g.impl.Printf("goto cpy_label_%s_init_fail;\n", cpy.sym.cpyname)
		g.impl.Outdent()
		g.impl.Printf("}\n\n")

		for i := 0; i < nfields; i++ {
			g.impl.Printf("if (py_kwd_%03d != NULL) {\n", i)
			g.impl.Indent()
			g.impl.Printf(
				"if (cpy_func_%[1]s_setter_%[2]d(self, py_kwd_%03[3]d, NULL)) {\n",
				cpy.sym.id,
				i+1,
				i,
			)
			g.impl.Indent()
			g.impl.Printf("goto cpy_label_%s_init_fail;\n", cpy.sym.cpyname)
			g.impl.Outdent()
			g.impl.Printf("}\n\n")

			g.impl.Outdent()
			g.impl.Printf("}\n\n")
		}
	}
	g.impl.Printf("return 0;\n")
	g.impl.Outdent()
	g.impl.Printf("\ncpy_label_%s_init_fail:\n", cpy.sym.cpyname)
	g.impl.Indent()
	for i := 0; i < nfields; i++ {
		g.impl.Printf("Py_XDECREF(py_kwd_%03d);\n", i)
	}
	g.impl.Printf("\nreturn -1;\n")
	g.impl.Outdent()
	g.impl.Printf("}\n\n")
}

func (g *cpyGen) genStructMembers(cpy Struct) {
	pkgname := cpy.Package().Name()
	typ := cpy.Struct()

	g.decl.Printf("\n/* tp_getset for %s.%v */\n", pkgname, cpy.GoName())
	for i := 0; i < typ.NumFields(); i++ {
		f := typ.Field(i)
		if !f.Exported() {
{'fraction_non_alphanumeric': 0.24709797873203992, 'fraction_numerical': 0.010471629190681063, 'mean_word_length': 3.5646535753982955, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6679015', 'n_tokens_mistral': 5889, 'n_tokens_neox': 5865, 'n_words': 847}