replacement implementation for set/frozenset in Py3, mainly by Lisandro
[cython.git] / Cython / Compiler / Builtin.py
1 #
2 #   Pyrex - Builtin Definitions
3 #
4
5 from Symtab import BuiltinScope, StructOrUnionScope
6 from TypeSlots import Signature
7 import PyrexTypes
8 import __builtin__
9
10 builtin_function_table = [
11     # name,        args,   return,  C API func,           py equiv = "*"
12     ('abs',        "O",    "O",     "PyNumber_Absolute"),
13     #('chr',       "",     "",      ""),
14     #('cmp', "",   "",     "",      ""), # int PyObject_Cmp(PyObject *o1, PyObject *o2, int *result)
15     #('compile',   "",     "",      ""), # PyObject* Py_CompileString(  char *str, char *filename, int start)
16     ('delattr',    "OO",   "r",     "PyObject_DelAttr"),
17     ('dir',        "O",    "O",     "PyObject_Dir"),
18     ('divmod',     "OO",   "O",     "PyNumber_Divmod"),
19     #('eval',      "",     "",      ""),
20     #('execfile',  "",     "",      ""),
21     #('filter',    "",     "",      ""),
22     ('getattr',    "OO",   "O",     "PyObject_GetAttr"),
23     ('getattr3',   "OOO",  "O",     "__Pyx_GetAttr3",       "getattr"),
24     ('hasattr',    "OO",   "b",     "PyObject_HasAttr"),
25     ('hash',       "O",    "l",     "PyObject_Hash"),
26     #('hex',       "",     "",      ""),
27     #('id',        "",     "",      ""),
28     #('input',     "",     "",      ""),
29     ('intern',     "s",    "O",     "__Pyx_InternFromString"),
30     ('isinstance', "OO",   "b",     "PyObject_IsInstance"),
31     ('issubclass', "OO",   "b",     "PyObject_IsSubclass"),
32     ('iter',       "O",    "O",     "PyObject_GetIter"),
33     ('len',        "O",    "Z",     "PyObject_Length"),
34     ('locals',     "",     "O",     "__pyx_locals"),
35     #('map',       "",     "",      ""),
36     #('max',       "",     "",      ""),
37     #('min',       "",     "",      ""),
38     #('oct',       "",     "",      ""),
39     # Not worth doing open, when second argument would become mandatory
40     #('open',       "ss",   "O",     "PyFile_FromString"),
41     #('ord',       "",     "",      ""),
42     ('pow',        "OOO",  "O",     "PyNumber_Power"),
43     #('range',     "",     "",      ""),
44     #('raw_input', "",     "",      ""),
45     #('reduce',    "",     "",      ""),
46     ('reload',     "O",    "O",     "PyImport_ReloadModule"),
47     ('repr',       "O",    "O",     "PyObject_Repr"),
48     #('round',     "",     "",      ""),
49     ('setattr',    "OOO",  "r",     "PyObject_SetAttr"),
50     #('sum',       "",     "",      ""),
51     #('unichr',    "",     "",      ""),
52     #('unicode',   "",     "",      ""),
53     #('vars',      "",     "",      ""),
54     #('zip',       "",     "",      ""),
55     #  Can't do these easily until we have builtin type entries.
56     #('typecheck',  "OO",   "i",     "PyObject_TypeCheck", False),
57     #('issubtype',  "OO",   "i",     "PyType_IsSubtype",   False),
58
59     # Put in namespace append optimization.
60     ('__Pyx_PyObject_Append', "OO",  "O",     "__Pyx_PyObject_Append"),
61 ]
62
63 # Builtin types
64 #  bool
65 #  buffer
66 #  classmethod
67 #  dict
68 #  enumerate
69 #  file
70 #  float
71 #  int
72 #  list
73 #  long
74 #  object
75 #  property
76 #  slice
77 #  staticmethod
78 #  super
79 #  str
80 #  tuple
81 #  type
82 #  xrange
83
84 builtin_types_table = [
85
86     ("type",    "PyType_Type",     []),
87
88     ("bool",    "PyBool_Type",     []),
89     ("int",     "PyInt_Type",      []),
90     ("long",    "PyLong_Type",     []),
91     ("float",   "PyFloat_Type",    []),
92     ("complex", "PyComplex_Type",  []),
93
94     ("bytes",   "PyBytes_Type",    []),
95     ("str",     "PyString_Type",   []),
96     ("unicode", "PyUnicode_Type",  []),
97
98     ("tuple",   "PyTuple_Type",    []),
99
100     ("list",    "PyList_Type",     [("append", "OO",   "i", "PyList_Append"),
101                                     ("insert", "OiO",  "i", "PyList_Insert"),
102                                     ("sort",   "O",    "i", "PyList_Sort"),
103                                     ("reverse","O",    "i", "PyList_Reverse")]),
104
105     ("dict",    "PyDict_Type",     [("items", "O",   "O", "PyDict_Items"),
106                                     ("keys",  "O",   "O", "PyDict_Keys"),
107                                     ("values","O",   "O", "PyDict_Values")]),
108
109     ("slice",   "PySlice_Type",    []),
110     ("file",    "PyFile_Type",     []),
111
112     ("set",       "PySet_Type",    [("clear",   "O",  "i", "PySet_Clear"), 
113                                     ("discard", "OO", "i", "PySet_Discard"),
114                                     ("add",     "OO", "i", "PySet_Add"),
115                                     ("pop",     "O",  "O", "PySet_Pop")]),
116     ("frozenset", "PyFrozenSet_Type", []),
117 ]
118
119
120         
121 builtin_structs_table = [
122     ('Py_buffer', 'Py_buffer',
123      [("buf",        PyrexTypes.c_void_ptr_type),
124       ("obj",        PyrexTypes.py_object_type),
125       ("len",        PyrexTypes.c_py_ssize_t_type),
126       ("itemsize",   PyrexTypes.c_py_ssize_t_type),
127       ("readonly",   PyrexTypes.c_bint_type),
128       ("ndim",       PyrexTypes.c_int_type),
129       ("format",     PyrexTypes.c_char_ptr_type),
130       ("shape",      PyrexTypes.c_py_ssize_t_ptr_type),
131       ("strides",    PyrexTypes.c_py_ssize_t_ptr_type),
132       ("suboffsets", PyrexTypes.c_py_ssize_t_ptr_type),
133       ("internal",   PyrexTypes.c_void_ptr_type),
134       ])
135 ]
136
137 getattr3_utility_code = ["""
138 static PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); /*proto*/
139 ""","""
140 static PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) {
141     PyObject *r = PyObject_GetAttr(o, n);
142     if (!r) {
143         if (!PyErr_ExceptionMatches(PyExc_AttributeError))
144             goto bad;
145         PyErr_Clear();
146         r = d;
147         Py_INCREF(d);
148     }
149     return r;
150 bad:
151     return 0;
152 }
153 """]
154
155 intern_utility_code = ["""
156 #if PY_MAJOR_VERSION >= 3
157 #  define __Pyx_InternFromString(s) PyUnicode_InternFromString(s)
158 #else
159 #  define __Pyx_InternFromString(s) PyString_InternFromString(s)
160 #endif
161 ""","""
162 """]
163
164 py23_set_utility_code = ["""
165 #if PY_VERSION_HEX < 0x02050000
166 #ifndef PyAnySet_CheckExact
167
168 #define PyAnySet_CheckExact(ob) \
169     ((ob)->ob_type == ((PyTypeObject*)&PySet_Type) || \
170      (ob)->ob_type == ((PyTypeObject*)&PyFrozenSet_Type))
171
172 #define PySet_Pop(set) PyObject_CallMethod(set, "pop", NULL)
173
174 static INLINE int PySet_Clear(PyObject *set) {
175     PyObject *ret = PyObject_CallMethod(set, "clear", NULL);
176     if (!ret) return -1;
177     Py_DECREF(ret); return 0;
178 }
179
180 static INLINE int PySet_Discard(PyObject *set, PyObject *key) {
181     PyObject *ret = PyObject_CallMethod(set, "discard", "O", key);
182     if (!ret) return -1;
183     Py_DECREF(ret); return 0;
184 }
185
186 static INLINE int PySet_Add(PyObject *set, PyObject *key) {
187     PyObject *ret = PyObject_CallMethod(set, "add", "O", key);
188     if (!ret) return -1;
189     Py_DECREF(ret); return 0;
190 }
191
192 #endif /* PyAnySet_CheckExact (<= Py2.4) */
193
194 #if PY_VERSION_HEX < 0x02040000
195 #ifndef Py_SETOBJECT_H
196 #define Py_SETOBJECT_H
197
198 static PyTypeObject *PySet_Type = NULL;
199 static PyTypeObject *PyFrozenSet_Type = NULL;
200
201 #define PyAnySet_Check(ob) \
202     (PyAnySet_CheckExact(ob) || \
203       PyType_IsSubtype((ob)->ob_type, &PySet_Type) || \
204       PyType_IsSubtype((ob)->ob_type, &PyFrozenSet_Type))
205
206 #define PyFrozenSet_CheckExact(ob) ((ob)->ob_type == &PyFrozenSet_Type)
207
208 #define PySet_New(iterable) \
209     PyObject_CallFunctionObjArgs((PyObject *)PySet_Type, iterable, NULL)
210 #define Pyx_PyFrozenSet_New(iterable) \
211     PyObject_CallFunctionObjArgs((PyObject *)PyFrozenSet_Type, iterable, NULL)
212
213 #define PySet_Size(anyset)          PyObject_Size(anyset)
214 #define PySet_Contains(anyset, key) PySequence_Contains(anyset, key)
215
216 /* ---------------------------------------------------------------- */
217
218 static int __Pyx_Py23SetsImport(void) {
219     PyObject *sets=0, *Set=0, *ImmutableSet=0;
220
221     sets = PyImport_ImportModule("sets");
222     if (!sets) goto bad;
223     Set = PyObject_GetAttrString(sets, "Set");
224     if (!Set) goto bad;
225     ImmutableSet = PyObject_GetAttrString(sets, "ImmutableSet");
226     if (!ImmutableSet) goto bad;
227     Py_DECREF(sets);
228   
229     PySet_Type       = (PyTypeObject*) Set;
230     PyFrozenSet_Type = (PyTypeObject*) ImmutableSet;
231
232     /* FIXME: this should be done in dedicated module cleanup code */
233     /*
234     Py_DECREF(Set);
235     Py_DECREF(ImmutableSet);
236     */
237
238     return 0;
239
240  bad:
241     Py_XDECREF(sets);
242     Py_XDECREF(Set);
243     Py_XDECREF(ImmutableSet);
244     return -1;
245 }
246
247 /* ---------------------------------------------------------------- */
248
249 #else
250 static int py23sets_import(void) { return 0; }
251 #endif /* !Py_SETOBJECT_H */
252 #endif /* < Py2.4  */
253 #endif /* < Py2.5  */
254 ""","""
255 """]
256
257 builtin_utility_code = {
258     'getattr3'  : getattr3_utility_code,
259     'intern'    : intern_utility_code,
260     'set'       : py23_set_utility_code,
261     'frozenset' : py23_set_utility_code,
262 }
263
264 builtin_scope = BuiltinScope()
265
266 def declare_builtin_func(name, args, ret, cname, py_equiv = "*"):
267     sig = Signature(args, ret)
268     type = sig.function_type()
269     utility = builtin_utility_code.get(name)
270     builtin_scope.declare_builtin_cfunction(name, type, cname, py_equiv, utility)
271
272 def init_builtin_funcs():
273     for desc in builtin_function_table:
274         declare_builtin_func(*desc)
275
276 def init_builtin_types():
277     for name, cname, funcs in builtin_types_table:
278         utility = builtin_utility_code.get(name)
279         the_type = builtin_scope.declare_builtin_type(name, cname, utility)
280         for name, args, ret, cname in funcs:
281             sig = Signature(args, ret)
282             the_type.scope.declare_cfunction(name, sig.function_type(), None, cname)
283
284 def init_builtin_structs():
285     for name, cname, attribute_types in builtin_structs_table:
286         scope = StructOrUnionScope(name)
287         for attribute_name, attribute_type in attribute_types:
288             scope.declare_var(
289                 attribute_name, attribute_type, None, attribute_name)
290         builtin_scope.declare_struct_or_union(
291             name, "struct", scope, 1, None, cname = cname)
292
293 def init_builtins():
294     init_builtin_funcs()
295     init_builtin_types()
296     init_builtin_structs()
297     global list_type, tuple_type, dict_type, unicode_type, type_type
298     type_type  = builtin_scope.lookup('type').type
299     list_type  = builtin_scope.lookup('list').type
300     tuple_type = builtin_scope.lookup('tuple').type
301     dict_type  = builtin_scope.lookup('dict').type
302     unicode_type = builtin_scope.lookup('unicode').type
303
304 init_builtins()