Cython has moved to github.

cython-devel

view Cython/Compiler/Builtin.py @ 2194:b9d8cecc8975

general optimisation support for calls to builtin types and their methods

currently providing optimisations for
- getattr(o,a)
- getattr(o,a,d)
- X.append(o)
- L.append(o)
- list.append(L,x)
author Stefan Behnel <scoder@users.berlios.de>
date Sun Mar 29 13:27:55 2009 +0200 (3 years ago)
parents 52b9ed726ad5
children 1c2ee9725be9
line source
1 #
2 # Pyrex - Builtin Definitions
3 #
5 from Symtab import BuiltinScope, StructOrUnionScope
6 from Cython.Utils import UtilityCode
7 from TypeSlots import Signature
8 import PyrexTypes
9 import Naming
11 builtin_function_table = [
12 # name, args, return, C API func, py equiv = "*"
13 ('abs', "O", "O", "PyNumber_Absolute"),
14 #('chr', "", "", ""),
15 #('cmp', "", "", "", ""), # int PyObject_Cmp(PyObject *o1, PyObject *o2, int *result)
16 #('compile', "", "", ""), # PyObject* Py_CompileString( char *str, char *filename, int start)
17 ('delattr', "OO", "r", "PyObject_DelAttr"),
18 ('dir', "O", "O", "PyObject_Dir"),
19 ('divmod', "OO", "O", "PyNumber_Divmod"),
20 ('exec', "OOO", "O", "__Pyx_PyRun"),
21 #('eval', "", "", ""),
22 #('execfile', "", "", ""),
23 #('filter', "", "", ""),
24 #('getattr', "OO", "O", "PyObject_GetAttr"), # optimised later on
25 ('getattr3', "OOO", "O", "__Pyx_GetAttr3", "getattr"),
26 ('hasattr', "OO", "b", "PyObject_HasAttr"),
27 ('hash', "O", "l", "PyObject_Hash"),
28 #('hex', "", "", ""),
29 #('id', "", "", ""),
30 #('input', "", "", ""),
31 ('intern', "s", "O", "__Pyx_InternFromString"),
32 ('isinstance', "OO", "b", "PyObject_IsInstance"),
33 ('issubclass', "OO", "b", "PyObject_IsSubclass"),
34 ('iter', "O", "O", "PyObject_GetIter"),
35 ('len', "O", "Z", "PyObject_Length"),
36 ('locals', "", "O", "__pyx_locals"),
37 #('map', "", "", ""),
38 #('max', "", "", ""),
39 #('min', "", "", ""),
40 #('oct', "", "", ""),
41 # Not worth doing open, when second argument would become mandatory
42 #('open', "ss", "O", "PyFile_FromString"),
43 #('ord', "", "", ""),
44 ('pow', "OOO", "O", "PyNumber_Power"),
45 #('range', "", "", ""),
46 #('raw_input', "", "", ""),
47 #('reduce', "", "", ""),
48 ('reload', "O", "O", "PyImport_ReloadModule"),
49 ('repr', "O", "O", "PyObject_Repr"),
50 #('round', "", "", ""),
51 ('setattr', "OOO", "r", "PyObject_SetAttr"),
52 #('sum', "", "", ""),
53 #('unichr', "", "", ""),
54 #('unicode', "", "", ""),
55 #('vars', "", "", ""),
56 #('zip', "", "", ""),
57 # Can't do these easily until we have builtin type entries.
58 #('typecheck', "OO", "i", "PyObject_TypeCheck", False),
59 #('issubtype', "OO", "i", "PyType_IsSubtype", False),
61 # Put in namespace append optimization.
62 ('__Pyx_PyObject_Append', "OO", "O", "__Pyx_PyObject_Append"),
63 ]
65 # Builtin types
66 # bool
67 # buffer
68 # classmethod
69 # dict
70 # enumerate
71 # file
72 # float
73 # int
74 # list
75 # long
76 # object
77 # property
78 # slice
79 # staticmethod
80 # super
81 # str
82 # tuple
83 # type
84 # xrange
86 builtin_types_table = [
88 ("type", "PyType_Type", []),
90 ("bool", "PyBool_Type", []),
91 ("int", "PyInt_Type", []),
92 ("long", "PyLong_Type", []),
93 ("float", "PyFloat_Type", []),
95 # Until we have a way to access attributes of a type,
96 # we don't want to make this one builtin.
97 # ("complex", "PyComplex_Type", []),
99 ("bytes", "PyBytes_Type", []),
100 ("str", "PyString_Type", []),
101 ("unicode", "PyUnicode_Type", []),
103 ("tuple", "PyTuple_Type", []),
105 ("list", "PyList_Type", [("append", "OO", "i", "PyList_Append"),
106 ("insert", "OZO", "i", "PyList_Insert"),
107 # ("sort", "O", "i", "PyList_Sort"), # has optional arguments
108 ("reverse","O", "i", "PyList_Reverse")]),
110 ("dict", "PyDict_Type", [("items", "O", "O", "PyDict_Items"),
111 ("keys", "O", "O", "PyDict_Keys"),
112 ("values","O", "O", "PyDict_Values"),
113 ("copy", "O", "O", "PyDict_Copy")]),
115 ("slice", "PySlice_Type", []),
116 ("file", "PyFile_Type", []),
118 ("set", "PySet_Type", [("clear", "O", "i", "PySet_Clear"),
119 ("discard", "OO", "i", "PySet_Discard"),
120 ("add", "OO", "i", "PySet_Add"),
121 ("pop", "O", "O", "PySet_Pop")]),
122 ("frozenset", "PyFrozenSet_Type", []),
123 ]
127 builtin_structs_table = [
128 ('Py_buffer', 'Py_buffer',
129 [("buf", PyrexTypes.c_void_ptr_type),
130 ("obj", PyrexTypes.py_object_type),
131 ("len", PyrexTypes.c_py_ssize_t_type),
132 ("itemsize", PyrexTypes.c_py_ssize_t_type),
133 ("readonly", PyrexTypes.c_bint_type),
134 ("ndim", PyrexTypes.c_int_type),
135 ("format", PyrexTypes.c_char_ptr_type),
136 ("shape", PyrexTypes.c_py_ssize_t_ptr_type),
137 ("strides", PyrexTypes.c_py_ssize_t_ptr_type),
138 ("suboffsets", PyrexTypes.c_py_ssize_t_ptr_type),
139 ("internal", PyrexTypes.c_void_ptr_type),
140 ])
141 ]
143 getattr3_utility_code = UtilityCode(
144 proto = """
145 static PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); /*proto*/
146 """,
147 impl = """
148 static PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) {
149 PyObject *r = PyObject_GetAttr(o, n);
150 if (!r) {
151 if (!PyErr_ExceptionMatches(PyExc_AttributeError))
152 goto bad;
153 PyErr_Clear();
154 r = d;
155 Py_INCREF(d);
156 }
157 return r;
158 bad:
159 return 0;
160 }
161 """)
163 pyexec_utility_code = UtilityCode(
164 proto = """
165 static PyObject* __Pyx_PyRun(PyObject*, PyObject*, PyObject*);
166 """,
167 impl = """
168 static PyObject* __Pyx_PyRun(PyObject* o, PyObject* globals, PyObject* locals) {
169 PyObject* result;
170 PyObject* s = 0;
172 if (!locals && !globals) {
173 globals = PyModule_GetDict(%s);""" % Naming.module_cname + """
174 if (!globals)
175 goto bad;
176 locals = globals;
177 } else if (!locals) {
178 locals = globals;
179 } else if (!globals) {
180 globals = locals;
181 }
183 if (PyUnicode_Check(o)) {
184 s = PyUnicode_AsUTF8String(o);
185 if (!s) goto bad;
186 o = s;
187 #if PY_MAJOR_VERSION >= 3
188 } else if (!PyBytes_Check(o)) {
189 #else
190 } else if (!PyString_Check(o)) {
191 #endif
192 /* FIXME: support file objects and code objects */
193 PyErr_SetString(PyExc_TypeError,
194 "exec currently requires a string as code input.");
195 goto bad;
196 }
198 result = PyRun_String(
199 #if PY_MAJOR_VERSION >= 3
200 PyBytes_AS_STRING(o),
201 #else
202 PyString_AS_STRING(o),
203 #endif
204 Py_file_input, globals, locals);
206 Py_XDECREF(s);
207 return result;
208 bad:
209 Py_XDECREF(s);
210 return 0;
211 }
212 """)
214 intern_utility_code = UtilityCode(
215 proto = """
216 #if PY_MAJOR_VERSION >= 3
217 # define __Pyx_InternFromString(s) PyUnicode_InternFromString(s)
218 #else
219 # define __Pyx_InternFromString(s) PyString_InternFromString(s)
220 #endif
221 """)
223 def put_py23_set_init_utility_code(code, pos):
224 code.putln("#if PY_VERSION_HEX < 0x02040000")
225 code.putln(code.error_goto_if_neg("__Pyx_Py23SetsImport()", pos))
226 code.putln("#endif")
228 py23_set_utility_code = UtilityCode(
229 proto = """
230 #if PY_VERSION_HEX < 0x02050000
231 #ifndef PyAnySet_CheckExact
233 #define PyAnySet_CheckExact(ob) \\
234 ((ob)->ob_type == &PySet_Type || \\
235 (ob)->ob_type == &PyFrozenSet_Type)
237 #define PySet_New(iterable) \\
238 PyObject_CallFunctionObjArgs((PyObject *)&PySet_Type, (iterable), NULL)
240 #define Pyx_PyFrozenSet_New(iterable) \\
241 PyObject_CallFunctionObjArgs((PyObject *)&PyFrozenSet_Type, (iterable), NULL)
243 #define PySet_Size(anyset) \\
244 PyObject_Size((anyset))
246 #define PySet_Contains(anyset, key) \\
247 PySequence_Contains((anyset), (key))
249 #define PySet_Pop(set) \\
250 PyObject_CallMethod(set, (char *)"pop", NULL)
252 static INLINE int PySet_Clear(PyObject *set) {
253 PyObject *ret = PyObject_CallMethod(set, (char *)"clear", NULL);
254 if (!ret) return -1;
255 Py_DECREF(ret); return 0;
256 }
258 static INLINE int PySet_Discard(PyObject *set, PyObject *key) {
259 PyObject *ret = PyObject_CallMethod(set, (char *)"discard", (char *)"O", key);
260 if (!ret) return -1;
261 Py_DECREF(ret); return 0;
262 }
264 static INLINE int PySet_Add(PyObject *set, PyObject *key) {
265 PyObject *ret = PyObject_CallMethod(set, (char *)"add", (char *)"O", key);
266 if (!ret) return -1;
267 Py_DECREF(ret); return 0;
268 }
270 #endif /* PyAnySet_CheckExact (<= Py2.4) */
272 #if PY_VERSION_HEX < 0x02040000
273 #ifndef Py_SETOBJECT_H
274 #define Py_SETOBJECT_H
276 static PyTypeObject *__Pyx_PySet_Type = NULL;
277 static PyTypeObject *__Pyx_PyFrozenSet_Type = NULL;
279 #define PySet_Type (*__Pyx_PySet_Type)
280 #define PyFrozenSet_Type (*__Pyx_PyFrozenSet_Type)
282 #define PyAnySet_Check(ob) \\
283 (PyAnySet_CheckExact(ob) || \\
284 PyType_IsSubtype((ob)->ob_type, &PySet_Type) || \\
285 PyType_IsSubtype((ob)->ob_type, &PyFrozenSet_Type))
287 #define PyFrozenSet_CheckExact(ob) ((ob)->ob_type == &PyFrozenSet_Type)
289 static int __Pyx_Py23SetsImport(void) {
290 PyObject *sets=0, *Set=0, *ImmutableSet=0;
292 sets = PyImport_ImportModule((char *)"sets");
293 if (!sets) goto bad;
294 Set = PyObject_GetAttrString(sets, (char *)"Set");
295 if (!Set) goto bad;
296 ImmutableSet = PyObject_GetAttrString(sets, (char *)"ImmutableSet");
297 if (!ImmutableSet) goto bad;
298 Py_DECREF(sets);
300 __Pyx_PySet_Type = (PyTypeObject*) Set;
301 __Pyx_PyFrozenSet_Type = (PyTypeObject*) ImmutableSet;
303 return 0;
305 bad:
306 Py_XDECREF(sets);
307 Py_XDECREF(Set);
308 Py_XDECREF(ImmutableSet);
309 return -1;
310 }
312 #else
313 static int __Pyx_Py23SetsImport(void) { return 0; }
314 #endif /* !Py_SETOBJECT_H */
315 #endif /* < Py2.4 */
316 #endif /* < Py2.5 */
317 """,
318 init = put_py23_set_init_utility_code,
319 cleanup = """
320 #if PY_VERSION_HEX < 0x02040000
321 Py_XDECREF(__Pyx_PySet_Type); __Pyx_PySet_Type = NULL;
322 Py_XDECREF(__Pyx_PyFrozenSet_Type); __Pyx_PyFrozenSet_Type = NULL;
323 #endif /* < Py2.4 */
324 """)
326 builtin_utility_code = {
327 'exec' : pyexec_utility_code,
328 'getattr3' : getattr3_utility_code,
329 'intern' : intern_utility_code,
330 'set' : py23_set_utility_code,
331 'frozenset' : py23_set_utility_code,
332 }
334 builtin_scope = BuiltinScope()
336 def declare_builtin_func(name, args, ret, cname, py_equiv = "*"):
337 sig = Signature(args, ret)
338 type = sig.function_type()
339 utility = builtin_utility_code.get(name)
340 builtin_scope.declare_builtin_cfunction(name, type, cname, py_equiv, utility)
342 def init_builtin_funcs():
343 for desc in builtin_function_table:
344 declare_builtin_func(*desc)
346 builtin_types = {}
348 def init_builtin_types():
349 global builtin_types
350 for name, cname, funcs in builtin_types_table:
351 utility = builtin_utility_code.get(name)
352 the_type = builtin_scope.declare_builtin_type(name, cname, utility)
353 builtin_types[name] = the_type
354 for name, args, ret, cname in funcs:
355 sig = Signature(args, ret)
356 the_type.scope.declare_cfunction(name, sig.function_type(), None, cname)
358 def init_builtin_structs():
359 for name, cname, attribute_types in builtin_structs_table:
360 scope = StructOrUnionScope(name)
361 for attribute_name, attribute_type in attribute_types:
362 scope.declare_var(
363 attribute_name, attribute_type, None, attribute_name)
364 builtin_scope.declare_struct_or_union(
365 name, "struct", scope, 1, None, cname = cname)
367 def init_builtins():
368 init_builtin_funcs()
369 init_builtin_types()
370 init_builtin_structs()
371 global list_type, tuple_type, dict_type, set_type, unicode_type, type_type
372 type_type = builtin_scope.lookup('type').type
373 list_type = builtin_scope.lookup('list').type
374 tuple_type = builtin_scope.lookup('tuple').type
375 dict_type = builtin_scope.lookup('dict').type
376 set_type = builtin_scope.lookup('set').type
377 unicode_type = builtin_scope.lookup('unicode').type
379 init_builtins()