cython

Форк
0
/
Builtin.py 
796 строк · 34.5 Кб
1
#
2
#   Builtin Definitions
3
#
4

5

6
from .StringEncoding import EncodedString
7
from .Symtab import BuiltinScope, StructOrUnionScope, ModuleScope, Entry
8
from .Code import UtilityCode, TempitaUtilityCode
9
from .TypeSlots import Signature
10
from . import PyrexTypes
11

12

13
# C-level implementations of builtin types, functions and methods
14

15
iter_next_utility_code = UtilityCode.load("IterNext", "ObjectHandling.c")
16
getattr_utility_code = UtilityCode.load("GetAttr", "ObjectHandling.c")
17
getattr3_utility_code = UtilityCode.load("GetAttr3", "Builtins.c")
18
pyexec_utility_code = UtilityCode.load("PyExec", "Builtins.c")
19
pyexec_globals_utility_code = UtilityCode.load("PyExecGlobals", "Builtins.c")
20
globals_utility_code = UtilityCode.load("Globals", "Builtins.c")
21

22

23
# mapping from builtins to their C-level equivalents
24

25
class _BuiltinOverride:
26
    def __init__(self, py_name, args, ret_type, cname, py_equiv="*",
27
                 utility_code=None, sig=None, func_type=None,
28
                 is_strict_signature=False, builtin_return_type=None,
29
                 nogil=None):
30
        self.py_name, self.cname, self.py_equiv = py_name, cname, py_equiv
31
        self.args, self.ret_type = args, ret_type
32
        self.func_type, self.sig = func_type, sig
33
        self.builtin_return_type = builtin_return_type
34
        self.is_strict_signature = is_strict_signature
35
        self.utility_code = utility_code
36
        self.nogil = nogil
37

38
    def build_func_type(self, sig=None, self_arg=None):
39
        if sig is None:
40
            sig = Signature(self.args, self.ret_type, nogil=self.nogil)
41
            sig.exception_check = False  # not needed for the current builtins
42
        func_type = sig.function_type(self_arg)
43
        if self.is_strict_signature:
44
            func_type.is_strict_signature = True
45
        if self.builtin_return_type:
46
            func_type.return_type = builtin_types[self.builtin_return_type]
47
        return func_type
48

49

50
class BuiltinAttribute:
51
    def __init__(self, py_name, cname=None, field_type=None, field_type_name=None):
52
        self.py_name = py_name
53
        self.cname = cname or py_name
54
        self.field_type_name = field_type_name  # can't do the lookup before the type is declared!
55
        self.field_type = field_type
56

57
    def declare_in_type(self, self_type):
58
        if self.field_type_name is not None:
59
            # lazy type lookup
60
            field_type = builtin_scope.lookup(self.field_type_name).type
61
        else:
62
            field_type = self.field_type or PyrexTypes.py_object_type
63
        entry = self_type.scope.declare(self.py_name, self.cname, field_type, None, 'private')
64
        entry.is_variable = True
65

66

67
class BuiltinFunction(_BuiltinOverride):
68
    def declare_in_scope(self, scope):
69
        func_type, sig = self.func_type, self.sig
70
        if func_type is None:
71
            func_type = self.build_func_type(sig)
72
        scope.declare_builtin_cfunction(self.py_name, func_type, self.cname,
73
                                        self.py_equiv, self.utility_code)
74

75

76
class BuiltinMethod(_BuiltinOverride):
77
    def declare_in_type(self, self_type):
78
        method_type, sig = self.func_type, self.sig
79
        if method_type is None:
80
            # override 'self' type (first argument)
81
            self_arg = PyrexTypes.CFuncTypeArg("", self_type, None)
82
            self_arg.not_none = True
83
            self_arg.accept_builtin_subtypes = True
84
            method_type = self.build_func_type(sig, self_arg)
85
        self_type.scope.declare_builtin_cfunction(
86
            self.py_name, method_type, self.cname, utility_code=self.utility_code)
87

88

89
class BuiltinProperty:
90
    # read only for now
91
    def __init__(self, py_name, property_type, call_cname,
92
                 exception_value=None, exception_check=None, utility_code=None):
93
        self.py_name = py_name
94
        self.property_type = property_type
95
        self.call_cname = call_cname
96
        self.utility_code = utility_code
97
        self.exception_value = exception_value
98
        self.exception_check = exception_check
99

100
    def declare_in_type(self, self_type):
101
        self_type.scope.declare_cproperty(
102
            self.py_name,
103
            self.property_type,
104
            self.call_cname,
105
            exception_value=self.exception_value,
106
            exception_check=self.exception_check,
107
            utility_code=self.utility_code
108
        )
109

110

