OLD | NEW |
(Empty) | |
| 1 # |
| 2 # Builtin Definitions |
| 3 # |
| 4 |
| 5 from Symtab import BuiltinScope, StructOrUnionScope |
| 6 from Code import UtilityCode |
| 7 from TypeSlots import Signature |
| 8 import PyrexTypes |
| 9 import Options |
| 10 |
| 11 |
| 12 # C-level implementations of builtin types, functions and methods |
| 13 |
| 14 iter_next_utility_code = UtilityCode.load("IterNext", "ObjectHandling.c") |
| 15 getattr_utility_code = UtilityCode.load("GetAttr", "ObjectHandling.c") |
| 16 getattr3_utility_code = UtilityCode.load("GetAttr3", "Builtins.c") |
| 17 pyexec_utility_code = UtilityCode.load("PyExec", "Builtins.c") |
| 18 pyexec_globals_utility_code = UtilityCode.load("PyExecGlobals", "Builtins.c") |
| 19 globals_utility_code = UtilityCode.load("Globals", "Builtins.c") |
| 20 |
| 21 py_set_utility_code = UtilityCode.load("pyset_compat", "Builtins.c") |
| 22 |
| 23 builtin_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 |
| 31 class _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 |
| 54 class BuiltinAttribute(object): |
| 55 def __init__(self, py_name, cname=None, field_type=None, field_type_name=Non
e): |
| 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, No
ne, 'private') |
| 68 entry.is_variable = True |
| 69 |
| 70 |
| 71 class 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 |
| 80 class 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_cod
e) |
| 91 |
| 92 |
| 93 builtin_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_typ
e, 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", "ObjectHand
ling.c")), |
| 123 #('chr', "", "", ""), |
| 124 #('cmp', "", "", "", ""), # int PyObject_Cmp(PyObject *o1, PyObje
ct *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", "getatt
r", |
| 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_retu
rn_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_App
end"), |
| 189 ] |
| 190 |
| 191 if 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 |
| 217 builtin_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_P
yBaseString_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_P
yBytes_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_P
yString_Join", |
| 247 builtin_return_type='basestrin
g', |
| 248 utility_code=UtilityCode.load(
"StringJoin", "StringTools.c")), |
| 249 ]), |
| 250 ("unicode", "PyUnicode_Type", [BuiltinMethod("__contains__", "TO", "b",
"PyUnicode_Contains"), |
| 251 BuiltinMethod("join", "TO", "T", "PyUnico
de_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", "PyLis
t_Insert"), |
| 259 BuiltinMethod("reverse", "T", "r", "PyLis
t_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_P
yDict_Items", |
| 269 utility_code=UtilityCode.load(
"py_dict_items", "Builtins.c")), |
| 270 BuiltinMethod("keys", "T", "O", "__Pyx_P
yDict_Keys", |
| 271 utility_code=UtilityCode.load(
"py_dict_keys", "Builtins.c")), |
| 272 BuiltinMethod("values", "T", "O", "__Pyx_P
yDict_Values", |
| 273 utility_code=UtilityCode.load(
"py_dict_values", "Builtins.c")), |
| 274 BuiltinMethod("iteritems", "T", "O", "__P
yx_PyDict_IterItems", |
| 275 utility_code=UtilityCode.load(
"py_dict_iteritems", "Builtins.c")), |
| 276 BuiltinMethod("iterkeys", "T", "O", "__P
yx_PyDict_IterKeys", |
| 277 utility_code=UtilityCode.load(
"py_dict_iterkeys", "Builtins.c")), |
| 278 BuiltinMethod("itervalues", "T", "O", "__P
yx_PyDict_IterValues", |
| 279 utility_code=UtilityCode.load(
"py_dict_itervalues", "Builtins.c")), |
| 280 BuiltinMethod("viewitems", "T", "O", "__P
yx_PyDict_ViewItems", |
| 281 utility_code=UtilityCode.load(
"py_dict_viewitems", "Builtins.c")), |
| 282 BuiltinMethod("viewkeys", "T", "O", "__P
yx_PyDict_ViewKeys", |
| 283 utility_code=UtilityCode.load(
"py_dict_viewkeys", "Builtins.c")), |
| 284 BuiltinMethod("viewvalues", "T", "O", "__P
yx_PyDict_ViewValues", |
| 285 utility_code=UtilityCode.load(
"py_dict_viewvalues", "Builtins.c")), |
| 286 BuiltinMethod("clear", "T", "r", "__Pyx_P
yDict_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_C
lear", |
| 298 utility_code = py_set_utility_
code), |
| 299 # discard() and remove() have a special trea
tment for unhashable values |
| 300 # BuiltinMethod("discard", "TO", "r", "PySet_
Discard", |
| 301 # utility_code = py_set_utility
_code), |
| 302 BuiltinMethod("add", "TO", "r", "PySet_A
dd", |
| 303 utility_code = py_set_utility_
code), |
| 304 BuiltinMethod("pop", "T", "O", "PySet_P
op", |
| 305 utility_code = py_set_utility_
code)]), |
| 306 ("frozenset", "PyFrozenSet_Type", []), |
| 307 ] |
| 308 |
| 309 |
| 310 types_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 |
| 321 builtin_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 |
| 344 builtin_scope = BuiltinScope() |
| 345 |
| 346 def init_builtin_funcs(): |
| 347 for bf in builtin_function_table: |
| 348 bf.declare_in_scope(builtin_scope) |
| 349 |
| 350 builtin_types = {} |
| 351 |
| 352 def 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, objs
truct_cname) |
| 363 builtin_types[name] = the_type |
| 364 for method in methods: |
| 365 method.declare_in_type(the_type) |
| 366 |
| 367 def 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 |
| 377 def 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 |
| 404 init_builtins() |
OLD | NEW |