From: Stefan Behnel Date: Sat, 25 Oct 2008 11:01:31 +0000 (+0200) Subject: replacement implementation for set/frozenset in Py3, mainly by Lisandro X-Git-Tag: 0.9.9.2.beta~24 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=4148f516ef5f30884fc15f44e2014ccbb69d1b58;p=cython.git replacement implementation for set/frozenset in Py3, mainly by Lisandro --- diff --git a/Cython/Compiler/Builtin.py b/Cython/Compiler/Builtin.py index c201db88..60c2deaf 100644 --- a/Cython/Compiler/Builtin.py +++ b/Cython/Compiler/Builtin.py @@ -109,18 +109,13 @@ builtin_types_table = [ ("slice", "PySlice_Type", []), ("file", "PyFile_Type", []), + ("set", "PySet_Type", [("clear", "O", "i", "PySet_Clear"), + ("discard", "OO", "i", "PySet_Discard"), + ("add", "OO", "i", "PySet_Add"), + ("pop", "O", "O", "PySet_Pop")]), + ("frozenset", "PyFrozenSet_Type", []), ] -if 'set' in __builtin__.__dict__: - builtin_types_table += [ - ("set", "PySet_Type", [("clear", "O", "i", "PySet_Clear"), - ("discard", "OO", "i", "PySet_Discard"), - ("add", "OO", "i", "PySet_Add"), - ("pop", "O", "O", "PySet_Pop")]), - - ("frozenset", "PyFrozenSet_Type", []), - ] - builtin_structs_table = [ @@ -166,9 +161,104 @@ intern_utility_code = [""" """,""" """] +py23_set_utility_code = [""" +#if PY_VERSION_HEX < 0x02050000 +#ifndef PyAnySet_CheckExact + +#define PyAnySet_CheckExact(ob) \ + ((ob)->ob_type == ((PyTypeObject*)&PySet_Type) || \ + (ob)->ob_type == ((PyTypeObject*)&PyFrozenSet_Type)) + +#define PySet_Pop(set) PyObject_CallMethod(set, "pop", NULL) + +static INLINE int PySet_Clear(PyObject *set) { + PyObject *ret = PyObject_CallMethod(set, "clear", NULL); + if (!ret) return -1; + Py_DECREF(ret); return 0; +} + +static INLINE int PySet_Discard(PyObject *set, PyObject *key) { + PyObject *ret = PyObject_CallMethod(set, "discard", "O", key); + if (!ret) return -1; + Py_DECREF(ret); return 0; +} + +static INLINE int PySet_Add(PyObject *set, PyObject *key) { + PyObject *ret = PyObject_CallMethod(set, "add", "O", key); + if (!ret) return -1; + Py_DECREF(ret); return 0; +} + +#endif /* PyAnySet_CheckExact (<= Py2.4) */ + +#if PY_VERSION_HEX < 0x02040000 +#ifndef Py_SETOBJECT_H +#define Py_SETOBJECT_H + +static PyTypeObject *PySet_Type = NULL; +static PyTypeObject *PyFrozenSet_Type = NULL; + +#define PyAnySet_Check(ob) \ + (PyAnySet_CheckExact(ob) || \ + PyType_IsSubtype((ob)->ob_type, &PySet_Type) || \ + PyType_IsSubtype((ob)->ob_type, &PyFrozenSet_Type)) + +#define PyFrozenSet_CheckExact(ob) ((ob)->ob_type == &PyFrozenSet_Type) + +#define PySet_New(iterable) \ + PyObject_CallFunctionObjArgs((PyObject *)PySet_Type, iterable, NULL) +#define Pyx_PyFrozenSet_New(iterable) \ + PyObject_CallFunctionObjArgs((PyObject *)PyFrozenSet_Type, iterable, NULL) + +#define PySet_Size(anyset) PyObject_Size(anyset) +#define PySet_Contains(anyset, key) PySequence_Contains(anyset, key) + +/* ---------------------------------------------------------------- */ + +static int __Pyx_Py23SetsImport(void) { + PyObject *sets=0, *Set=0, *ImmutableSet=0; + + sets = PyImport_ImportModule("sets"); + if (!sets) goto bad; + Set = PyObject_GetAttrString(sets, "Set"); + if (!Set) goto bad; + ImmutableSet = PyObject_GetAttrString(sets, "ImmutableSet"); + if (!ImmutableSet) goto bad; + Py_DECREF(sets); + + PySet_Type = (PyTypeObject*) Set; + PyFrozenSet_Type = (PyTypeObject*) ImmutableSet; + + /* FIXME: this should be done in dedicated module cleanup code */ + /* + Py_DECREF(Set); + Py_DECREF(ImmutableSet); + */ + + return 0; + + bad: + Py_XDECREF(sets); + Py_XDECREF(Set); + Py_XDECREF(ImmutableSet); + return -1; +} + +/* ---------------------------------------------------------------- */ + +#else +static int py23sets_import(void) { return 0; } +#endif /* !Py_SETOBJECT_H */ +#endif /* < Py2.4 */ +#endif /* < Py2.5 */ +""",""" +"""] + builtin_utility_code = { - 'getattr3': getattr3_utility_code, - 'intern' : intern_utility_code, + 'getattr3' : getattr3_utility_code, + 'intern' : intern_utility_code, + 'set' : py23_set_utility_code, + 'frozenset' : py23_set_utility_code, } builtin_scope = BuiltinScope() @@ -185,7 +275,8 @@ def init_builtin_funcs(): def init_builtin_types(): for name, cname, funcs in builtin_types_table: - the_type = builtin_scope.declare_builtin_type(name, cname) + utility = builtin_utility_code.get(name) + the_type = builtin_scope.declare_builtin_type(name, cname, utility) for name, args, ret, cname in funcs: sig = Signature(args, ret) the_type.scope.declare_cfunction(name, sig.function_type(), None, cname) diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index c36cc3be..f094fab1 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -1567,6 +1567,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln("/*--- Initialize various global constants etc. ---*/") code.putln(code.error_goto_if_neg("__Pyx_InitGlobals()", self.pos)) + code.putln("#if PY_VERSION_HEX < 0x02040000") + code.putln(code.error_goto_if_neg("__Pyx_Py23SetsImport()", self.pos)) + code.putln("#endif") + code.putln("/*--- Module creation code ---*/") self.generate_module_creation_code(env, code) @@ -1574,7 +1578,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln("/*--- Builtin init code ---*/") code.putln(code.error_goto_if_neg("__Pyx_InitCachedBuiltins()", self.pos)) - + code.putln("%s = 0;" % Naming.skip_dispatch_cname); code.putln("/*--- Global init code ---*/") diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py index 3348e434..6700807e 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@ -706,7 +706,7 @@ class BuiltinScope(Scope): entry.as_variable = var_entry return entry - def declare_builtin_type(self, name, cname): + def declare_builtin_type(self, name, cname, utility_code = None): name = EncodedString(name) type = PyrexTypes.BuiltinObjectType(name, cname) type.set_scope(CClassScope(name, outer_scope=None, visibility='extern')) @@ -720,6 +720,7 @@ class BuiltinScope(Scope): var_entry.is_variable = 1 var_entry.is_cglobal = 1 var_entry.is_readonly = 1 + var_entry.utility_code = utility_code entry.as_variable = var_entry return type diff --git a/runtests.py b/runtests.py index 9b511e68..a954ea19 100644 --- a/runtests.py +++ b/runtests.py @@ -19,7 +19,8 @@ EXT_DEP_MODULES = { } VER_DEP_MODULES = { - (2,4) : lambda x: x in ['run.set'] +# such as: +# (2,4) : lambda x: x in ['run.set'] } INCLUDE_DIRS = [ d for d in os.getenv('INCLUDE', '').split(os.pathsep) if d ]