111
builtin_function_table = [
112
    # name,        args,   return,  C API func,           py equiv = "*"
113
    BuiltinFunction('abs',        "d",    "d",     "fabs",
114
                    is_strict_signature=True, nogil=True),
115
    BuiltinFunction('abs',        "f",    "f",     "fabsf",
116
                    is_strict_signature=True, nogil=True),
117
    BuiltinFunction('abs',        "i",    "i",     "abs",
118
                    is_strict_signature=True, nogil=True),
119
    BuiltinFunction('abs',        "l",    "l",     "labs",
120
                    is_strict_signature=True, nogil=True),
121
    BuiltinFunction('abs',        None,    None,   "__Pyx_abs_longlong",
122
                utility_code = UtilityCode.load("abs_longlong", "Builtins.c"),
123
                func_type = PyrexTypes.CFuncType(
124
                    PyrexTypes.c_longlong_type, [
125
                        PyrexTypes.CFuncTypeArg("arg", PyrexTypes.c_longlong_type, None)
126
                        ],
127
                    is_strict_signature = True, nogil=True)),
128
    ] + list(
129
        BuiltinFunction('abs',        None,    None,   "/*abs_{}*/".format(t.specialization_name()),
130
                    func_type = PyrexTypes.CFuncType(
131
                        t,
132
                        [PyrexTypes.CFuncTypeArg("arg", t, None)],
133
                        is_strict_signature = True, nogil=True))
134
                            for t in (PyrexTypes.c_uint_type, PyrexTypes.c_ulong_type, PyrexTypes.c_ulonglong_type)
135
             ) + list(
136
        BuiltinFunction('abs',        None,    None,   "__Pyx_c_abs{}".format(t.funcsuffix),
137
                    func_type = PyrexTypes.CFuncType(
138
                        t.real_type, [
139
                            PyrexTypes.CFuncTypeArg("arg", t, None)
140
                            ],
141
                            is_strict_signature = True, nogil=True))
142
                        for t in (PyrexTypes.c_float_complex_type,
143
                                  PyrexTypes.c_double_complex_type,
144
                                  PyrexTypes.c_longdouble_complex_type)
145
                        ) + [
146
    BuiltinFunction('abs',        "O",    "O",     "__Pyx_PyNumber_Absolute",
147
                    utility_code=UtilityCode.load("py_abs", "Builtins.c")),
148
    #('all',       "",     "",      ""),
149
    #('any',       "",     "",      ""),
150
    #('ascii',     "",     "",      ""),
151
    #('bin',       "",     "",      ""),
152
    BuiltinFunction('callable',   "O",    "b",     "__Pyx_PyCallable_Check",
153
                    utility_code = UtilityCode.load("CallableCheck", "ObjectHandling.c")),
154
    BuiltinFunction('chr',        "i",    "O",      "PyUnicode_FromOrdinal", builtin_return_type='str'),
155
    #('cmp', "",   "",     "",      ""), # int PyObject_Cmp(PyObject *o1, PyObject *o2, int *result)
156
    #('compile',   "",     "",      ""), # PyObject* Py_CompileString(    char *str, char *filename, int start)
157
    BuiltinFunction('delattr',    "OO",   "r",     "PyObject_DelAttr"),
158
    BuiltinFunction('dir',        "O",    "O",     "PyObject_Dir"),
159
    BuiltinFunction('divmod',     "ii",   "O",     "__Pyx_divmod_int",
160
                    utility_code=UtilityCode.load("divmod_int", "Builtins.c"),
161
                    is_strict_signature = True),
162
    BuiltinFunction('divmod',     "OO",   "O",     "PyNumber_Divmod"),
163
    BuiltinFunction('exec',       "O",    "O",     "__Pyx_PyExecGlobals",
164
                    utility_code = pyexec_globals_utility_code),
165
    BuiltinFunction('exec',       "OO",   "O",     "__Pyx_PyExec2",
166
                    utility_code = pyexec_utility_code),
167
    BuiltinFunction('exec',       "OOO",  "O",     "__Pyx_PyExec3",
168
                    utility_code = pyexec_utility_code),
169
    #('eval',      "",     "",      ""),
170
    #('execfile',  "",     "",      ""),
171
    #('filter',    "",     "",      ""),
172
    BuiltinFunction('getattr3',   "OOO",  "O",     "__Pyx_GetAttr3",     "getattr",
173
                    utility_code=getattr3_utility_code),  # Pyrex legacy
174
    BuiltinFunction('getattr',    "OOO",  "O",     "__Pyx_GetAttr3",
175
                    utility_code=getattr3_utility_code),
176
    BuiltinFunction('getattr',    "OO",   "O",     "__Pyx_GetAttr",
177
                    utility_code=getattr_utility_code),
178
    BuiltinFunction('hasattr',    "OO",   "b",     "__Pyx_HasAttr",
179
                    utility_code = UtilityCode.load("HasAttr", "Builtins.c")),
180
    BuiltinFunction('hash',       "O",    "h",     "PyObject_Hash"),
181
    #('hex',       "",     "",      ""),
182
    #('id',        "",     "",      ""),
183
    #('input',     "",     "",      ""),
184
    BuiltinFunction('intern',     "O",    "O",     "__Pyx_Intern",
185
                    utility_code = UtilityCode.load("Intern", "Builtins.c")),
186
    BuiltinFunction('isinstance', "OO",   "b",     "PyObject_IsInstance"),
187
    BuiltinFunction('issubclass', "OO",   "b",     "PyObject_IsSubclass"),
188
    BuiltinFunction('iter',       "OO",   "O",     "PyCallIter_New"),
189
    BuiltinFunction('iter',       "O",    "O",     "PyObject_GetIter"),
190
    BuiltinFunction('len',        "O",    "z",     "PyObject_Length"),
191
    BuiltinFunction('locals',     "",     "O",     "__pyx_locals"),
192
    #('map',       "",     "",      ""),
193
    #('max',       "",     "",      ""),
194
    #('min',       "",     "",      ""),
195
    BuiltinFunction('next',       "O",    "O",     "__Pyx_PyIter_Next",
196
                    utility_code = iter_next_utility_code),   # not available in Py2 => implemented here
197
    BuiltinFunction('next',      "OO",    "O",     "__Pyx_PyIter_Next2",
198
                    utility_code = iter_next_utility_code),  # not available in Py2 => implemented here
199
    #('oct',       "",     "",      ""),
200
    #('open',       "ss",   "O",     "PyFile_FromString"),   # not in Py3
201
] + [
202
    BuiltinFunction('ord',        None,    None,   "__Pyx_long_cast",
203
                    func_type=PyrexTypes.CFuncType(
204
                        PyrexTypes.c_long_type, [PyrexTypes.CFuncTypeArg("c", c_type, None)],
205
                        is_strict_signature=True))
206
    for c_type in [PyrexTypes.c_py_ucs4_type, PyrexTypes.c_py_unicode_type]
207
] + [
208
    BuiltinFunction('ord',        None,    None,   "__Pyx_uchar_cast",
209
                    func_type=PyrexTypes.CFuncType(
210
                        PyrexTypes.c_uchar_type, [PyrexTypes.CFuncTypeArg("c", c_type, None)],
211
                        is_strict_signature=True))
212
    for c_type in [PyrexTypes.c_char_type, PyrexTypes.c_schar_type, PyrexTypes.c_uchar_type]
213
] + [
214
    BuiltinFunction('ord',        None,    None,   "__Pyx_PyObject_Ord",
215
                    utility_code=UtilityCode.load_cached("object_ord", "Builtins.c"),
216
                    func_type=PyrexTypes.CFuncType(
217
                        PyrexTypes.c_long_type, [
218
                            PyrexTypes.CFuncTypeArg("c", PyrexTypes.py_object_type, None)
219
                        ],
220
                        exception_value="(long)(Py_UCS4)-1")),
221
    BuiltinFunction('pow',        "OOO",  "O",     "PyNumber_Power"),
222
    BuiltinFunction('pow',        "OO",   "O",     "__Pyx_PyNumber_Power2",
223
                    utility_code = UtilityCode.load("pow2", "Builtins.c")),
224
    #('range',     "",     "",      ""),
225
    #('raw_input', "",     "",      ""),
226
    #('reduce',    "",     "",      ""),
227
    BuiltinFunction('reload',     "O",    "O",     "PyImport_ReloadModule"),
228
    BuiltinFunction('repr',       "O",    "O",     "PyObject_Repr", builtin_return_type='str'),
229
    #('round',     "",     "",      ""),
230
    BuiltinFunction('setattr',    "OOO",  "r",     "PyObject_SetAttr"),
231
    #('sum',       "",     "",      ""),
232
    #('sorted',    "",     "",      ""),
233
    #('type',       "O",    "O",     "PyObject_Type"),
234
    BuiltinFunction('unichr',     "i",    "O",      "PyUnicode_FromOrdinal", builtin_return_type='str'),
235
    #('vars',      "",     "",      ""),
236
    #('zip',       "",     "",      ""),
237
    #  Can't do these easily until we have builtin type entries.
238
    #('typecheck',  "OO",   "i",     "PyObject_TypeCheck", False),
239
    #('issubtype',  "OO",   "i",     "PyType_IsSubtype",   False),
240

241
    # Put in namespace append optimization.
242
    BuiltinFunction('__Pyx_PyObject_Append', "OO",  "O",     "__Pyx_PyObject_Append"),
243

244
    # This is conditionally looked up based on a compiler directive.
245
    BuiltinFunction('__Pyx_Globals',    "",     "O",     "__Pyx_Globals",
246
                    utility_code=globals_utility_code),
247
]
248

