1# 2# Builtin Definitions 3# 4 5from __future__ import absolute_import 6 7from .Symtab import BuiltinScope, StructOrUnionScope 8from .Code import UtilityCode 9from .TypeSlots import Signature 10from . import PyrexTypes 11from . import Options 12 13 14# C-level implementations of builtin types, functions and methods 15 16iter_next_utility_code = UtilityCode.load("IterNext", "ObjectHandling.c") 17getattr_utility_code = UtilityCode.load("GetAttr", "ObjectHandling.c") 18getattr3_utility_code = UtilityCode.load("GetAttr3", "Builtins.c") 19pyexec_utility_code = UtilityCode.load("PyExec", "Builtins.c") 20pyexec_globals_utility_code = UtilityCode.load("PyExecGlobals", "Builtins.c") 21globals_utility_code = UtilityCode.load("Globals", "Builtins.c") 22 23builtin_utility_code = { 24 'StopAsyncIteration': UtilityCode.load_cached("StopAsyncIteration", "Coroutine.c"), 25} 26 27 28# mapping from builtins to their C-level equivalents 29 30class _BuiltinOverride(object): 31 def __init__(self, py_name, args, ret_type, cname, py_equiv="*", 32 utility_code=None, sig=None, func_type=None, 33 is_strict_signature=False, builtin_return_type=None, 34 nogil=None): 35 self.py_name, self.cname, self.py_equiv = py_name, cname, py_equiv 36 self.args, self.ret_type = args, ret_type 37 self.func_type, self.sig = func_type, sig 38 self.builtin_return_type = builtin_return_type 39 self.is_strict_signature = is_strict_signature 40 self.utility_code = utility_code 41 self.nogil = nogil 42 43 def build_func_type(self, sig=None, self_arg=None): 44 if sig is None: 45 sig = Signature(self.args, self.ret_type, nogil=self.nogil) 46 sig.exception_check = False # not needed for the current builtins 47 func_type = sig.function_type(self_arg) 48 if self.is_strict_signature: 49 func_type.is_strict_signature = True 50 if self.builtin_return_type: 51 func_type.return_type = builtin_types[self.builtin_return_type] 52 return func_type 53 54 55class BuiltinAttribute(object): 56 def __init__(self, py_name, cname=None, field_type=None, field_type_name=None): 57 self.py_name = py_name 58 self.cname = cname or py_name 59 self.field_type_name = field_type_name # can't do the lookup before the type is declared! 60 self.field_type = field_type 61 62 def declare_in_type(self, self_type): 63 if self.field_type_name is not None: 64 # lazy type lookup 65 field_type = builtin_scope.lookup(self.field_type_name).type 66 else: 67 field_type = self.field_type or PyrexTypes.py_object_type 68 entry = self_type.scope.declare(self.py_name, self.cname, field_type, None, 'private') 69 entry.is_variable = True 70 71 72class BuiltinFunction(_BuiltinOverride): 73 def declare_in_scope(self, scope): 74 func_type, sig = self.func_type, self.sig 75 if func_type is None: 76 func_type = self.build_func_type(sig) 77 scope.declare_builtin_cfunction(self.py_name, func_type, self.cname, 78 self.py_equiv, self.utility_code) 79 80 81class BuiltinMethod(_BuiltinOverride): 82 def declare_in_type(self, self_type): 83 method_type, sig = self.func_type, self.sig 84 if method_type is None: 85 # override 'self' type (first argument) 86 self_arg = PyrexTypes.CFuncTypeArg("", self_type, None) 87 self_arg.not_none = True 88 self_arg.accept_builtin_subtypes = True 89 method_type = self.build_func_type(sig, self_arg) 90 self_type.scope.declare_builtin_cfunction( 91 self.py_name, method_type, self.cname, utility_code=self.utility_code) 92 93 94builtin_function_table = [ 95 # name, args, return, C API func, py equiv = "*" 96 BuiltinFunction('abs', "d", "d", "fabs", 97 is_strict_signature=True, nogil=True), 98 BuiltinFunction('abs', "f", "f", "fabsf", 99 is_strict_signature=True, nogil=True), 100 BuiltinFunction('abs', "i", "i", "abs", 101 is_strict_signature=True, nogil=True), 102 BuiltinFunction('abs', "l", "l", "labs", 103 is_strict_signature=True, nogil=True), 104 BuiltinFunction('abs', None, None, "__Pyx_abs_longlong", 105 utility_code = UtilityCode.load("abs_longlong", "Builtins.c"), 106 func_type = PyrexTypes.CFuncType( 107 PyrexTypes.c_longlong_type, [ 108 PyrexTypes.CFuncTypeArg("arg", PyrexTypes.c_longlong_type, None) 109 ], 110 is_strict_signature = True, nogil=True)), 111 ] + list( 112 BuiltinFunction('abs', None, None, "/*abs_{0}*/".format(t.specialization_name()), 113 func_type = PyrexTypes.CFuncType( 114 t, 115 [PyrexTypes.CFuncTypeArg("arg", t, None)], 116 is_strict_signature = True, nogil=True)) 117 for t in (PyrexTypes.c_uint_type, PyrexTypes.c_ulong_type, PyrexTypes.c_ulonglong_type) 118 ) + list( 119 BuiltinFunction('abs', None, None, "__Pyx_c_abs{0}".format(t.funcsuffix), 120 func_type = PyrexTypes.CFuncType( 121 t.real_type, [ 122 PyrexTypes.CFuncTypeArg("arg", t, None) 123 ], 124 is_strict_signature = True, nogil=True)) 125 for t in (PyrexTypes.c_float_complex_type, 126 PyrexTypes.c_double_complex_type, 127 PyrexTypes.c_longdouble_complex_type) 128 ) + [ 129 BuiltinFunction('abs', "O", "O", "__Pyx_PyNumber_Absolute", 130 utility_code=UtilityCode.load("py_abs", "Builtins.c")), 131 #('all', "", "", ""), 132 #('any', "", "", ""), 133 #('ascii', "", "", ""), 134 #('bin', "", "", ""), 135 BuiltinFunction('callable', "O", "b", "__Pyx_PyCallable_Check", 136 utility_code = UtilityCode.load("CallableCheck", "ObjectHandling.c")), 137 #('chr', "", "", ""), 138 #('cmp', "", "", "", ""), # int PyObject_Cmp(PyObject *o1, PyObject *o2, int *result) 139 #('compile', "", "", ""), # PyObject* Py_CompileString( char *str, char *filename, int start) 140 BuiltinFunction('delattr', "OO", "r", "PyObject_DelAttr"), 141 BuiltinFunction('dir', "O", "O", "PyObject_Dir"), 142 BuiltinFunction('divmod', "OO", "O", "PyNumber_Divmod"), 143 BuiltinFunction('exec', "O", "O", "__Pyx_PyExecGlobals", 144 utility_code = pyexec_globals_utility_code), 145 BuiltinFunction('exec', "OO", "O", "__Pyx_PyExec2", 146 utility_code = pyexec_utility_code), 147 BuiltinFunction('exec', "OOO", "O", "__Pyx_PyExec3", 148 utility_code = pyexec_utility_code), 149 #('eval', "", "", ""), 150 #('execfile', "", "", ""), 151 #('filter', "", "", ""), 152 BuiltinFunction('getattr3', "OOO", "O", "__Pyx_GetAttr3", "getattr", 153 utility_code=getattr3_utility_code), # Pyrex legacy 154 BuiltinFunction('getattr', "OOO", "O", "__Pyx_GetAttr3", 155 utility_code=getattr3_utility_code), 156 BuiltinFunction('getattr', "OO", "O", "__Pyx_GetAttr", 157 utility_code=getattr_utility_code), 158 BuiltinFunction('hasattr', "OO", "b", "__Pyx_HasAttr", 159 utility_code = UtilityCode.load("HasAttr", "Builtins.c")), 160 BuiltinFunction('hash', "O", "h", "PyObject_Hash"), 161 #('hex', "", "", ""), 162 #('id', "", "", ""), 163 #('input', "", "", ""), 164 BuiltinFunction('intern', "O", "O", "__Pyx_Intern", 165 utility_code = UtilityCode.load("Intern", "Builtins.c")), 166 BuiltinFunction('isinstance', "OO", "b", "PyObject_IsInstance"), 167 BuiltinFunction('issubclass', "OO", "b", "PyObject_IsSubclass"), 168 BuiltinFunction('iter', "OO", "O", "PyCallIter_New"), 169 BuiltinFunction('iter', "O", "O", "PyObject_GetIter"), 170 BuiltinFunction('len', "O", "z", "PyObject_Length"), 171 BuiltinFunction('locals', "", "O", "__pyx_locals"), 172 #('map', "", "", ""), 173 #('max', "", "", ""), 174 #('min', "", "", ""), 175 BuiltinFunction('next', "O", "O", "__Pyx_PyIter_Next", 176 utility_code = iter_next_utility_code), # not available in Py2 => implemented here 177 BuiltinFunction('next', "OO", "O", "__Pyx_PyIter_Next2", 178 utility_code = iter_next_utility_code), # not available in Py2 => implemented here 179 #('oct', "", "", ""), 180 #('open', "ss", "O", "PyFile_FromString"), # not in Py3 181] + [ 182 BuiltinFunction('ord', None, None, "__Pyx_long_cast", 183 func_type=PyrexTypes.CFuncType( 184 PyrexTypes.c_long_type, [PyrexTypes.CFuncTypeArg("c", c_type, None)], 185 is_strict_signature=True)) 186 for c_type in [PyrexTypes.c_py_ucs4_type, PyrexTypes.c_py_unicode_type] 187] + [ 188 BuiltinFunction('ord', None, None, "__Pyx_uchar_cast", 189 func_type=PyrexTypes.CFuncType( 190 PyrexTypes.c_uchar_type, [PyrexTypes.CFuncTypeArg("c", c_type, None)], 191 is_strict_signature=True)) 192 for c_type in [PyrexTypes.c_char_type, PyrexTypes.c_schar_type, PyrexTypes.c_uchar_type] 193] + [ 194 BuiltinFunction('ord', None, None, "__Pyx_PyObject_Ord", 195 utility_code=UtilityCode.load_cached("object_ord", "Builtins.c"), 196 func_type=PyrexTypes.CFuncType( 197 PyrexTypes.c_long_type, [ 198 PyrexTypes.CFuncTypeArg("c", PyrexTypes.py_object_type, None) 199 ], 200 exception_value="(long)(Py_UCS4)-1")), 201 BuiltinFunction('pow', "OOO", "O", "PyNumber_Power"), 202 BuiltinFunction('pow', "OO", "O", "__Pyx_PyNumber_Power2", 203 utility_code = UtilityCode.load("pow2", "Builtins.c")), 204 #('range', "", "", ""), 205 #('raw_input', "", "", ""), 206 #('reduce', "", "", ""), 207 BuiltinFunction('reload', "O", "O", "PyImport_ReloadModule"), 208 BuiltinFunction('repr', "O", "O", "PyObject_Repr"), # , builtin_return_type='str'), # add in Cython 3.1 209 #('round', "", "", ""), 210 BuiltinFunction('setattr', "OOO", "r", "PyObject_SetAttr"), 211 #('sum', "", "", ""), 212 #('sorted', "", "", ""), 213 #('type', "O", "O", "PyObject_Type"), 214 BuiltinFunction('unichr', "l", "O", "PyUnicode_FromOrdinal", builtin_return_type='unicode'), 215 #('unicode', "", "", ""), 216 #('vars', "", "", ""), 217 #('zip', "", "", ""), 218 # Can't do these easily until we have builtin type entries. 219 #('typecheck', "OO", "i", "PyObject_TypeCheck", False), 220 #('issubtype', "OO", "i", "PyType_IsSubtype", False), 221 222 # Put in namespace append optimization. 223 BuiltinFunction('__Pyx_PyObject_Append', "OO", "O", "__Pyx_PyObject_Append"), 224 225 # This is conditionally looked up based on a compiler directive. 226 BuiltinFunction('__Pyx_Globals', "", "O", "__Pyx_Globals", 227 utility_code=globals_utility_code), 228] 229 230 231# Builtin types 232# bool 233# buffer 234# classmethod 235# dict 236# enumerate 237# file 238# float 239# int 240# list 241# long 242# object 243# property 244# slice 245# staticmethod 246# super 247# str 248# tuple 249# type 250# xrange 251 252builtin_types_table = [ 253 254 ("type", "PyType_Type", []), 255 256# This conflicts with the C++ bool type, and unfortunately 257# C++ is too liberal about PyObject* <-> bool conversions, 258# resulting in unintuitive runtime behavior and segfaults. 259# ("bool", "PyBool_Type", []), 260 261 ("int", "PyInt_Type", []), 262 ("long", "PyLong_Type", []), 263 ("float", "PyFloat_Type", []), 264 265 ("complex", "PyComplex_Type", [BuiltinAttribute('cval', field_type_name = 'Py_complex'), 266 BuiltinAttribute('real', 'cval.real', field_type = PyrexTypes.c_double_type), 267 BuiltinAttribute('imag', 'cval.imag', field_type = PyrexTypes.c_double_type), 268 ]), 269 270 ("basestring", "PyBaseString_Type", [ 271 BuiltinMethod("join", "TO", "T", "__Pyx_PyBaseString_Join", 272 utility_code=UtilityCode.load("StringJoin", "StringTools.c")), 273 ]), 274 ("bytearray", "PyByteArray_Type", [ 275 ]), 276 ("bytes", "PyBytes_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"), 277 BuiltinMethod("join", "TO", "O", "__Pyx_PyBytes_Join", 278 utility_code=UtilityCode.load("StringJoin", "StringTools.c")), 279 ]), 280 ("str", "PyString_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"), 281 BuiltinMethod("join", "TO", "O", "__Pyx_PyString_Join", 282 builtin_return_type='basestring', 283 utility_code=UtilityCode.load("StringJoin", "StringTools.c")), 284 ]), 285 ("unicode", "PyUnicode_Type", [BuiltinMethod("__contains__", "TO", "b", "PyUnicode_Contains"), 286 BuiltinMethod("join", "TO", "T", "PyUnicode_Join"), 287 ]), 288 289 ("tuple", "PyTuple_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"), 290 ]), 291 292 ("list", "PyList_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"), 293 BuiltinMethod("insert", "TzO", "r", "PyList_Insert"), 294 BuiltinMethod("reverse", "T", "r", "PyList_Reverse"), 295 BuiltinMethod("append", "TO", "r", "__Pyx_PyList_Append", 296 utility_code=UtilityCode.load("ListAppend", "Optimize.c")), 297 BuiltinMethod("extend", "TO", "r", "__Pyx_PyList_Extend", 298 utility_code=UtilityCode.load("ListExtend", "Optimize.c")), 299 ]), 300 301 ("dict", "PyDict_Type", [BuiltinMethod("__contains__", "TO", "b", "PyDict_Contains"), 302 BuiltinMethod("has_key", "TO", "b", "PyDict_Contains"), 303 BuiltinMethod("items", "T", "O", "__Pyx_PyDict_Items", 304 utility_code=UtilityCode.load("py_dict_items", "Builtins.c")), 305 BuiltinMethod("keys", "T", "O", "__Pyx_PyDict_Keys", 306 utility_code=UtilityCode.load("py_dict_keys", "Builtins.c")), 307 BuiltinMethod("values", "T", "O", "__Pyx_PyDict_Values", 308 utility_code=UtilityCode.load("py_dict_values", "Builtins.c")), 309 BuiltinMethod("iteritems", "T", "O", "__Pyx_PyDict_IterItems", 310 utility_code=UtilityCode.load("py_dict_iteritems", "Builtins.c")), 311 BuiltinMethod("iterkeys", "T", "O", "__Pyx_PyDict_IterKeys", 312 utility_code=UtilityCode.load("py_dict_iterkeys", "Builtins.c")), 313 BuiltinMethod("itervalues", "T", "O", "__Pyx_PyDict_IterValues", 314 utility_code=UtilityCode.load("py_dict_itervalues", "Builtins.c")), 315 BuiltinMethod("viewitems", "T", "O", "__Pyx_PyDict_ViewItems", 316 utility_code=UtilityCode.load("py_dict_viewitems", "Builtins.c")), 317 BuiltinMethod("viewkeys", "T", "O", "__Pyx_PyDict_ViewKeys", 318 utility_code=UtilityCode.load("py_dict_viewkeys", "Builtins.c")), 319 BuiltinMethod("viewvalues", "T", "O", "__Pyx_PyDict_ViewValues", 320 utility_code=UtilityCode.load("py_dict_viewvalues", "Builtins.c")), 321 BuiltinMethod("clear", "T", "r", "__Pyx_PyDict_Clear", 322 utility_code=UtilityCode.load("py_dict_clear", "Optimize.c")), 323 BuiltinMethod("copy", "T", "T", "PyDict_Copy")]), 324 325 ("slice", "PySlice_Type", [BuiltinAttribute('start'), 326 BuiltinAttribute('stop'), 327 BuiltinAttribute('step'), 328 ]), 329# ("file", "PyFile_Type", []), # not in Py3 330 331 ("set", "PySet_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"), 332 BuiltinMethod("clear", "T", "r", "PySet_Clear"), 333 # discard() and remove() have a special treatment for unhashable values 334 BuiltinMethod("discard", "TO", "r", "__Pyx_PySet_Discard", 335 utility_code=UtilityCode.load("py_set_discard", "Optimize.c")), 336 BuiltinMethod("remove", "TO", "r", "__Pyx_PySet_Remove", 337 utility_code=UtilityCode.load("py_set_remove", "Optimize.c")), 338 # update is actually variadic (see Github issue #1645) 339# BuiltinMethod("update", "TO", "r", "__Pyx_PySet_Update", 340# utility_code=UtilityCode.load_cached("PySet_Update", "Builtins.c")), 341 BuiltinMethod("add", "TO", "r", "PySet_Add"), 342 BuiltinMethod("pop", "T", "O", "PySet_Pop")]), 343 ("frozenset", "PyFrozenSet_Type", []), 344 ("Exception", "((PyTypeObject*)PyExc_Exception)[0]", []), 345 ("StopAsyncIteration", "((PyTypeObject*)__Pyx_PyExc_StopAsyncIteration)[0]", []), 346] 347 348 349types_that_construct_their_instance = frozenset({ 350 # some builtin types do not always return an instance of 351 # themselves - these do: 352 'type', 'bool', 'long', 'float', 'complex', 353 'bytes', 'unicode', 'bytearray', 354 'tuple', 'list', 'dict', 'set', 'frozenset', 355 # 'str', # only in Py3.x 356 # 'file', # only in Py2.x 357}) 358 359 360builtin_structs_table = [ 361 ('Py_buffer', 'Py_buffer', 362 [("buf", PyrexTypes.c_void_ptr_type), 363 ("obj", PyrexTypes.py_object_type), 364 ("len", PyrexTypes.c_py_ssize_t_type), 365 ("itemsize", PyrexTypes.c_py_ssize_t_type), 366 ("readonly", PyrexTypes.c_bint_type), 367 ("ndim", PyrexTypes.c_int_type), 368 ("format", PyrexTypes.c_char_ptr_type), 369 ("shape", PyrexTypes.c_py_ssize_t_ptr_type), 370 ("strides", PyrexTypes.c_py_ssize_t_ptr_type), 371 ("suboffsets", PyrexTypes.c_py_ssize_t_ptr_type), 372 ("smalltable", PyrexTypes.CArrayType(PyrexTypes.c_py_ssize_t_type, 2)), 373 ("internal", PyrexTypes.c_void_ptr_type), 374 ]), 375 ('Py_complex', 'Py_complex', 376 [('real', PyrexTypes.c_double_type), 377 ('imag', PyrexTypes.c_double_type), 378 ]) 379] 380 381# set up builtin scope 382 383builtin_scope = BuiltinScope() 384 385def init_builtin_funcs(): 386 for bf in builtin_function_table: 387 bf.declare_in_scope(builtin_scope) 388 389builtin_types = {} 390 391def init_builtin_types(): 392 global builtin_types 393 for name, cname, methods in builtin_types_table: 394 utility = builtin_utility_code.get(name) 395 if name == 'frozenset': 396 objstruct_cname = 'PySetObject' 397 elif name == 'bytearray': 398 objstruct_cname = 'PyByteArrayObject' 399 elif name == 'bool': 400 objstruct_cname = None 401 elif name == 'Exception': 402 objstruct_cname = "PyBaseExceptionObject" 403 elif name == 'StopAsyncIteration': 404 objstruct_cname = "PyBaseExceptionObject" 405 else: 406 objstruct_cname = 'Py%sObject' % name.capitalize() 407 the_type = builtin_scope.declare_builtin_type(name, cname, utility, objstruct_cname) 408 builtin_types[name] = the_type 409 for method in methods: 410 method.declare_in_type(the_type) 411 412def init_builtin_structs(): 413 for name, cname, attribute_types in builtin_structs_table: 414 scope = StructOrUnionScope(name) 415 for attribute_name, attribute_type in attribute_types: 416 scope.declare_var(attribute_name, attribute_type, None, 417 attribute_name, allow_pyobject=True) 418 builtin_scope.declare_struct_or_union( 419 name, "struct", scope, 1, None, cname = cname) 420 421 422def init_builtins(): 423 init_builtin_structs() 424 init_builtin_types() 425 init_builtin_funcs() 426 427 builtin_scope.declare_var( 428 '__debug__', PyrexTypes.c_const_type(PyrexTypes.c_bint_type), 429 pos=None, cname='(!Py_OptimizeFlag)', is_cdef=True) 430 431 global list_type, tuple_type, dict_type, set_type, frozenset_type 432 global bytes_type, str_type, unicode_type, basestring_type, slice_type 433 global float_type, long_type, bool_type, type_type, complex_type, bytearray_type 434 type_type = builtin_scope.lookup('type').type 435 list_type = builtin_scope.lookup('list').type 436 tuple_type = builtin_scope.lookup('tuple').type 437 dict_type = builtin_scope.lookup('dict').type 438 set_type = builtin_scope.lookup('set').type 439 frozenset_type = builtin_scope.lookup('frozenset').type 440 slice_type = builtin_scope.lookup('slice').type 441 bytes_type = builtin_scope.lookup('bytes').type 442 str_type = builtin_scope.lookup('str').type 443 unicode_type = builtin_scope.lookup('unicode').type 444 basestring_type = builtin_scope.lookup('basestring').type 445 bytearray_type = builtin_scope.lookup('bytearray').type 446 float_type = builtin_scope.lookup('float').type 447 long_type = builtin_scope.lookup('long').type 448 bool_type = builtin_scope.lookup('bool').type 449 complex_type = builtin_scope.lookup('complex').type 450 451 452init_builtins() 453