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
13
# C-level implementations of builtin types, functions and methods
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")
23
# mapping from builtins to their C-level equivalents
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,
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
38
def build_func_type(self, sig=None, self_arg=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]
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
57
def declare_in_type(self, self_type):
58
if self.field_type_name is not None:
60
field_type = builtin_scope.lookup(self.field_type_name).type
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
67
class BuiltinFunction(_BuiltinOverride):
68
def declare_in_scope(self, scope):
69
func_type, sig = self.func_type, self.sig
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)
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)
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
100
def declare_in_type(self, self_type):
101
self_type.scope.declare_cproperty(
105
exception_value=self.exception_value,
106
exception_check=self.exception_check,
107
utility_code=self.utility_code
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)
127
is_strict_signature = True, nogil=True)),
129
BuiltinFunction('abs', None, None, "/*abs_{}*/".format(t.specialization_name()),
130
func_type = PyrexTypes.CFuncType(
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)
136
BuiltinFunction('abs', None, None, "__Pyx_c_abs{}".format(t.funcsuffix),
137
func_type = PyrexTypes.CFuncType(
139
PyrexTypes.CFuncTypeArg("arg", t, None)
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)
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', "", "", ""),
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
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]
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]
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)
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),
241
# Put in namespace append optimization.
242
BuiltinFunction('__Pyx_PyObject_Append', "OO", "O", "__Pyx_PyObject_Append"),
244
# This is conditionally looked up based on a compiler directive.
245
BuiltinFunction('__Pyx_Globals', "", "O", "__Pyx_Globals",
246
utility_code=globals_utility_code),
271
builtin_types_table = [
273
("type", "&PyType_Type", []),
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", []),
280
("int", "&PyLong_Type", []),
281
("float", "&PyFloat_Type", []),
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),
288
("bytearray", "&PyByteArray_Type", [
289
BuiltinMethod("__mul__", "Tz", "T", "__Pyx_PySequence_Multiply",
290
utility_code=UtilityCode.load("PySequenceMultiply", "ObjectHandling.c")),
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")),
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")),
303
("tuple", "&PyTuple_Type", [BuiltinMethod("__mul__", "Tz", "T", "__Pyx_PySequence_Multiply",
304
utility_code=UtilityCode.load("PySequenceMultiply", "ObjectHandling.c")),
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")),
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")]),
341
("slice", "&PySlice_Type", [BuiltinAttribute('start'),
342
BuiltinAttribute('stop'),
343
BuiltinAttribute('step'),
345
# ("file", "&PyFile_Type", []), # not in Py3
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")
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")
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")
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',
401
inferred_method_return_types = {
409
from_bytes='T', # classmethod
410
as_integer_ratio='tuple[int,int]',
414
as_integer_ratio='tuple[int,int]',
417
fromhex='T', # classmethod
451
maketrans='dict[int,object]', # staticmethod
452
partition='tuple[T,T,T]',
459
rpartition='tuple[T,T,T]',
463
splitlines='list[T]',
474
fromhex='T', # classmethod
483
maketrans='bytes', # staticmethod
484
partition='tuple[T,T,T]',
488
rpartition='tuple[T,T,T]',
510
splitlines='list[T]',
517
# Inherited from 'bytes' below.
533
symmetric_difference='T',
537
# Inherited from 'set' below.
544
inferred_method_return_types['bytearray'].update(inferred_method_return_types['bytes'])
545
inferred_method_return_types['frozenset'].update(inferred_method_return_types['set'])
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':
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
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),
584
('Py_complex', 'Py_complex',
585
[('real', PyrexTypes.c_double_type),
586
('imag', PyrexTypes.c_double_type),
590
# set up builtin scope
592
builtin_scope = BuiltinScope()
594
def init_builtin_funcs():
595
for bf in builtin_function_table:
596
bf.declare_in_scope(builtin_scope)
600
def init_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'
608
objstruct_cname = 'PyLongObject'
610
objstruct_cname = 'PyUnicodeObject'
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"
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)
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)
644
#Errors.init_thread() # hopefully not needed - we should not emit warnings ourselves
645
init_builtin_structs()
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")
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
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
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
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
690
float_type.equivalent_type = PyrexTypes.c_double_type
691
PyrexTypes.c_double_type.equivalent_type = float_type
693
complex_type.equivalent_type = PyrexTypes.c_double_complex_type
694
PyrexTypes.c_double_complex_type.equivalent_type = complex_type
696
py_buffer_type = builtin_scope.lookup('Py_buffer').type
701
##############################
702
# Support for a few standard library modules that Cython understands (currently typing and dataclasses)
703
##############################
704
_known_module_scopes = {}
706
def get_known_standard_library_module_scope(module_name):
707
mod = _known_module_scopes.get(module_name)
711
if module_name == "typing":
712
mod = ModuleScope(module_name, None, None)
716
('Tuple', tuple_type),
718
('FrozenSet', frozenset_type),
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)
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
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:]
767
if len(rest) > 1: # for now, we don't know how to deal with any nested modules
770
mod = get_known_standard_library_module_scope(module_name)
772
# eventually handle more sophisticated multiple lookups if needed
774
return mod.lookup_here(rest[0])
778
def exprnode_to_known_standard_library_name(node, env):
779
qualified_name_parts = []
781
while node.is_attribute:
782
qualified_name_parts.append(node.attribute)
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
791
standard_env = get_known_standard_library_module_scope(
792
entry.known_standard_library_import)
794
qualified_name_parts.append(standard_env.name)
795
known_name = ".".join(reversed(qualified_name_parts))