249

250
# Builtin types
251
#  bool
252
#  buffer
253
#  classmethod
254
#  dict
255
#  enumerate
256
#  file
257
#  float
258
#  int
259
#  list
260
#  long
261
#  object
262
#  property
263
#  slice
264
#  staticmethod
265
#  super
266
#  str
267
#  tuple
268
#  type
269
#  xrange
270

271
builtin_types_table = [
272

273
    ("type",    "&PyType_Type",     []),
274

275
# This conflicts with the C++ bool type, and unfortunately
276
# C++ is too liberal about PyObject* <-> bool conversions,
277
# resulting in unintuitive runtime behavior and segfaults.
278
#    ("bool",   "&PyBool_Type",     []),
279

280
    ("int",     "&PyLong_Type",     []),
281
    ("float",   "&PyFloat_Type",   []),
282

283
    ("complex", "&PyComplex_Type", [BuiltinAttribute('cval', field_type_name = 'Py_complex'),
284
                                    BuiltinAttribute('real', 'cval.real', field_type = PyrexTypes.c_double_type),
285
                                    BuiltinAttribute('imag', 'cval.imag', field_type = PyrexTypes.c_double_type),
286
                                    ]),
287

288
    ("bytearray", "&PyByteArray_Type", [
289
                                    BuiltinMethod("__mul__",  "Tz",   "T", "__Pyx_PySequence_Multiply",
290
                                                  utility_code=UtilityCode.load("PySequenceMultiply", "ObjectHandling.c")),
291
                                    ]),
292
    ("bytes",   "&PyBytes_Type",   [BuiltinMethod("join",  "TO",   "O", "__Pyx_PyBytes_Join",
293
                                                  utility_code=UtilityCode.load("StringJoin", "StringTools.c")),
294
                                    BuiltinMethod("__mul__",  "Tz",   "T", "__Pyx_PySequence_Multiply",
295
                                                  utility_code=UtilityCode.load("PySequenceMultiply", "ObjectHandling.c")),
296
                                    ]),
297
    ("str",     "&PyUnicode_Type", [BuiltinMethod("__contains__",  "TO",   "b", "PyUnicode_Contains"),
298
                                    BuiltinMethod("join",  "TO",   "T", "PyUnicode_Join"),
299
                                    BuiltinMethod("__mul__",  "Tz",   "T", "__Pyx_PySequence_Multiply",
300
                                                  utility_code=UtilityCode.load("PySequenceMultiply", "ObjectHandling.c")),
301
                                    ]),
302

303
    ("tuple",  "&PyTuple_Type",    [BuiltinMethod("__mul__", "Tz", "T", "__Pyx_PySequence_Multiply",
304
                                                  utility_code=UtilityCode.load("PySequenceMultiply", "ObjectHandling.c")),
305
                                    ]),
306

307
    ("list",   "&PyList_Type",     [BuiltinMethod("insert",  "TzO",  "r", "PyList_Insert"),
308
                                    BuiltinMethod("reverse", "T",    "r", "PyList_Reverse"),
309
                                    BuiltinMethod("append",  "TO",   "r", "__Pyx_PyList_Append",
310
                                                  utility_code=UtilityCode.load("ListAppend", "Optimize.c")),
311
                                    BuiltinMethod("extend",  "TO",   "r", "__Pyx_PyList_Extend",
312
                                                  utility_code=UtilityCode.load("ListExtend", "Optimize.c")),
313
                                    BuiltinMethod("__mul__",  "Tz",   "T", "__Pyx_PySequence_Multiply",
314
                                                  utility_code=UtilityCode.load("PySequenceMultiply", "ObjectHandling.c")),
315
                                    ]),
316

317
    ("dict",   "&PyDict_Type",     [BuiltinMethod("__contains__",  "TO",   "b", "PyDict_Contains"),
318
                                    BuiltinMethod("has_key",       "TO",   "b", "PyDict_Contains"),
319
                                    BuiltinMethod("items",  "T",   "O", "__Pyx_PyDict_Items",
320
                                                  utility_code=UtilityCode.load("py_dict_items", "Builtins.c")),
321
                                    BuiltinMethod("keys",   "T",   "O", "__Pyx_PyDict_Keys",
322
                                                  utility_code=UtilityCode.load("py_dict_keys", "Builtins.c")),
323
                                    BuiltinMethod("values", "T",   "O", "__Pyx_PyDict_Values",
324
                                                  utility_code=UtilityCode.load("py_dict_values", "Builtins.c")),
325
                                    BuiltinMethod("iteritems",  "T",   "O", "__Pyx_PyDict_IterItems",
326
                                                  utility_code=UtilityCode.load("py_dict_iteritems", "Builtins.c")),
327
                                    BuiltinMethod("iterkeys",   "T",   "O", "__Pyx_PyDict_IterKeys",
328
                                                  utility_code=UtilityCode.load("py_dict_iterkeys", "Builtins.c")),
329
                                    BuiltinMethod("itervalues", "T",   "O", "__Pyx_PyDict_IterValues",
330
                                                  utility_code=UtilityCode.load("py_dict_itervalues", "Builtins.c")),
331
                                    BuiltinMethod("viewitems",  "T",   "O", "__Pyx_PyDict_ViewItems",
332
                                                  utility_code=UtilityCode.load("py_dict_viewitems", "Builtins.c")),
333
                                    BuiltinMethod("viewkeys",   "T",   "O", "__Pyx_PyDict_ViewKeys",
334
                                                  utility_code=UtilityCode.load("py_dict_viewkeys", "Builtins.c")),
335
                                    BuiltinMethod("viewvalues", "T",   "O", "__Pyx_PyDict_ViewValues",
336
                                                  utility_code=UtilityCode.load("py_dict_viewvalues", "Builtins.c")),
337
                                    BuiltinMethod("clear",  "T",   "r", "__Pyx_PyDict_Clear",
338
                                                  utility_code=UtilityCode.load("py_dict_clear", "Optimize.c")),
339
                                    BuiltinMethod("copy",   "T",   "T", "PyDict_Copy")]),
340

341
    ("slice",  "&PySlice_Type",    [BuiltinAttribute('start'),
342
                                    BuiltinAttribute('stop'),
343
                                    BuiltinAttribute('step'),
344
                                    ]),
345
#    ("file",   "&PyFile_Type",     []),  # not in Py3
346

347
    ("set",      "&PySet_Type",    [BuiltinMethod("clear",   "T",  "r", "PySet_Clear"),
348
                                    # discard() and remove() have a special treatment for unhashable values
349
                                    BuiltinMethod("discard", "TO", "r", "__Pyx_PySet_Discard",
350
                                                  utility_code=UtilityCode.load("py_set_discard", "Optimize.c")),
351
                                    BuiltinMethod("remove",  "TO", "r", "__Pyx_PySet_Remove",
352
                                                  utility_code=UtilityCode.load("py_set_remove", "Optimize.c")),
353
                                    # update is actually variadic (see Github issue #1645)
354
#                                    BuiltinMethod("update",     "TO", "r", "__Pyx_PySet_Update",
355
#                                                  utility_code=UtilityCode.load_cached("PySet_Update", "Builtins.c")),
356
                                    BuiltinMethod("add",     "TO", "r", "PySet_Add"),
357
                                    BuiltinMethod("pop",     "T",  "O", "PySet_Pop")]),
358
    ("frozenset", "&PyFrozenSet_Type", []),
359
    ("BaseException", "((PyTypeObject*)PyExc_BaseException)", []),
360
    ("Exception", "((PyTypeObject*)PyExc_Exception)", []),
361
    ("StopAsyncIteration", "((PyTypeObject*)PyExc_StopAsyncIteration)", []),
362
    ("memoryview", "&PyMemoryView_Type", [
363
        # TODO - format would be nice, but hard to get
364
        # __len__ can be accessed through a direct lookup of the buffer (but probably in Optimize.c)
365
        # error checking would ideally be limited api only
366
        BuiltinProperty("ndim", PyrexTypes.c_int_type, '__Pyx_PyMemoryView_Get_ndim',
367
                        exception_value=-1, exception_check=True,
368
                        utility_code=TempitaUtilityCode.load_cached(
369
                            "memoryview_get_from_buffer", "Builtins.c",
370
                            context=dict(name="ndim")
371
                        )
372
        ),
373
        BuiltinProperty("readonly", PyrexTypes.c_bint_type, '__Pyx_PyMemoryView_Get_readonly',
374
                        exception_value=-1, exception_check=True,
375
                        utility_code=TempitaUtilityCode.load_cached(
376
                            "memoryview_get_from_buffer", "Builtins.c",
377
                            context=dict(name="readonly")
378
                        )
379
        ),
380
        BuiltinProperty("itemsize", PyrexTypes.c_py_ssize_t_type, '__Pyx_PyMemoryView_Get_itemsize',
381
                        exception_value=-1, exception_check=True,
382
                        utility_code=TempitaUtilityCode.load_cached(
383
                            "memoryview_get_from_buffer", "Builtins.c",
384
                            context=dict(name="itemsize")
385
                        )
386
        )]
387
    )
388
]
389

