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