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