390

391
types_that_construct_their_instance = frozenset({
392
    # some builtin types do not always return an instance of
393
    # themselves - these do:
394
    'type', 'bool', 'int', 'float', 'complex',
395
    'bytes', 'unicode', 'bytearray', 'str',
396
    'tuple', 'list', 'dict', 'set', 'frozenset',
397
    'memoryview'
398
})
399

400

401
inferred_method_return_types = {
402
    'complex': dict(
403
        conjugate='complex',
404
    ),
405
    'int': dict(
406
        bit_length='T',
407
        bit_count='T',
408
        to_bytes='bytes',
409
        from_bytes='T',  # classmethod
410
        as_integer_ratio='tuple[int,int]',
411
        is_integer='bint',
412
    ),
413
    'float': dict(
414
        as_integer_ratio='tuple[int,int]',
415
        is_integer='bint',
416
        hex='str',
417
        fromhex='T',  # classmethod
418
    ),
419
    'list': dict(
420
        index='Py_ssize_t',
421
        count='Py_ssize_t',
422
    ),
423
    'str': dict(
424
        capitalize='T',
425
        casefold='T',
426
        center='T',
427
        count='Py_ssize_t',
428
        encode='bytes',
429
        endswith='bint',
430
        expandtabs='T',
431
        find='Py_ssize_t',
432
        format='T',
433
        format_map='T',
434
        index='Py_ssize_t',
435
        isalnum='bint',
436
        isalpha='bint',
437
        isascii='bint',
438
        isdecimal='bint',
439
        isdigit='bint',
440
        isidentifier='bint',
441
        islower='bint',
442
        isnumeric='bint',
443
        isprintable='bint',
444
        isspace='bint',
445
        istitle='bint',
446
        isupper='bint',
447
        join='T',
448
        ljust='T',
449
        lower='T',
450
        lstrip='T',
451
        maketrans='dict[int,object]',  # staticmethod
452
        partition='tuple[T,T,T]',
453
        removeprefix='T',
454
        removesuffix='T',
455
        replace='T',
456
        rfind='Py_ssize_t',
457
        rindex='Py_ssize_t',
458
        rjust='T',
459
        rpartition='tuple[T,T,T]',
460
        rsplit='list[T]',
461
        rstrip='T',
462
        split='list[T]',
463
        splitlines='list[T]',
464
        startswith='bint',
465
        strip='T',
466
        swapcase='T',
467
        title='T',
468
        translate='T',
469
        upper='T',
470
        zfill='T',
471
    ),
472
    'bytes': dict(
473
        hex='str',
474
        fromhex='T',  # classmethod
475
        count='Py_ssize_t',
476
        removeprefix='T',
477
        removesuffix='T',
478
        decode='str',
479
        endswith='bint',
480
        find='Py_ssize_t',
481
        index='Py_ssize_t',
482
        join='T',
483
        maketrans='bytes',  # staticmethod
484
        partition='tuple[T,T,T]',
485
        replace='T',
486
        rfind='Py_ssize_t',
487
        rindex='Py_ssize_t',
488
        rpartition='tuple[T,T,T]',
489
        startswith='bint',
490
        translate='T',
491
        center='T',
492
        ljust='T',
493
        lstrip='T',
494
        rjust='T',
495
        rsplit='list[T]',
496
        rstrip='T',
497
        split='list[T]',
498
        strip='T',
499
        capitalize='T',
500
        expandtabs='T',
501
        isalnum='bint',
502
        isalpha='bint',
503
        isascii='bint',
504
        isdigit='bint',
505
        islower='bint',
506
        isspace='bint',
507
        istitle='bint',
508
        isupper='bint',
509
        lower='T',
510
        splitlines='list[T]',
511
        swapcase='T',
512
        title='T',
513
        upper='T',
514
        zfill='T',
515
    ),
516
    'bytearray': dict(
517
        # Inherited from 'bytes' below.
518
    ),
519
    'memoryview': dict(
520
        tobytes='bytes',
521
        hex='str',
522
        tolist='list',
523
        toreadonly='T',
524
        cast='T',
525
    ),
526
    'set': dict(
527
        isdisjoint='bint',
528
        isubset='bint',
529
        issuperset='bint',
530
        union='T',
531
        intersection='T',
532
        difference='T',
533
        symmetric_difference='T',
534
        copy='T',
535
    ),
536
    'frozenset': dict(
537
        # Inherited from 'set' below.
538
    ),
539
    'dict': dict(
540
        copy='T',
541
    ),
542
}
543

544
inferred_method_return_types['bytearray'].update(inferred_method_return_types['bytes'])
545
inferred_method_return_types['frozenset'].update(inferred_method_return_types['set'])
546

547

548
def find_return_type_of_builtin_method(builtin_type, method_name):
549
    type_name = builtin_type.name
550
    if type_name in inferred_method_return_types:
551
        methods = inferred_method_return_types[type_name]
552
        if method_name in methods:
553
            return_type_name = methods[method_name]
554
            if '[' in return_type_name:
555
                # TODO: Keep the "[...]" part when we add support for generics.
556
                return_type_name = return_type_name.partition('[')[0]
557
            if return_type_name == 'T':
558
                return builtin_type
559
            if 'T' in return_type_name:
560
                return_type_name = return_type_name.replace('T', builtin_type.name)
561
            if return_type_name == 'bint':
562
                return PyrexTypes.c_bint_type
563
            elif return_type_name == 'Py_ssize_t':
564
                return PyrexTypes.c_py_ssize_t_type
565
            return builtin_scope.lookup(return_type_name).type
566
    return PyrexTypes.py_object_type
567

568

569
builtin_structs_table = [
570
    ('Py_buffer', 'Py_buffer',
571
     [("buf",        PyrexTypes.c_void_ptr_type),
572
      ("obj",        PyrexTypes.py_object_type),
573
      ("len",        PyrexTypes.c_py_ssize_t_type),
574
      ("itemsize",   PyrexTypes.c_py_ssize_t_type),
575
      ("readonly",   PyrexTypes.c_bint_type),
576
      ("ndim",       PyrexTypes.c_int_type),
577
      ("format",     PyrexTypes.c_char_ptr_type),
578
      ("shape",      PyrexTypes.c_py_ssize_t_ptr_type),
579
      ("strides",    PyrexTypes.c_py_ssize_t_ptr_type),
580
      ("suboffsets", PyrexTypes.c_py_ssize_t_ptr_type),
581
      ("smalltable", PyrexTypes.CArrayType(PyrexTypes.c_py_ssize_t_type, 2)),
582
      ("internal",   PyrexTypes.c_void_ptr_type),
583
      ]),
584
    ('Py_complex', 'Py_complex',
585
     [('real', PyrexTypes.c_double_type),
586
      ('imag', PyrexTypes.c_double_type),
587
      ])
588
]
589

590
# set up builtin scope
591

592
builtin_scope = BuiltinScope()
593

594
def init_builtin_funcs():
595
    for bf in builtin_function_table:
596
        bf.declare_in_scope(builtin_scope)
597

598
builtin_types = {}
599

600
def init_builtin_types():
601
    global builtin_types
602
    for name, cname, methods in builtin_types_table:
603
        if name == 'frozenset':
604
            objstruct_cname = 'PySetObject'
605
        elif name == 'bytearray':
606
            objstruct_cname = 'PyByteArrayObject'
607
        elif name == 'int':
608
            objstruct_cname = 'PyLongObject'
609
        elif name == 'str':
610
            objstruct_cname = 'PyUnicodeObject'
611
        elif name == 'bool':
612
            objstruct_cname = None
613
        elif name == 'BaseException':
614
            objstruct_cname = "PyBaseExceptionObject"
615
        elif name == 'Exception':
616
            objstruct_cname = "PyBaseExceptionObject"
617
        elif name == 'StopAsyncIteration':
618
            objstruct_cname = "PyBaseExceptionObject"
619
        else:
620
            objstruct_cname = 'Py%sObject' % name.capitalize()
621
        type_class = PyrexTypes.BuiltinObjectType
622
        if name in ['dict', 'list', 'set', 'frozenset']:
623
            type_class = PyrexTypes.BuiltinTypeConstructorObjectType
624
        elif name == 'tuple':
625
            type_class = PyrexTypes.PythonTupleTypeConstructor
626
        the_type = builtin_scope.declare_builtin_type(
627
            name, cname, objstruct_cname=objstruct_cname, type_class=type_class)
628
        builtin_types[name] = the_type
629
        for method in methods:
630
            method.declare_in_type(the_type)
631

632

633
def init_builtin_structs():
634
    for name, cname, attribute_types in builtin_structs_table:
635
        scope = StructOrUnionScope(name)
636
        for attribute_name, attribute_type in attribute_types:
637
            scope.declare_var(attribute_name, attribute_type, None,
638
                              attribute_name, allow_pyobject=True)
639
        builtin_scope.declare_struct_or_union(
640
            name, "struct", scope, 1, None, cname = cname)
641

642

643
def init_builtins():
644
    #Errors.init_thread()  # hopefully not needed - we should not emit warnings ourselves
645
    init_builtin_structs()
646
    init_builtin_types()
647
    init_builtin_funcs()
648

649
    entry = builtin_scope.declare_var(
650
        '__debug__', PyrexTypes.c_const_type(PyrexTypes.c_bint_type),
651
        pos=None, cname='__pyx_assertions_enabled()', is_cdef=True)
652
    entry.utility_code = UtilityCode.load_cached("AssertionsEnabled", "Exceptions.c")
653

654
    global type_type, list_type, tuple_type, dict_type, set_type, frozenset_type, slice_type
655
    global bytes_type, unicode_type, bytearray_type
656
    global float_type, int_type, bool_type, complex_type
657
    global memoryview_type, py_buffer_type
658
    global sequence_types
659
    type_type  = builtin_scope.lookup('type').type
660
    list_type  = builtin_scope.lookup('list').type
661
    tuple_type = builtin_scope.lookup('tuple').type
662
    dict_type  = builtin_scope.lookup('dict').type
663
    set_type   = builtin_scope.lookup('set').type
664
    frozenset_type = builtin_scope.lookup('frozenset').type
665
    slice_type   = builtin_scope.lookup('slice').type
666

667
    bytes_type = builtin_scope.lookup('bytes').type
668
    unicode_type = builtin_scope.lookup('str').type
669
    bytearray_type = builtin_scope.lookup('bytearray').type
670
    memoryview_type = builtin_scope.lookup('memoryview').type
671

672
    float_type = builtin_scope.lookup('float').type
673
    int_type = builtin_scope.lookup('int').type
674
    bool_type  = builtin_scope.lookup('bool').type
675
    complex_type  = builtin_scope.lookup('complex').type
676

677
    sequence_types = (
678
        list_type,
679
        tuple_type,
680
        bytes_type,
681
        unicode_type,
682
        bytearray_type,
683
        memoryview_type,
684
    )
685

686
    # Set up type inference links between equivalent Python/C types
687
    bool_type.equivalent_type = PyrexTypes.c_bint_type
688
    PyrexTypes.c_bint_type.equivalent_type = bool_type
689

690
    float_type.equivalent_type = PyrexTypes.c_double_type
691
    PyrexTypes.c_double_type.equivalent_type = float_type
692

693
    complex_type.equivalent_type = PyrexTypes.c_double_complex_type
694
    PyrexTypes.c_double_complex_type.equivalent_type = complex_type
695

696
    py_buffer_type = builtin_scope.lookup('Py_buffer').type
697

698

699
init_builtins()
700

701
##############################
702
# Support for a few standard library modules that Cython understands (currently typing and dataclasses)
703
##############################
704
_known_module_scopes = {}
705

706
def get_known_standard_library_module_scope(module_name):
707
    mod = _known_module_scopes.get(module_name)
708
    if mod:
709
        return mod
710

711
    if module_name == "typing":
712
        mod = ModuleScope(module_name, None, None)
713
        for name, tp in [
714
                ('Dict', dict_type),
715
                ('List', list_type),
716
                ('Tuple', tuple_type),
717
                ('Set', set_type),
718
                ('FrozenSet', frozenset_type),
719
                ]:
720
            name = EncodedString(name)
721
            entry = mod.declare_type(name, tp, pos = None)
722
            var_entry = Entry(name, None, PyrexTypes.py_object_type)
723
            var_entry.is_pyglobal = True
724
            var_entry.is_variable = True
725
            var_entry.scope = mod
726
            entry.as_variable = var_entry
727
            entry.known_standard_library_import = "%s.%s" % (module_name, name)
728

729
        for name in ['ClassVar', 'Optional']:
730
            name = EncodedString(name)
731
            indexed_type = PyrexTypes.SpecialPythonTypeConstructor(EncodedString("typing."+name))
732
            entry = mod.declare_type(name, indexed_type, pos = None)
733
            var_entry = Entry(name, None, PyrexTypes.py_object_type)
734
            var_entry.is_pyglobal = True
735
            var_entry.is_variable = True
736
            var_entry.scope = mod
737
            entry.as_variable = var_entry
738
            entry.known_standard_library_import = "%s.%s" % (module_name, name)
739
        _known_module_scopes[module_name] = mod
740
    elif module_name == "dataclasses":
741
        mod = ModuleScope(module_name, None, None)
742
        indexed_type = PyrexTypes.SpecialPythonTypeConstructor(EncodedString("dataclasses.InitVar"))
743
        initvar_string = EncodedString("InitVar")
744
        entry = mod.declare_type(initvar_string, indexed_type, pos = None)
745
        var_entry = Entry(initvar_string, None, PyrexTypes.py_object_type)
746
        var_entry.is_pyglobal = True
747
        var_entry.scope = mod
748
        entry.as_variable = var_entry
749
        entry.known_standard_library_import = "%s.InitVar" % module_name
750
        for name in ["dataclass", "field"]:
751
            mod.declare_var(EncodedString(name), PyrexTypes.py_object_type, pos=None)
752
        _known_module_scopes[module_name] = mod
753
    elif module_name == "functools":
754
        mod = ModuleScope(module_name, None, None)
755
        for name in ["total_ordering"]:
756
            mod.declare_var(EncodedString(name), PyrexTypes.py_object_type, pos=None)
757
        _known_module_scopes[module_name] = mod
758

759
    return mod
760

761

762
def get_known_standard_library_entry(qualified_name):
763
    name_parts = qualified_name.split(".")
764
    module_name = EncodedString(name_parts[0])
765
    rest = name_parts[1:]
766

767
    if len(rest) > 1:  # for now, we don't know how to deal with any nested modules
768
        return None
769

770
    mod = get_known_standard_library_module_scope(module_name)
771

772
    # eventually handle more sophisticated multiple lookups if needed
773
    if mod and rest:
774
        return mod.lookup_here(rest[0])
775
    return None
776

777

778
def exprnode_to_known_standard_library_name(node, env):
779
    qualified_name_parts = []
780
    known_name = None
781
    while node.is_attribute:
782
        qualified_name_parts.append(node.attribute)
783
        node = node.obj
784
    if node.is_name:
785
        entry = env.lookup(node.name)
786
        if entry and entry.known_standard_library_import:
787
            if get_known_standard_library_entry(
788
                    entry.known_standard_library_import):
789
                known_name = entry.known_standard_library_import
790
            else:
791
                standard_env = get_known_standard_library_module_scope(
792
                    entry.known_standard_library_import)
793
                if standard_env:
794
                    qualified_name_parts.append(standard_env.name)
795
                    known_name = ".".join(reversed(qualified_name_parts))
796
    return known_name
797

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.